drafter-mcp 0.26.1 → 0.26.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/drafter-mcp.js +1252 -384
- package/package.json +1 -1
package/drafter-mcp.js
CHANGED
|
@@ -7,7 +7,7 @@ import { join, posix, win32 } from "node:path";
|
|
|
7
7
|
import { parseArgs } from "node:util";
|
|
8
8
|
import { constants } from "node:fs";
|
|
9
9
|
import { lstat, open, readdir, realpath, stat } from "node:fs/promises";
|
|
10
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
10
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/chunk-vYduTEsO.mjs
|
|
11
11
|
var __create = Object.create;
|
|
12
12
|
var __defProp = Object.defineProperty;
|
|
13
13
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -38,7 +38,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
38
38
|
value: mod,
|
|
39
39
|
enumerable: true
|
|
40
40
|
}) : target, mod));
|
|
41
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
41
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/dialects-CDpMbily.mjs
|
|
42
42
|
/**
|
|
43
43
|
* Canonical `$schema` URIs per supported dialect (http + https variants, trailing-`#` stripped).
|
|
44
44
|
*/
|
|
@@ -7426,6 +7426,7 @@ const ServerResultSchema = union([
|
|
|
7426
7426
|
ListToolsResultSchema,
|
|
7427
7427
|
SubscriptionsListenResultSchema
|
|
7428
7428
|
]);
|
|
7429
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+core@2.4.0/node_modules/@modelcontextprotocol/core/dist/auth-UMQCo-ad.mjs
|
|
7429
7430
|
/**
|
|
7430
7431
|
* Reusable URL validation that disallows `javascript:` scheme
|
|
7431
7432
|
*/
|
|
@@ -7628,7 +7629,7 @@ const OAuthTokenRevocationRequestSchema = object({
|
|
|
7628
7629
|
token: string(),
|
|
7629
7630
|
token_type_hint: string().optional()
|
|
7630
7631
|
}).strip();
|
|
7631
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
7632
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/src-DdvbAHrR.mjs
|
|
7632
7633
|
/**
|
|
7633
7634
|
* Cross-bundle `instanceof` support for the SDK error classes.
|
|
7634
7635
|
*
|
|
@@ -11889,25 +11890,22 @@ const X_MCP_HEADER_KEY = "x-mcp-header";
|
|
|
11889
11890
|
*/
|
|
11890
11891
|
const RFC9110_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
11891
11892
|
/**
|
|
11892
|
-
* JSON Schema `type` values the spec admits on an `x-mcp-header` property
|
|
11893
|
-
*
|
|
11894
|
-
*
|
|
11895
|
-
* `number
|
|
11896
|
-
* `
|
|
11897
|
-
* parameters and expects the client to mirror them, so `number` is accepted
|
|
11898
|
-
* here so that the conformance gate passes; the discrepancy is tracked
|
|
11899
|
-
* upstream. Everything else (`object`, `array`, `null`, absent) is rejected.
|
|
11893
|
+
* JSON Schema `type` values the spec admits on an `x-mcp-header` property:
|
|
11894
|
+
* `integer`, `string` and `boolean`. `number` is explicitly not permitted
|
|
11895
|
+
* (2026-07-28 Streamable HTTP, "Schema Extension"), so a tool that annotates a
|
|
11896
|
+
* `number`-typed property is invalid (the server still checks its headers).
|
|
11897
|
+
* Everything else (`object`, `array`, `null`, absent) is rejected too.
|
|
11900
11898
|
*/
|
|
11901
11899
|
const PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
11902
11900
|
"string",
|
|
11903
11901
|
"integer",
|
|
11904
|
-
"boolean"
|
|
11905
|
-
"number"
|
|
11902
|
+
"boolean"
|
|
11906
11903
|
]);
|
|
11907
11904
|
/**
|
|
11908
11905
|
* Scan a tool's JSON-serialized `inputSchema` for `x-mcp-header` declarations
|
|
11909
11906
|
* and validate every constraint the spec places on them. Returns either the
|
|
11910
|
-
* collected declarations (possibly empty) or the first violated constraint
|
|
11907
|
+
* collected declarations (possibly empty) or the first violated constraint
|
|
11908
|
+
* (with the declarations too, when `number`-typed declarations are the only fault).
|
|
11911
11909
|
*
|
|
11912
11910
|
* The walk descends through `properties` at any depth (the spec's "any nesting
|
|
11913
11911
|
* depth" clause). The static-reachability MUST is enforced as a structural
|
|
@@ -11920,6 +11918,7 @@ const PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
|
11920
11918
|
function scanXMcpHeaderDeclarations(inputSchema) {
|
|
11921
11919
|
const declarations = [];
|
|
11922
11920
|
const seenLower = /* @__PURE__ */ new Map();
|
|
11921
|
+
let numberFault;
|
|
11923
11922
|
const visit = (node, path, reachable) => {
|
|
11924
11923
|
if (node === null || typeof node !== "object") return void 0;
|
|
11925
11924
|
const schema = node;
|
|
@@ -11929,7 +11928,11 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
11929
11928
|
if (typeof raw !== "string" || raw.length === 0) return `${pathName(path)}: x-mcp-header MUST be a non-empty string`;
|
|
11930
11929
|
if (!RFC9110_TOKEN.test(raw)) return `${pathName(path)}: x-mcp-header '${raw}' is not a valid RFC 9110 token (no spaces, control characters or HTTP delimiters)`;
|
|
11931
11930
|
const type = typeof schema.type === "string" ? schema.type : void 0;
|
|
11932
|
-
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type))
|
|
11931
|
+
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) {
|
|
11932
|
+
const fault$1 = `${pathName(path)}: x-mcp-header is only permitted on primitive-typed properties (string, integer, boolean); got ${type ?? "<none>"}`;
|
|
11933
|
+
if (type !== "number") return fault$1;
|
|
11934
|
+
numberFault ??= fault$1;
|
|
11935
|
+
}
|
|
11933
11936
|
const lower = raw.toLowerCase();
|
|
11934
11937
|
const prior = seenLower.get(lower);
|
|
11935
11938
|
if (prior !== void 0) return `x-mcp-header '${raw}' is not case-insensitively unique (also declared as '${prior}')`;
|
|
@@ -11956,12 +11959,17 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
11956
11959
|
}
|
|
11957
11960
|
};
|
|
11958
11961
|
const fault = visit(inputSchema, [], true);
|
|
11959
|
-
|
|
11962
|
+
if (fault !== void 0) return {
|
|
11963
|
+
valid: false,
|
|
11964
|
+
reason: numberFault ?? fault
|
|
11965
|
+
};
|
|
11966
|
+
return numberFault === void 0 ? {
|
|
11960
11967
|
valid: true,
|
|
11961
11968
|
declarations
|
|
11962
11969
|
} : {
|
|
11963
11970
|
valid: false,
|
|
11964
|
-
reason:
|
|
11971
|
+
reason: numberFault,
|
|
11972
|
+
declarations
|
|
11965
11973
|
};
|
|
11966
11974
|
}
|
|
11967
11975
|
/**
|
|
@@ -12003,8 +12011,115 @@ const OBJECT_VALUED_SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
12003
12011
|
function pathName(path) {
|
|
12004
12012
|
return path.length === 0 ? "<root>" : path.join(".");
|
|
12005
12013
|
}
|
|
12014
|
+
/**
|
|
12015
|
+
* Inbound HTTP request classification and the inbound validation ladder
|
|
12016
|
+
* (protocol revision 2026-07-28).
|
|
12017
|
+
*
|
|
12018
|
+
* `classifyInboundRequest` is the body-primary era predicate for an HTTP
|
|
12019
|
+
* entry that serves both protocol eras on one endpoint. It is evaluated
|
|
12020
|
+
* exactly once, at the entry boundary, on the already-parsed request body:
|
|
12021
|
+
*
|
|
12022
|
+
* - `initialize` is a legacy-era request by definition (the modern era has no
|
|
12023
|
+
* `initialize` handshake) — unless it carries a valid envelope claim naming
|
|
12024
|
+
* a modern revision, in which case the claim wins and the request is
|
|
12025
|
+
* classified like any other enveloped request (the modern era then answers
|
|
12026
|
+
* it with method-not-found, exactly like every other method it does not
|
|
12027
|
+
* define).
|
|
12028
|
+
* - A request whose `params._meta` carries the reserved protocol-version key
|
|
12029
|
+
* claims the per-request envelope mechanism and classifies into the era the
|
|
12030
|
+
* named revision belongs to (a malformed envelope behind a present claim is
|
|
12031
|
+
* a validation error, never a silent fall back to legacy handling).
|
|
12032
|
+
* - A request without a claim is legacy-era traffic.
|
|
12033
|
+
* - The `MCP-Protocol-Version` header is a cross-check only *for
|
|
12034
|
+
* classification*: it never upgrades or downgrades a body-derived
|
|
12035
|
+
* classification, and a disagreement between header and body is an explicit
|
|
12036
|
+
* ladder outcome. Its absence likewise never changes the era — but the spec
|
|
12037
|
+
* requires the header on every modern *request* POST, so a
|
|
12038
|
+
* modern-classified request that omits it is refused one rung later, by
|
|
12039
|
+
* {@linkcode validateStandardRequestHeaders}, not here. Notification POSTs
|
|
12040
|
+
* are exempt (see the next bullet), and that rung enforces presence on
|
|
12041
|
+
* requests only.
|
|
12042
|
+
* - Notifications carry no envelope claim of their own under the current
|
|
12043
|
+
* spec, so for notification POSTs without a body claim the modern header is
|
|
12044
|
+
* determinative; the `Mcp-Method` header is validated against the body when
|
|
12045
|
+
* the message classifies modern and is never enforced on legacy traffic.
|
|
12046
|
+
* A notification that does carry a claim is treated body-primary like a
|
|
12047
|
+
* request, and a malformed claim is rejected the same way a request's
|
|
12048
|
+
* malformed claim is — never silently resolved against the header.
|
|
12049
|
+
* The notification-POST header cross-checks here are an SDK-defensive
|
|
12050
|
+
* posture, not a spec requirement: the spec leaves header rules for posted
|
|
12051
|
+
* notifications undefined (core client notifications do not occur over
|
|
12052
|
+
* Streamable HTTP); applying the request rules symmetrically is what an
|
|
12053
|
+
* ecosystem custom-notification POST expects, and the −32020 cells stay
|
|
12054
|
+
* passing for them.
|
|
12055
|
+
* - `GET`/`DELETE` (and any other non-`POST` method) are body-less 2025-era
|
|
12056
|
+
* session operations: the modern era is `POST`-only, so they are routed to
|
|
12057
|
+
* legacy serving when it is configured and rejected otherwise.
|
|
12058
|
+
* - Array (batch) bodies are classified element-wise: an array containing a
|
|
12059
|
+
* modern-claiming or invalid element is rejected, an all-legacy array is
|
|
12060
|
+
* legacy traffic unchanged, and a single-element array is still an array.
|
|
12061
|
+
*
|
|
12062
|
+
* The classifier returns plain values (it never throws and never touches a
|
|
12063
|
+
* transport): a routing outcome (`legacy`/`modern`) or a ladder rejection
|
|
12064
|
+
* carrying the JSON-RPC error to emit and the HTTP status to emit it with.
|
|
12065
|
+
* Legacy routing outcomes deliberately carry NO `MessageClassification` —
|
|
12066
|
+
* legacy and hand-wired traffic is never classified, which keeps its
|
|
12067
|
+
* dispatch behavior byte-identical to today's.
|
|
12068
|
+
*
|
|
12069
|
+
* Error codes for the modern-path rejection cells follow the published
|
|
12070
|
+
* conformance suite (and the spec text it asserts):
|
|
12071
|
+
*
|
|
12072
|
+
* - A header/body cross-check mismatch (the `MCP-Protocol-Version` header
|
|
12073
|
+
* disagreeing with the body, or the `Mcp-Method` header disagreeing with the
|
|
12074
|
+
* body method) is rejected with `-32020` (`HeaderMismatch`) on HTTP 400.
|
|
12075
|
+
* - A request whose protocol-version header names a modern revision but whose
|
|
12076
|
+
* body carries no `_meta` envelope claim — including an envelope present but
|
|
12077
|
+
* missing the required protocol-version key — is rejected with `-32602`
|
|
12078
|
+
* (invalid params) naming the missing key(s), on HTTP 400.
|
|
12079
|
+
*
|
|
12080
|
+
* Should a future spec revision or conformance release change these
|
|
12081
|
+
* assignments, the affected cells are re-derived against that release; the
|
|
12082
|
+
* `settled` flag on {@linkcode InboundLadderRejection} stays available to mark
|
|
12083
|
+
* a cell provisional again while such a change is in flight.
|
|
12084
|
+
*/
|
|
12085
|
+
/**
|
|
12086
|
+
* The error code emitted for header/body cross-check mismatches: the
|
|
12087
|
+
* `MCP-Protocol-Version` header disagreeing with the body's envelope claim (or
|
|
12088
|
+
* with the body's classification), and the `Mcp-Method` header disagreeing
|
|
12089
|
+
* with the body method.
|
|
12090
|
+
*
|
|
12091
|
+
* `-32020` is the draft schema's `HEADER_MISMATCH` constant (the SEP-2243
|
|
12092
|
+
* `HeaderMismatch` code; the spec requires HTTP 400 for it), as also asserted
|
|
12093
|
+
* by the published conformance suite for header-validation failures. It has no
|
|
12094
|
+
* {@linkcode ProtocolErrorCode} member because it is not part of the 2025-era
|
|
12095
|
+
* wire vocabulary; the validation ladder is its only emitter.
|
|
12096
|
+
*/
|
|
12097
|
+
const HEADER_MISMATCH_ERROR_CODE = -32020;
|
|
12006
12098
|
ProtocolErrorCode.InvalidRequest, ProtocolErrorCode.UnsupportedProtocolVersion, ProtocolErrorCode.InvalidParams, ProtocolErrorCode.MethodNotFound, ProtocolErrorCode.InvalidParams, ProtocolErrorCode.MissingRequiredClientCapability;
|
|
12007
|
-
|
|
12099
|
+
/**
|
|
12100
|
+
* HTTP status for ladder-originated JSON-RPC error codes.
|
|
12101
|
+
*
|
|
12102
|
+
* Keyed on origin, not on the bare code: this table only applies to errors
|
|
12103
|
+
* the ladder (or a pre-handler protocol gate) produced. Errors produced by
|
|
12104
|
+
* request handlers — whatever their code — stay in-band on HTTP 200, and are
|
|
12105
|
+
* never mapped to an HTTP status by this table; in particular `-32603` and
|
|
12106
|
+
* domain-specific codes never become a blanket 500. The single exception is
|
|
12107
|
+
* `MissingRequiredClientCapability` (-32021) — see
|
|
12108
|
+
* {@linkcode httpStatusForErrorCode}.
|
|
12109
|
+
*
|
|
12110
|
+
* `-32602` (invalid params) deliberately has NO entry: the only invalid-params
|
|
12111
|
+
* rejection that maps to HTTP 400 is the classifier's own envelope rung
|
|
12112
|
+
* short-circuit, which carries its HTTP status directly. A dispatch- or
|
|
12113
|
+
* handler-produced invalid-params error is always in-band.
|
|
12114
|
+
*/
|
|
12115
|
+
const LADDER_ERROR_HTTP_STATUS = {
|
|
12116
|
+
[ProtocolErrorCode.ParseError]: 400,
|
|
12117
|
+
[ProtocolErrorCode.InvalidRequest]: 400,
|
|
12118
|
+
[ProtocolErrorCode.MethodNotFound]: 404,
|
|
12119
|
+
[ProtocolErrorCode.UnsupportedProtocolVersion]: 400,
|
|
12120
|
+
[ProtocolErrorCode.MissingRequiredClientCapability]: 400,
|
|
12121
|
+
[HEADER_MISMATCH_ERROR_CODE]: 400
|
|
12122
|
+
};
|
|
12008
12123
|
function rejection(rung, cell, httpStatus, error, settled) {
|
|
12009
12124
|
return {
|
|
12010
12125
|
kind: "reject",
|
|
@@ -12141,22 +12256,26 @@ function standardSchemaToJsonSchema(schema, io = "input") {
|
|
|
12141
12256
|
...result
|
|
12142
12257
|
};
|
|
12143
12258
|
}
|
|
12259
|
+
const LOCAL_DEFINITION_REF = /^#\/(\$defs|definitions)\/([^/~%]+)$/;
|
|
12144
12260
|
/**
|
|
12145
12261
|
* A typeless JSON Schema root is "provably object-shaped" when either it carries object keywords
|
|
12146
12262
|
* directly (`properties`/`patternProperties`/`additionalProperties`/`required`), or it is a
|
|
12147
12263
|
* composition (`oneOf`/`anyOf`/`allOf`) whose every member is itself `type:'object'` or recursively
|
|
12148
|
-
* provably object-shaped (e.g. a nested `discriminatedUnion`). `$ref` is
|
|
12264
|
+
* provably object-shaped (e.g. a nested `discriminatedUnion`). A `$ref` is followed one hop, to an
|
|
12265
|
+
* entry of the root's `$defs`/`definitions` that is itself `type:'object'`. Used to
|
|
12149
12266
|
* decide whether stamping `type:'object'` is safe (redundant-but-valid) versus self-contradictory.
|
|
12150
12267
|
*/
|
|
12151
|
-
function isProvablyObjectShapedRoot(schema) {
|
|
12268
|
+
function isProvablyObjectShapedRoot(schema, root = schema) {
|
|
12152
12269
|
if ("properties" in schema || "patternProperties" in schema || "additionalProperties" in schema || "required" in schema) return true;
|
|
12270
|
+
const ref = typeof schema.$ref === "string" && LOCAL_DEFINITION_REF.exec(schema.$ref);
|
|
12271
|
+
if (ref && root[ref[1]]?.[ref[2]]?.type === "object") return true;
|
|
12153
12272
|
for (const key of [
|
|
12154
12273
|
"oneOf",
|
|
12155
12274
|
"anyOf",
|
|
12156
12275
|
"allOf"
|
|
12157
12276
|
]) {
|
|
12158
12277
|
const members = schema[key];
|
|
12159
|
-
if (Array.isArray(members) && members.length > 0) return members.every((m) => m !== null && typeof m === "object" && (m.type === "object" || isProvablyObjectShapedRoot(m)));
|
|
12278
|
+
if (Array.isArray(members) && members.length > 0) return members.every((m) => m !== null && typeof m === "object" && (m.type === "object" || isProvablyObjectShapedRoot(m, "$id" in m ? {} : root)));
|
|
12160
12279
|
}
|
|
12161
12280
|
return false;
|
|
12162
12281
|
}
|
|
@@ -13821,7 +13940,7 @@ function normalizeRawShapeSchema(schema) {
|
|
|
13821
13940
|
if (!isStandardSchema(schema)) throw new TypeError("inputSchema/outputSchema/argsSchema must be a Standard Schema (e.g. z.object({...})) or a raw Zod shape ({ field: z.string() }).");
|
|
13822
13941
|
return schema;
|
|
13823
13942
|
}
|
|
13824
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
13943
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/ajvProvider-DyjnscPj.mjs
|
|
13825
13944
|
var require_code$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
13826
13945
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13827
13946
|
exports.regexpCode = exports.getEsmExportName = exports.getProperty = exports.safeStringify = exports.stringify = exports.strConcat = exports.addCodeArg = exports.str = exports._ = exports.nil = exports._Code = exports.Name = exports.IDENTIFIER = exports._CodeOrName = void 0;
|
|
@@ -16499,6 +16618,28 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16499
16618
|
const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
16500
16619
|
/** @type {(value: string) => boolean} */
|
|
16501
16620
|
const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
16621
|
+
/** @type {(value: string) => boolean} */
|
|
16622
|
+
const isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
16623
|
+
/** @type {(value: string) => boolean} */
|
|
16624
|
+
const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
16625
|
+
/** @type {(value: string) => boolean} */
|
|
16626
|
+
const isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
16627
|
+
/** @type {(value: string) => boolean} */
|
|
16628
|
+
const isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
16629
|
+
/** @type {(value: string) => boolean} */
|
|
16630
|
+
const isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
16631
|
+
/** @type {(value: string) => boolean} */
|
|
16632
|
+
const isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
16633
|
+
const BYTE_HEX = new Array(256);
|
|
16634
|
+
{
|
|
16635
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
16636
|
+
for (let i = 0; i < 256; i++) BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
16637
|
+
}
|
|
16638
|
+
function percentEncodeNonAscii(cp) {
|
|
16639
|
+
if (cp < 2048) return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
16640
|
+
if (cp < 65536) return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
16641
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
16642
|
+
}
|
|
16502
16643
|
/**
|
|
16503
16644
|
* @param {Array<string>} input
|
|
16504
16645
|
* @returns {string}
|
|
@@ -16521,119 +16662,162 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16521
16662
|
}
|
|
16522
16663
|
return acc;
|
|
16523
16664
|
}
|
|
16524
|
-
/**
|
|
16525
|
-
|
|
16526
|
-
|
|
16527
|
-
|
|
16528
|
-
|
|
16529
|
-
|
|
16665
|
+
/** @type {(value: string) => boolean} */
|
|
16666
|
+
const isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
16667
|
+
/** @type {(value: string) => boolean} */
|
|
16668
|
+
const isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
16669
|
+
/** @type {(value: string) => boolean} */
|
|
16670
|
+
const isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
16530
16671
|
/**
|
|
16531
16672
|
* @param {string} value
|
|
16532
16673
|
* @returns {boolean}
|
|
16533
16674
|
*/
|
|
16534
16675
|
const nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
16535
16676
|
/**
|
|
16536
|
-
* @param {
|
|
16677
|
+
* @param {string} zone
|
|
16537
16678
|
* @returns {boolean}
|
|
16538
16679
|
*/
|
|
16539
|
-
function
|
|
16540
|
-
|
|
16680
|
+
function isZoneIdentifier(zone) {
|
|
16681
|
+
if (zone.length === 0) return false;
|
|
16682
|
+
for (let i = 0; i < zone.length; i++) {
|
|
16683
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
16684
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
16685
|
+
i += 2;
|
|
16686
|
+
continue;
|
|
16687
|
+
}
|
|
16688
|
+
return false;
|
|
16689
|
+
}
|
|
16541
16690
|
return true;
|
|
16542
16691
|
}
|
|
16543
16692
|
/**
|
|
16544
|
-
*
|
|
16545
|
-
*
|
|
16546
|
-
*
|
|
16547
|
-
* @
|
|
16693
|
+
* Compresses the longest run of zero hextets to "::" per RFC 5952. A run of a
|
|
16694
|
+
* single zero hextet is left uncompressed. On ties the leftmost run wins.
|
|
16695
|
+
*
|
|
16696
|
+
* @param {string[]} hextets
|
|
16697
|
+
* @returns {string}
|
|
16548
16698
|
*/
|
|
16549
|
-
function
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16554
|
-
|
|
16555
|
-
|
|
16699
|
+
function compressIPv6ZeroRun(hextets) {
|
|
16700
|
+
let bestStart = -1;
|
|
16701
|
+
let bestLength = 0;
|
|
16702
|
+
let runStart = -1;
|
|
16703
|
+
let runLength = 0;
|
|
16704
|
+
for (let i = 0; i < hextets.length; i++) if (hextets[i] === "0") {
|
|
16705
|
+
if (runStart === -1) runStart = i;
|
|
16706
|
+
runLength++;
|
|
16707
|
+
if (runLength > bestLength) {
|
|
16708
|
+
bestLength = runLength;
|
|
16709
|
+
bestStart = runStart;
|
|
16556
16710
|
}
|
|
16557
|
-
|
|
16711
|
+
} else {
|
|
16712
|
+
runStart = -1;
|
|
16713
|
+
runLength = 0;
|
|
16558
16714
|
}
|
|
16559
|
-
return
|
|
16715
|
+
if (bestLength < 2) return hextets.join(":");
|
|
16716
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
16717
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
16718
|
+
return head + "::" + tail;
|
|
16560
16719
|
}
|
|
16561
16720
|
/**
|
|
16721
|
+
* Validates an IPv6 address against the alternatives in RFC 3986 section
|
|
16722
|
+
* 3.2.2 and returns the same address with leading hextet zeroes removed.
|
|
16723
|
+
* An embedded IPv4 address counts as two hextets and is only valid at the end.
|
|
16724
|
+
*
|
|
16562
16725
|
* @param {string} input
|
|
16563
|
-
* @returns {
|
|
16564
|
-
*/
|
|
16565
|
-
function
|
|
16566
|
-
|
|
16567
|
-
|
|
16568
|
-
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
let
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
if (cursor === ":") {
|
|
16583
|
-
if (endipv6Encountered === true) endIpv6 = true;
|
|
16584
|
-
if (!consume(buffer, address, output)) break;
|
|
16585
|
-
if (++tokenCount > 7) {
|
|
16586
|
-
output.error = true;
|
|
16587
|
-
break;
|
|
16588
|
-
}
|
|
16589
|
-
if (i > 0 && input[i - 1] === ":") endipv6Encountered = true;
|
|
16590
|
-
address.push(":");
|
|
16591
|
-
continue;
|
|
16592
|
-
} else if (cursor === "%") {
|
|
16593
|
-
if (!consume(buffer, address, output)) break;
|
|
16594
|
-
consume = consumeIsZone;
|
|
16595
|
-
} else {
|
|
16596
|
-
buffer.push(cursor);
|
|
16726
|
+
* @returns {string|undefined}
|
|
16727
|
+
*/
|
|
16728
|
+
function normalizeIPv6Address(input) {
|
|
16729
|
+
const compression = input.indexOf("::");
|
|
16730
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
16731
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
16732
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
16733
|
+
if (compression !== -1) {
|
|
16734
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
16735
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
16736
|
+
}
|
|
16737
|
+
const parts = left.concat(right);
|
|
16738
|
+
let hextetCount = 0;
|
|
16739
|
+
for (let i = 0; i < parts.length; i++) {
|
|
16740
|
+
const part = parts[i];
|
|
16741
|
+
if (part === "") return void 0;
|
|
16742
|
+
if (part.indexOf(".") !== -1) {
|
|
16743
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
16744
|
+
hextetCount += 2;
|
|
16597
16745
|
continue;
|
|
16598
16746
|
}
|
|
16747
|
+
if (!isHextet(part)) return void 0;
|
|
16748
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
16749
|
+
hextetCount++;
|
|
16599
16750
|
}
|
|
16600
|
-
if (
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
return
|
|
16751
|
+
if (compression === -1) {
|
|
16752
|
+
if (hextetCount !== 8) return void 0;
|
|
16753
|
+
return compressIPv6ZeroRun(parts);
|
|
16754
|
+
}
|
|
16755
|
+
if (hextetCount >= 8) return void 0;
|
|
16756
|
+
const expanded = parts.slice(0, left.length);
|
|
16757
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
16758
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
16759
|
+
return compressIPv6ZeroRun(expanded);
|
|
16605
16760
|
}
|
|
16606
16761
|
/**
|
|
16607
16762
|
* @typedef {Object} NormalizeIPv6Result
|
|
16608
16763
|
* @property {string} host - The normalized host.
|
|
16609
16764
|
* @property {string} [escapedHost] - The escaped host.
|
|
16610
16765
|
* @property {boolean} isIPV6 - Indicates if the host is an IPv6 address.
|
|
16766
|
+
* @property {boolean} [isIPVFuture] - Indicates if the host is an IPvFuture literal.
|
|
16767
|
+
* @property {boolean} [error] - Indicates if a bracketed IP literal is malformed.
|
|
16611
16768
|
*/
|
|
16612
16769
|
/**
|
|
16770
|
+
* Validates and normalizes a bracketed IP literal. Raw zone separators remain
|
|
16771
|
+
* accepted for backwards compatibility, while encoded separators and zone
|
|
16772
|
+
* contents follow RFC 6874.
|
|
16773
|
+
*
|
|
16613
16774
|
* @param {string} host
|
|
16614
16775
|
* @returns {NormalizeIPv6Result}
|
|
16615
16776
|
*/
|
|
16616
16777
|
function normalizeIPv6(host) {
|
|
16617
|
-
|
|
16778
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
16779
|
+
if ((host[0] === "[" || host[host.length - 1] === "]") && !bracketed) return {
|
|
16618
16780
|
host,
|
|
16619
|
-
isIPV6: false
|
|
16781
|
+
isIPV6: false,
|
|
16782
|
+
error: true
|
|
16620
16783
|
};
|
|
16621
|
-
|
|
16622
|
-
if (
|
|
16623
|
-
|
|
16624
|
-
let escapedHost = ipv6.address;
|
|
16625
|
-
if (ipv6.zone) {
|
|
16626
|
-
newHost += "%" + ipv6.zone;
|
|
16627
|
-
escapedHost += "%25" + ipv6.zone;
|
|
16628
|
-
}
|
|
16784
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
16785
|
+
if (bracketed && isIPvFuture(input)) {
|
|
16786
|
+
input = input.toLowerCase();
|
|
16629
16787
|
return {
|
|
16630
|
-
host:
|
|
16631
|
-
|
|
16632
|
-
|
|
16788
|
+
host: `[${input}]`,
|
|
16789
|
+
escapedHost: input,
|
|
16790
|
+
isIPV6: false,
|
|
16791
|
+
isIPVFuture: true
|
|
16792
|
+
};
|
|
16793
|
+
}
|
|
16794
|
+
if (findToken(input, ":") < 2) return {
|
|
16795
|
+
host,
|
|
16796
|
+
isIPV6: false,
|
|
16797
|
+
error: bracketed
|
|
16798
|
+
};
|
|
16799
|
+
let zoneIdentifier = "";
|
|
16800
|
+
const zoneSeparator = input.indexOf("%");
|
|
16801
|
+
if (zoneSeparator !== -1) {
|
|
16802
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
16803
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
16804
|
+
if (!isZoneIdentifier(zoneIdentifier)) return {
|
|
16805
|
+
host,
|
|
16806
|
+
isIPV6: false,
|
|
16807
|
+
error: true
|
|
16633
16808
|
};
|
|
16634
|
-
|
|
16809
|
+
input = input.slice(0, zoneSeparator);
|
|
16810
|
+
}
|
|
16811
|
+
const address = normalizeIPv6Address(input);
|
|
16812
|
+
if (address === void 0) return {
|
|
16635
16813
|
host,
|
|
16636
|
-
isIPV6: false
|
|
16814
|
+
isIPV6: false,
|
|
16815
|
+
error: true
|
|
16816
|
+
};
|
|
16817
|
+
return {
|
|
16818
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
16819
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
16820
|
+
isIPV6: true
|
|
16637
16821
|
};
|
|
16638
16822
|
}
|
|
16639
16823
|
/**
|
|
@@ -16721,19 +16905,264 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16721
16905
|
return output.join("");
|
|
16722
16906
|
}
|
|
16723
16907
|
/**
|
|
16724
|
-
*
|
|
16725
|
-
*
|
|
16726
|
-
*
|
|
16908
|
+
* Re-escape RFC 3986 gen-delims that must not appear literally in the host.
|
|
16909
|
+
* After the URI regex parses, these characters cannot be literal in the host
|
|
16910
|
+
* field, so any that appear after decoding came from percent-encoding and
|
|
16911
|
+
* must be restored to prevent authority structure changes.
|
|
16912
|
+
*
|
|
16913
|
+
* @param {string} host
|
|
16914
|
+
* @param {boolean} isIP - true for IPv4/IPv6 hosts (skip colon re-escaping)
|
|
16915
|
+
* @returns {string}
|
|
16727
16916
|
*/
|
|
16728
|
-
|
|
16729
|
-
|
|
16730
|
-
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16917
|
+
const HOST_DELIMS = {
|
|
16918
|
+
"@": "%40",
|
|
16919
|
+
"/": "%2F",
|
|
16920
|
+
"?": "%3F",
|
|
16921
|
+
"#": "%23",
|
|
16922
|
+
":": "%3A"
|
|
16923
|
+
};
|
|
16924
|
+
const HOST_DELIM_RE = /[@/?#:]/g;
|
|
16925
|
+
const HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
16926
|
+
function reescapeHostDelimiters(host, isIP) {
|
|
16927
|
+
const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
16928
|
+
re.lastIndex = 0;
|
|
16929
|
+
return host.replace(re, (ch) => HOST_DELIMS[ch]);
|
|
16930
|
+
}
|
|
16931
|
+
/**
|
|
16932
|
+
* Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
|
|
16933
|
+
* Reserved delimiters such as `%2F` stay escaped; `%2E` is unreserved.
|
|
16934
|
+
*
|
|
16935
|
+
* @param {string} input
|
|
16936
|
+
* @param {boolean} [decodeUnreserved=false]
|
|
16937
|
+
* @returns {string}
|
|
16938
|
+
*/
|
|
16939
|
+
function normalizePercentEncoding(input, decodeUnreserved = false) {
|
|
16940
|
+
if (input.indexOf("%") === -1) return input;
|
|
16941
|
+
let output = "";
|
|
16942
|
+
for (let i = 0; i < input.length; i++) {
|
|
16943
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
16944
|
+
const hex = input.slice(i + 1, i + 3);
|
|
16945
|
+
if (isHexPair(hex)) {
|
|
16946
|
+
const normalizedHex = hex.toUpperCase();
|
|
16947
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
16948
|
+
if (decodeUnreserved && isUnreserved(decoded)) output += decoded;
|
|
16949
|
+
else output += "%" + normalizedHex;
|
|
16950
|
+
i += 2;
|
|
16951
|
+
continue;
|
|
16952
|
+
}
|
|
16953
|
+
}
|
|
16954
|
+
output += input[i];
|
|
16955
|
+
}
|
|
16956
|
+
return output;
|
|
16957
|
+
}
|
|
16958
|
+
/**
|
|
16959
|
+
* Normalizes path data without turning reserved escapes into live path syntax.
|
|
16960
|
+
* Valid escapes are uppercased, raw unsafe characters are escaped, and only
|
|
16961
|
+
* unreserved bytes that are not `.` are decoded.
|
|
16962
|
+
*
|
|
16963
|
+
* @param {string} input
|
|
16964
|
+
* @returns {string}
|
|
16965
|
+
*/
|
|
16966
|
+
function normalizePathEncoding(input) {
|
|
16967
|
+
let output = "";
|
|
16968
|
+
for (let i = 0; i < input.length; i++) {
|
|
16969
|
+
const ch = input[i];
|
|
16970
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
16971
|
+
const hex = input.slice(i + 1, i + 3);
|
|
16972
|
+
if (isHexPair(hex)) {
|
|
16973
|
+
const normalizedHex = hex.toUpperCase();
|
|
16974
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
16975
|
+
if (decoded !== "." && isUnreserved(decoded)) output += decoded;
|
|
16976
|
+
else output += "%" + normalizedHex;
|
|
16977
|
+
i += 2;
|
|
16978
|
+
continue;
|
|
16979
|
+
}
|
|
16980
|
+
}
|
|
16981
|
+
if (isPathCharacter(ch)) output += ch;
|
|
16982
|
+
else {
|
|
16983
|
+
const code = input.charCodeAt(i);
|
|
16984
|
+
if (code < 128) output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
16985
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
16986
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
16987
|
+
const low = input.charCodeAt(i + 1);
|
|
16988
|
+
if (low >= 56320 && low <= 57343) {
|
|
16989
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
16990
|
+
i++;
|
|
16991
|
+
} else output += percentEncodeNonAscii(65533);
|
|
16992
|
+
} else output += percentEncodeNonAscii(65533);
|
|
16993
|
+
}
|
|
16994
|
+
}
|
|
16995
|
+
return output;
|
|
16996
|
+
}
|
|
16997
|
+
/**
|
|
16998
|
+
* Serializes a path without rewriting reserved data. Raw RFC 3986 path
|
|
16999
|
+
* characters remain literal, valid escapes are preserved and uppercased, and
|
|
17000
|
+
* everything else is UTF-8 percent-encoded. In a path-noscheme, a colon in the
|
|
17001
|
+
* first segment must be escaped so the result cannot be parsed as a scheme.
|
|
17002
|
+
*
|
|
17003
|
+
* @param {string} input
|
|
17004
|
+
* @param {boolean} [pathNoScheme=false]
|
|
17005
|
+
* @returns {string}
|
|
17006
|
+
*/
|
|
17007
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
17008
|
+
let output = "";
|
|
17009
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
17010
|
+
for (let i = 0; i < input.length; i++) {
|
|
17011
|
+
const ch = input[i];
|
|
17012
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
17013
|
+
const hex = input.slice(i + 1, i + 3);
|
|
17014
|
+
if (isHexPair(hex)) {
|
|
17015
|
+
output += "%" + hex.toUpperCase();
|
|
17016
|
+
i += 2;
|
|
17017
|
+
continue;
|
|
17018
|
+
}
|
|
17019
|
+
}
|
|
17020
|
+
if (ch === "/") firstSegment = false;
|
|
17021
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) output += ch;
|
|
17022
|
+
else {
|
|
17023
|
+
const code = input.charCodeAt(i);
|
|
17024
|
+
if (code < 128) output += BYTE_HEX[code];
|
|
17025
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
17026
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
17027
|
+
const low = input.charCodeAt(i + 1);
|
|
17028
|
+
if (low >= 56320 && low <= 57343) {
|
|
17029
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
17030
|
+
i++;
|
|
17031
|
+
} else output += percentEncodeNonAscii(65533);
|
|
17032
|
+
} else output += percentEncodeNonAscii(65533);
|
|
17033
|
+
}
|
|
17034
|
+
}
|
|
17035
|
+
return output;
|
|
17036
|
+
}
|
|
17037
|
+
/**
|
|
17038
|
+
* Percent-encodes a URI component using its RFC 3986 literal character set.
|
|
17039
|
+
* Existing valid escapes are preserved and normalized to uppercase hex.
|
|
17040
|
+
*
|
|
17041
|
+
* @param {string} input
|
|
17042
|
+
* @param {(value: string) => boolean} isAllowed
|
|
17043
|
+
* @returns {string}
|
|
17044
|
+
*/
|
|
17045
|
+
function encodeComponent(input, isAllowed) {
|
|
17046
|
+
let output = "";
|
|
17047
|
+
for (let i = 0; i < input.length; i++) {
|
|
17048
|
+
const ch = input[i];
|
|
17049
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
17050
|
+
const hex = input.slice(i + 1, i + 3);
|
|
17051
|
+
if (isHexPair(hex)) {
|
|
17052
|
+
output += "%" + hex.toUpperCase();
|
|
17053
|
+
i += 2;
|
|
17054
|
+
continue;
|
|
17055
|
+
}
|
|
17056
|
+
}
|
|
17057
|
+
if (isAllowed(ch)) output += ch;
|
|
17058
|
+
else {
|
|
17059
|
+
const code = input.charCodeAt(i);
|
|
17060
|
+
if (code < 128) output += BYTE_HEX[code];
|
|
17061
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
17062
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
17063
|
+
const low = input.charCodeAt(i + 1);
|
|
17064
|
+
if (low >= 56320 && low <= 57343) {
|
|
17065
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
17066
|
+
i++;
|
|
17067
|
+
} else output += percentEncodeNonAscii(65533);
|
|
17068
|
+
} else output += percentEncodeNonAscii(65533);
|
|
17069
|
+
}
|
|
17070
|
+
}
|
|
17071
|
+
return output;
|
|
17072
|
+
}
|
|
17073
|
+
/**
|
|
17074
|
+
* Encodes userinfo while preserving its RFC 3986 §3.2.1 literal characters.
|
|
17075
|
+
* In particular, authority delimiters such as `@`, `/`, `?`, and `#` are data.
|
|
17076
|
+
*
|
|
17077
|
+
* @param {string} input
|
|
17078
|
+
* @returns {string}
|
|
17079
|
+
*/
|
|
17080
|
+
function encodeUserinfo(input) {
|
|
17081
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
17082
|
+
}
|
|
17083
|
+
/**
|
|
17084
|
+
* Encodes query data using the RFC 3986 §3.4 grammar. A literal `#` must be
|
|
17085
|
+
* escaped because it would otherwise begin the fragment component.
|
|
17086
|
+
*
|
|
17087
|
+
* @param {string} input
|
|
17088
|
+
* @returns {string}
|
|
17089
|
+
*/
|
|
17090
|
+
function encodeQuery(input) {
|
|
17091
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
17092
|
+
}
|
|
17093
|
+
/**
|
|
17094
|
+
* Encodes fragment data using the RFC 3986 §3.5 grammar.
|
|
17095
|
+
*
|
|
17096
|
+
* @param {string} input
|
|
17097
|
+
* @returns {string}
|
|
17098
|
+
*/
|
|
17099
|
+
function encodeFragment(input) {
|
|
17100
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
17101
|
+
}
|
|
17102
|
+
function isEscapeSafe(cp) {
|
|
17103
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
17104
|
+
}
|
|
17105
|
+
/**
|
|
17106
|
+
* Normalizes the percent-encoding of a query or fragment component.
|
|
17107
|
+
*
|
|
17108
|
+
* Like `normalizePathEncoding`, but uses the query/fragment character set
|
|
17109
|
+
* (which additionally allows `?`) and decodes `.` since it has no dot-segment
|
|
17110
|
+
* meaning outside of a path.
|
|
17111
|
+
*
|
|
17112
|
+
* @param {string} input
|
|
17113
|
+
* @returns {string}
|
|
17114
|
+
*/
|
|
17115
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
17116
|
+
let output = "";
|
|
17117
|
+
for (let i = 0; i < input.length; i++) {
|
|
17118
|
+
const ch = input[i];
|
|
17119
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
17120
|
+
const hex = input.slice(i + 1, i + 3);
|
|
17121
|
+
if (isHexPair(hex)) {
|
|
17122
|
+
const normalizedHex = hex.toUpperCase();
|
|
17123
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
17124
|
+
if (isUnreserved(decoded)) output += decoded;
|
|
17125
|
+
else output += "%" + normalizedHex;
|
|
17126
|
+
i += 2;
|
|
17127
|
+
continue;
|
|
17128
|
+
}
|
|
17129
|
+
}
|
|
17130
|
+
if (isQueryFragmentCharacter(ch)) output += ch;
|
|
17131
|
+
else {
|
|
17132
|
+
const code = input.charCodeAt(i);
|
|
17133
|
+
if (code < 128) output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
17134
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
17135
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
17136
|
+
const low = input.charCodeAt(i + 1);
|
|
17137
|
+
if (low >= 56320 && low <= 57343) {
|
|
17138
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
17139
|
+
i++;
|
|
17140
|
+
} else output += percentEncodeNonAscii(65533);
|
|
17141
|
+
} else output += percentEncodeNonAscii(65533);
|
|
17142
|
+
}
|
|
17143
|
+
}
|
|
17144
|
+
return output;
|
|
17145
|
+
}
|
|
17146
|
+
/**
|
|
17147
|
+
* Escapes a component while preserving existing valid percent escapes.
|
|
17148
|
+
*
|
|
17149
|
+
* @param {string} input
|
|
17150
|
+
* @returns {string}
|
|
17151
|
+
*/
|
|
17152
|
+
function escapePreservingEscapes(input) {
|
|
17153
|
+
let output = "";
|
|
17154
|
+
for (let i = 0; i < input.length; i++) {
|
|
17155
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
17156
|
+
const hex = input.slice(i + 1, i + 3);
|
|
17157
|
+
if (isHexPair(hex)) {
|
|
17158
|
+
output += "%" + hex.toUpperCase();
|
|
17159
|
+
i += 2;
|
|
17160
|
+
continue;
|
|
17161
|
+
}
|
|
17162
|
+
}
|
|
17163
|
+
output += escape(input[i]);
|
|
17164
|
+
}
|
|
17165
|
+
return output;
|
|
16737
17166
|
}
|
|
16738
17167
|
/**
|
|
16739
17168
|
* @param {import('../types/index').URIComponent} component
|
|
@@ -16742,28 +17171,42 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16742
17171
|
function recomposeAuthority(component) {
|
|
16743
17172
|
const uriTokens = [];
|
|
16744
17173
|
if (component.userinfo !== void 0) {
|
|
16745
|
-
uriTokens.push(component.userinfo);
|
|
17174
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
16746
17175
|
uriTokens.push("@");
|
|
16747
17176
|
}
|
|
16748
17177
|
if (component.host !== void 0) {
|
|
16749
|
-
let host =
|
|
17178
|
+
let host = component.host;
|
|
16750
17179
|
if (!isIPv4(host)) {
|
|
16751
|
-
|
|
16752
|
-
if (ipV6res.isIPV6
|
|
16753
|
-
|
|
17180
|
+
let ipV6res = normalizeIPv6(host);
|
|
17181
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
17182
|
+
host = normalizePercentEncoding(host, true);
|
|
17183
|
+
ipV6res = normalizeIPv6(host);
|
|
17184
|
+
}
|
|
17185
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) host = `[${ipV6res.escapedHost}]`;
|
|
17186
|
+
else host = reescapeHostDelimiters(host, false);
|
|
16754
17187
|
}
|
|
16755
17188
|
uriTokens.push(host);
|
|
16756
17189
|
}
|
|
16757
17190
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
17191
|
+
const port = String(component.port);
|
|
17192
|
+
if (!isPort(port)) throw new TypeError("URI port is malformed.");
|
|
16758
17193
|
uriTokens.push(":");
|
|
16759
|
-
uriTokens.push(
|
|
17194
|
+
uriTokens.push(port);
|
|
16760
17195
|
}
|
|
16761
17196
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
16762
17197
|
}
|
|
16763
17198
|
module.exports = {
|
|
16764
17199
|
nonSimpleDomain,
|
|
16765
17200
|
recomposeAuthority,
|
|
16766
|
-
|
|
17201
|
+
reescapeHostDelimiters,
|
|
17202
|
+
normalizePercentEncoding,
|
|
17203
|
+
normalizePathEncoding,
|
|
17204
|
+
serializePathEncoding,
|
|
17205
|
+
normalizeQueryFragmentEncoding,
|
|
17206
|
+
encodeUserinfo,
|
|
17207
|
+
encodeQuery,
|
|
17208
|
+
encodeFragment,
|
|
17209
|
+
escapePreservingEscapes,
|
|
16767
17210
|
removeDotSegments,
|
|
16768
17211
|
isIPv4,
|
|
16769
17212
|
isUUID,
|
|
@@ -16773,7 +17216,7 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16773
17216
|
}));
|
|
16774
17217
|
var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
16775
17218
|
const { isUUID } = require_utils();
|
|
16776
|
-
const URN_REG =
|
|
17219
|
+
const URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
16777
17220
|
const supportedSchemeNames = [
|
|
16778
17221
|
"http",
|
|
16779
17222
|
"https",
|
|
@@ -16844,9 +17287,10 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16844
17287
|
wsComponent.secure = void 0;
|
|
16845
17288
|
}
|
|
16846
17289
|
if (wsComponent.resourceName) {
|
|
16847
|
-
const
|
|
17290
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
17291
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
16848
17292
|
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
16849
|
-
wsComponent.query =
|
|
17293
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
16850
17294
|
wsComponent.resourceName = void 0;
|
|
16851
17295
|
}
|
|
16852
17296
|
wsComponent.fragment = void 0;
|
|
@@ -16859,7 +17303,7 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16859
17303
|
return urnComponent;
|
|
16860
17304
|
}
|
|
16861
17305
|
const matches = urnComponent.path.match(URN_REG);
|
|
16862
|
-
if (matches) {
|
|
17306
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
16863
17307
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
16864
17308
|
urnComponent.nid = matches[1].toLowerCase();
|
|
16865
17309
|
urnComponent.nss = matches[2];
|
|
@@ -16953,8 +17397,19 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16953
17397
|
};
|
|
16954
17398
|
}));
|
|
16955
17399
|
var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
16956
|
-
const { normalizeIPv6, removeDotSegments, recomposeAuthority,
|
|
17400
|
+
const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
16957
17401
|
const { SCHEMES, getSchemeHandler } = require_schemes();
|
|
17402
|
+
const VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
17403
|
+
const MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
17404
|
+
/**
|
|
17405
|
+
* @param {string} scheme
|
|
17406
|
+
* @returns {string}
|
|
17407
|
+
*/
|
|
17408
|
+
function decodeValidScheme(scheme) {
|
|
17409
|
+
const decodedScheme = unescape(String(scheme));
|
|
17410
|
+
if (!VALID_SCHEME.test(decodedScheme)) throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
17411
|
+
return decodedScheme;
|
|
17412
|
+
}
|
|
16958
17413
|
/**
|
|
16959
17414
|
* @template {import('./types/index').URIComponent|string} T
|
|
16960
17415
|
* @param {T} uri
|
|
@@ -16962,7 +17417,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16962
17417
|
* @returns {T}
|
|
16963
17418
|
*/
|
|
16964
17419
|
function normalize(uri, options) {
|
|
16965
|
-
if (typeof uri === "string") uri =
|
|
17420
|
+
if (typeof uri === "string") uri = normalizeString(uri, options);
|
|
16966
17421
|
else if (typeof uri === "object") uri = parse(serialize(uri, options), options);
|
|
16967
17422
|
return uri;
|
|
16968
17423
|
}
|
|
@@ -16974,7 +17429,16 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
16974
17429
|
*/
|
|
16975
17430
|
function resolve(baseURI, relativeURI, options) {
|
|
16976
17431
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
16977
|
-
const
|
|
17432
|
+
const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed, malformedPercentEncoding: baseMalformedPercentEncoding, malformedSchemeSpecific: baseMalformedSchemeSpecific, malformedHost: baseMalformedHost, malformedScheme: baseMalformedScheme } = parseWithStatus(baseURI, schemelessOptions);
|
|
17433
|
+
const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed, malformedPercentEncoding: relativeMalformedPercentEncoding, malformedSchemeSpecific: relativeMalformedSchemeSpecific, malformedHost: relativeMalformedHost, malformedScheme: relativeMalformedScheme } = parseWithStatus(relativeURI, schemelessOptions);
|
|
17434
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
17435
|
+
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
17436
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
17437
|
+
const resolvedHost = resolved.host;
|
|
17438
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
17439
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
17440
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
17441
|
+
if (resolved.error && !encodedASCIIHost) throw new Error(resolved.error);
|
|
16978
17442
|
schemelessOptions.skipEscape = true;
|
|
16979
17443
|
return serialize(resolved, schemelessOptions);
|
|
16980
17444
|
}
|
|
@@ -17038,27 +17502,9 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
17038
17502
|
* @returns {boolean}
|
|
17039
17503
|
*/
|
|
17040
17504
|
function equal(uriA, uriB, options) {
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
...options,
|
|
17045
|
-
skipEscape: true
|
|
17046
|
-
});
|
|
17047
|
-
} else if (typeof uriA === "object") uriA = serialize(normalizeComponentEncoding(uriA, true), {
|
|
17048
|
-
...options,
|
|
17049
|
-
skipEscape: true
|
|
17050
|
-
});
|
|
17051
|
-
if (typeof uriB === "string") {
|
|
17052
|
-
uriB = unescape(uriB);
|
|
17053
|
-
uriB = serialize(normalizeComponentEncoding(parse(uriB, options), true), {
|
|
17054
|
-
...options,
|
|
17055
|
-
skipEscape: true
|
|
17056
|
-
});
|
|
17057
|
-
} else if (typeof uriB === "object") uriB = serialize(normalizeComponentEncoding(uriB, true), {
|
|
17058
|
-
...options,
|
|
17059
|
-
skipEscape: true
|
|
17060
|
-
});
|
|
17061
|
-
return uriA.toLowerCase() === uriB.toLowerCase();
|
|
17505
|
+
const normalizedA = normalizeComparableURI(uriA, options);
|
|
17506
|
+
const normalizedB = normalizeComparableURI(uriB, options);
|
|
17507
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
17062
17508
|
}
|
|
17063
17509
|
/**
|
|
17064
17510
|
* @param {Readonly<import('./types/index').URIComponent>} cmpts
|
|
@@ -17084,13 +17530,17 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
17084
17530
|
};
|
|
17085
17531
|
const options = Object.assign({}, opts);
|
|
17086
17532
|
const uriTokens = [];
|
|
17533
|
+
if (component.scheme) component.scheme = decodeValidScheme(component.scheme);
|
|
17087
17534
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
17088
17535
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
if (options.reference !== "suffix" && component.scheme)
|
|
17536
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
17537
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
17538
|
+
if (component.path !== void 0) if (!options.skipEscape) component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
17539
|
+
else component.path = normalizePercentEncoding(component.path);
|
|
17540
|
+
if (options.reference !== "suffix" && component.scheme) {
|
|
17541
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
17542
|
+
uriTokens.push(component.scheme, ":");
|
|
17543
|
+
}
|
|
17094
17544
|
const authority = recomposeAuthority(component);
|
|
17095
17545
|
if (authority !== void 0) {
|
|
17096
17546
|
if (options.reference !== "suffix") uriTokens.push("//");
|
|
@@ -17100,20 +17550,84 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
17100
17550
|
if (component.path !== void 0) {
|
|
17101
17551
|
let s = component.path;
|
|
17102
17552
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) s = removeDotSegments(s);
|
|
17553
|
+
if (pathNoScheme) s = serializePathEncoding(s, true);
|
|
17103
17554
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") s = "/%2F" + s.slice(2);
|
|
17104
17555
|
uriTokens.push(s);
|
|
17105
17556
|
}
|
|
17106
|
-
if (component.query !== void 0) uriTokens.push("?", component.query);
|
|
17107
|
-
if (component.fragment !== void 0) uriTokens.push("#", component.fragment);
|
|
17557
|
+
if (component.query !== void 0) uriTokens.push("?", encodeQuery(component.query));
|
|
17558
|
+
if (component.fragment !== void 0) uriTokens.push("#", encodeFragment(component.fragment));
|
|
17108
17559
|
return uriTokens.join("");
|
|
17109
17560
|
}
|
|
17110
17561
|
const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
17562
|
+
const AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
|
|
17563
|
+
const AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
|
|
17564
|
+
/**
|
|
17565
|
+
* @param {import('./types/index').URIComponent} parsed
|
|
17566
|
+
* @param {RegExpMatchArray} matches
|
|
17567
|
+
* @returns {string|undefined}
|
|
17568
|
+
*/
|
|
17569
|
+
function getParseError(parsed, matches) {
|
|
17570
|
+
if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") return "URI path must start with \"/\" when authority is present.";
|
|
17571
|
+
if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) return "URI port is malformed.";
|
|
17572
|
+
}
|
|
17573
|
+
/**
|
|
17574
|
+
* Checks percent syntax without decoding the represented octets. RFC 3986
|
|
17575
|
+
* percent-encoding is byte-oriented, so sequences such as `%FF` are valid even
|
|
17576
|
+
* though they are not independently valid UTF-8.
|
|
17577
|
+
*
|
|
17578
|
+
* @param {string|undefined} component
|
|
17579
|
+
* @returns {boolean}
|
|
17580
|
+
*/
|
|
17581
|
+
function hasMalformedPercentEncoding(component) {
|
|
17582
|
+
if (component === void 0) return false;
|
|
17583
|
+
let percent = component.indexOf("%");
|
|
17584
|
+
while (percent !== -1) {
|
|
17585
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) return true;
|
|
17586
|
+
percent = component.indexOf("%", percent + 3);
|
|
17587
|
+
}
|
|
17588
|
+
return false;
|
|
17589
|
+
}
|
|
17590
|
+
/**
|
|
17591
|
+
* Whether the host is a bracketed IP literal (RFC 3986 `IP-literal`).
|
|
17592
|
+
* An unterminated `[` is not a literal, so it must still be validated as a
|
|
17593
|
+
* reg-name instead of being waved through as an IP.
|
|
17594
|
+
*
|
|
17595
|
+
* @param {string} host
|
|
17596
|
+
* @returns {boolean}
|
|
17597
|
+
*/
|
|
17598
|
+
function isIPLiteral(host) {
|
|
17599
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
17600
|
+
}
|
|
17601
|
+
/**
|
|
17602
|
+
* @param {RegExpMatchArray} matches
|
|
17603
|
+
* @returns {boolean}
|
|
17604
|
+
*/
|
|
17605
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
17606
|
+
const host = matches[4];
|
|
17607
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
17608
|
+
}
|
|
17609
|
+
/**
|
|
17610
|
+
* @param {import('./types/index').URIComponent} parsed
|
|
17611
|
+
* @param {import('./types/index').Options} options
|
|
17612
|
+
* @param {{ domainHost?: boolean, unicodeSupport?: boolean }|undefined} schemeHandler
|
|
17613
|
+
* @param {boolean} isIP
|
|
17614
|
+
* @returns {boolean} whether host conversion failed
|
|
17615
|
+
*/
|
|
17616
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
17617
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) try {
|
|
17618
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
17619
|
+
} catch (e) {
|
|
17620
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
17621
|
+
return true;
|
|
17622
|
+
}
|
|
17623
|
+
return false;
|
|
17624
|
+
}
|
|
17111
17625
|
/**
|
|
17112
17626
|
* @param {string} uri
|
|
17113
17627
|
* @param {import('./types/index').Options} [opts]
|
|
17114
|
-
* @returns
|
|
17628
|
+
* @returns {{ parsed: import('./types/index').URIComponent, malformedAuthorityOrPort: boolean, malformedPercentEncoding: boolean, malformedSchemeSpecific: boolean, malformedHost: boolean, malformedScheme: boolean }}
|
|
17115
17629
|
*/
|
|
17116
|
-
function
|
|
17630
|
+
function parseWithStatus(uri, opts) {
|
|
17117
17631
|
const options = Object.assign({}, opts);
|
|
17118
17632
|
/** @type {import('./types/index').URIComponent} */
|
|
17119
17633
|
const parsed = {
|
|
@@ -17125,9 +17639,34 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
17125
17639
|
query: void 0,
|
|
17126
17640
|
fragment: void 0
|
|
17127
17641
|
};
|
|
17642
|
+
let malformedAuthorityOrPort = false;
|
|
17643
|
+
let malformedPercentEncoding = false;
|
|
17644
|
+
let malformedSchemeSpecific = false;
|
|
17645
|
+
let malformedHost = false;
|
|
17646
|
+
let malformedIPLiteral = false;
|
|
17647
|
+
let malformedScheme = false;
|
|
17128
17648
|
let isIP = false;
|
|
17129
17649
|
if (options.reference === "suffix") if (options.scheme) uri = options.scheme + ":" + uri;
|
|
17130
17650
|
else uri = "//" + uri;
|
|
17651
|
+
const authorityMatch = uri.match(AUTHORITY_PREFIX);
|
|
17652
|
+
if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
|
|
17653
|
+
parsed.error = "URI authority must not contain a literal backslash.";
|
|
17654
|
+
malformedAuthorityOrPort = true;
|
|
17655
|
+
}
|
|
17656
|
+
const introducerMatch = uri.match(AUTHORITY_INTRODUCER_REGION);
|
|
17657
|
+
if (introducerMatch !== null) {
|
|
17658
|
+
const region = introducerMatch[1];
|
|
17659
|
+
const normalizedRegion = region.replace(/[\t\n\r]/g, "");
|
|
17660
|
+
if (normalizedRegion.length >= 2) {
|
|
17661
|
+
if (normalizedRegion.slice(0, 2) !== "//") {
|
|
17662
|
+
parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
|
|
17663
|
+
malformedAuthorityOrPort = true;
|
|
17664
|
+
} else if (region.length !== normalizedRegion.length) {
|
|
17665
|
+
parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
|
|
17666
|
+
malformedAuthorityOrPort = true;
|
|
17667
|
+
}
|
|
17668
|
+
}
|
|
17669
|
+
}
|
|
17131
17670
|
const matches = uri.match(URI_PARSE);
|
|
17132
17671
|
if (matches) {
|
|
17133
17672
|
parsed.scheme = matches[1];
|
|
@@ -17137,11 +17676,33 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
17137
17676
|
parsed.path = matches[6] || "";
|
|
17138
17677
|
parsed.query = matches[7];
|
|
17139
17678
|
parsed.fragment = matches[8];
|
|
17679
|
+
if (parsed.scheme !== void 0) {
|
|
17680
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
17681
|
+
if (VALID_SCHEME.test(decodedScheme)) parsed.scheme = decodedScheme.toLowerCase();
|
|
17682
|
+
else {
|
|
17683
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
17684
|
+
malformedScheme = true;
|
|
17685
|
+
}
|
|
17686
|
+
}
|
|
17687
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
17688
|
+
if (malformedPercentEncoding) parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
17140
17689
|
if (isNaN(parsed.port)) parsed.port = matches[5];
|
|
17690
|
+
const parseError = getParseError(parsed, matches);
|
|
17691
|
+
if (parseError !== void 0) {
|
|
17692
|
+
parsed.error = parsed.error || parseError;
|
|
17693
|
+
malformedAuthorityOrPort = true;
|
|
17694
|
+
}
|
|
17141
17695
|
if (parsed.host) if (isIPv4(parsed.host) === false) {
|
|
17696
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
17697
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
17142
17698
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
17143
|
-
|
|
17144
|
-
|
|
17699
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
17700
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
17701
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
17702
|
+
if (malformedIPLiteral) {
|
|
17703
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
17704
|
+
malformedAuthorityOrPort = true;
|
|
17705
|
+
}
|
|
17145
17706
|
} else isIP = true;
|
|
17146
17707
|
if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) parsed.reference = "same-document";
|
|
17147
17708
|
else if (parsed.scheme === void 0) parsed.reference = "relative";
|
|
@@ -17149,24 +17710,78 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
17149
17710
|
else parsed.reference = "uri";
|
|
17150
17711
|
if (options.reference && options.reference !== "suffix" && options.reference !== parsed.reference) parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
17151
17712
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
17152
|
-
if (!
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17156
|
-
|
|
17157
|
-
}
|
|
17713
|
+
if (!malformedIPLiteral) malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
17714
|
+
if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
|
|
17715
|
+
let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
17716
|
+
if (!isIP) host = normalizePercentEncoding(host.toLowerCase());
|
|
17717
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
17158
17718
|
}
|
|
17159
17719
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
17160
|
-
if (
|
|
17161
|
-
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17720
|
+
if (parsed.path) parsed.path = normalizePathEncoding(parsed.path);
|
|
17721
|
+
if (parsed.query) parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
17722
|
+
if (parsed.fragment) parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
17723
|
+
}
|
|
17724
|
+
if (schemeHandler && schemeHandler.parse) {
|
|
17725
|
+
schemeHandler.parse(parsed, options);
|
|
17726
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) malformedSchemeSpecific = true;
|
|
17166
17727
|
}
|
|
17167
|
-
if (schemeHandler && schemeHandler.parse) schemeHandler.parse(parsed, options);
|
|
17168
17728
|
} else parsed.error = parsed.error || "URI can not be parsed.";
|
|
17169
|
-
return
|
|
17729
|
+
return {
|
|
17730
|
+
parsed,
|
|
17731
|
+
malformedAuthorityOrPort,
|
|
17732
|
+
malformedPercentEncoding,
|
|
17733
|
+
malformedSchemeSpecific,
|
|
17734
|
+
malformedHost,
|
|
17735
|
+
malformedScheme
|
|
17736
|
+
};
|
|
17737
|
+
}
|
|
17738
|
+
/**
|
|
17739
|
+
* @param {string} uri
|
|
17740
|
+
* @param {import('./types/index').Options} [opts]
|
|
17741
|
+
* @returns
|
|
17742
|
+
*/
|
|
17743
|
+
function parse(uri, opts) {
|
|
17744
|
+
return parseWithStatus(uri, opts).parsed;
|
|
17745
|
+
}
|
|
17746
|
+
/**
|
|
17747
|
+
* @param {string} uri
|
|
17748
|
+
* @param {import('./types/index').Options} [opts]
|
|
17749
|
+
* @returns {string}
|
|
17750
|
+
*/
|
|
17751
|
+
function normalizeString(uri, opts) {
|
|
17752
|
+
return normalizeStringWithStatus(uri, opts).normalized;
|
|
17753
|
+
}
|
|
17754
|
+
/**
|
|
17755
|
+
* @param {string} uri
|
|
17756
|
+
* @param {import('./types/index').Options} [opts]
|
|
17757
|
+
* @returns {{ normalized: string, malformedAuthorityOrPort: boolean, malformedPercentEncoding: boolean, malformedSchemeSpecific: boolean, malformedHost: boolean, malformedScheme: boolean }}
|
|
17758
|
+
*/
|
|
17759
|
+
function normalizeStringWithStatus(uri, opts) {
|
|
17760
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
17761
|
+
return {
|
|
17762
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
17763
|
+
malformedAuthorityOrPort,
|
|
17764
|
+
malformedPercentEncoding,
|
|
17765
|
+
malformedSchemeSpecific,
|
|
17766
|
+
malformedHost,
|
|
17767
|
+
malformedScheme
|
|
17768
|
+
};
|
|
17769
|
+
}
|
|
17770
|
+
/**
|
|
17771
|
+
* @param {import ('./types/index').URIComponent|string} uri
|
|
17772
|
+
* @param {import('./types/index').Options} [opts]
|
|
17773
|
+
* @returns {string|undefined}
|
|
17774
|
+
*/
|
|
17775
|
+
function normalizeComparableURI(uri, opts) {
|
|
17776
|
+
if (typeof uri !== "string" && typeof uri !== "object") return;
|
|
17777
|
+
let value;
|
|
17778
|
+
try {
|
|
17779
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
17780
|
+
} catch {
|
|
17781
|
+
return;
|
|
17782
|
+
}
|
|
17783
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
17784
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
17170
17785
|
}
|
|
17171
17786
|
const fastUri = {
|
|
17172
17787
|
SCHEMES,
|
|
@@ -20955,7 +21570,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
20955
21570
|
}
|
|
20956
21571
|
};
|
|
20957
21572
|
import_ajv.Ajv;
|
|
20958
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
21573
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/mcp-oHn3ureC.mjs
|
|
20959
21574
|
const COMPLETABLE_SYMBOL = Symbol.for("mcp.completable");
|
|
20960
21575
|
/**
|
|
20961
21576
|
* Checks if a schema is completable (has completion metadata).
|
|
@@ -20969,225 +21584,237 @@ function isCompletable(schema) {
|
|
|
20969
21584
|
function getCompleter(schema) {
|
|
20970
21585
|
return schema[COMPLETABLE_SYMBOL]?.complete;
|
|
20971
21586
|
}
|
|
20972
|
-
|
|
20973
|
-
|
|
20974
|
-
|
|
20975
|
-
|
|
20976
|
-
|
|
20977
|
-
|
|
20978
|
-
|
|
20979
|
-
* `resource_updated` matches only when `resourceSubscriptions` is present and
|
|
20980
|
-
* contains the event's URI exactly (per the spec: "for these resource URIs").
|
|
20981
|
-
*/
|
|
20982
|
-
function listenFilterAccepts(filter, event) {
|
|
20983
|
-
switch (event.kind) {
|
|
20984
|
-
case "tools_list_changed": return filter.toolsListChanged === true;
|
|
20985
|
-
case "prompts_list_changed": return filter.promptsListChanged === true;
|
|
20986
|
-
case "resources_list_changed": return filter.resourcesListChanged === true;
|
|
20987
|
-
case "resource_updated": return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
|
|
20988
|
-
}
|
|
21587
|
+
const MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
21588
|
+
/** Arms an unref'd timer, or disables keep-alive for invalid delays. */
|
|
21589
|
+
function armSseKeepAlive(intervalMs, onTick) {
|
|
21590
|
+
if (!Number.isFinite(intervalMs) || intervalMs < 1) return;
|
|
21591
|
+
const timer = setInterval(onTick, Math.min(intervalMs, MAX_TIMER_DELAY_MS));
|
|
21592
|
+
timer.unref?.();
|
|
21593
|
+
return timer;
|
|
20989
21594
|
}
|
|
21595
|
+
let readClassification;
|
|
20990
21596
|
/**
|
|
20991
|
-
* The
|
|
20992
|
-
*
|
|
20993
|
-
*
|
|
20994
|
-
* this back in `notifications/subscriptions/acknowledged` so the ack reflects
|
|
20995
|
-
* what the server can actually deliver.
|
|
21597
|
+
* The per-request micro-transport: a real, connected `Transport` whose whole
|
|
21598
|
+
* lifetime is one HTTP exchange. See the module documentation for the
|
|
21599
|
+
* response shapes it produces.
|
|
20996
21600
|
*
|
|
20997
|
-
*
|
|
20998
|
-
*
|
|
20999
|
-
* - `resourceSubscriptions` is honored only when
|
|
21000
|
-
* `capabilities.resources.subscribe` is advertised.
|
|
21001
|
-
*
|
|
21002
|
-
* `capabilities` is optional on this pure helper for test convenience only —
|
|
21003
|
-
* both wired routers REQUIRE capabilities at the call site (the HTTP router's
|
|
21004
|
-
* `serve()` takes a required parameter; `StdioListenRouter.serve()` throws
|
|
21005
|
-
* before `setServerCapabilities()` was called), so the fail-open
|
|
21006
|
-
* `undefined → honor everything` branch is never reachable on a wired entry.
|
|
21007
|
-
*/
|
|
21008
|
-
function honoredSubset(requested, capabilities) {
|
|
21009
|
-
const honored = {};
|
|
21010
|
-
const allow = (bit) => capabilities === void 0 || bit === true;
|
|
21011
|
-
if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
|
|
21012
|
-
if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
|
|
21013
|
-
if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
|
|
21014
|
-
if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
|
|
21015
|
-
return honored;
|
|
21016
|
-
}
|
|
21017
|
-
/** Default capacity guard: refuse a new subscription when this many are already open. */
|
|
21018
|
-
const DEFAULT_MAX_SUBSCRIPTIONS = 1024;
|
|
21019
|
-
/** Stamp the subscription id onto a notification's `_meta`. Non-mutating. */
|
|
21020
|
-
function stampSubscriptionId(notification, subscriptionId) {
|
|
21021
|
-
return {
|
|
21022
|
-
method: notification.method,
|
|
21023
|
-
params: {
|
|
21024
|
-
...notification.params,
|
|
21025
|
-
_meta: {
|
|
21026
|
-
...notification.params?._meta,
|
|
21027
|
-
[SUBSCRIPTION_ID_META_KEY]: subscriptionId
|
|
21028
|
-
}
|
|
21029
|
-
}
|
|
21030
|
-
};
|
|
21031
|
-
}
|
|
21032
|
-
/**
|
|
21033
|
-
* Read the requested filter off a `subscriptions/listen` request body.
|
|
21034
|
-
* Returns the validated filter, or `undefined` when `params.notifications`
|
|
21035
|
-
* is absent or fails the schema (the caller answers `-32602` — the spec
|
|
21036
|
-
* marks `notifications` REQUIRED on the listen request).
|
|
21037
|
-
*/
|
|
21038
|
-
function parseListenFilter(message) {
|
|
21039
|
-
const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
|
|
21040
|
-
return outcome.ok ? outcome.value.params?.notifications : void 0;
|
|
21041
|
-
}
|
|
21042
|
-
const CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
|
|
21043
|
-
"notifications/tools/list_changed",
|
|
21044
|
-
"notifications/prompts/list_changed",
|
|
21045
|
-
"notifications/resources/list_changed",
|
|
21046
|
-
"notifications/resources/updated"
|
|
21047
|
-
]);
|
|
21048
|
-
/**
|
|
21049
|
-
* Per-connection listen state for the stdio entry. One instance is held by
|
|
21050
|
-
* `serveStdio` for the connection lifetime; it routes inbound
|
|
21051
|
-
* `subscriptions/listen` / `notifications/cancelled` and rewrites outbound
|
|
21052
|
-
* change notifications onto the active subscriptions. No bus — the long-lived
|
|
21053
|
-
* pinned instance's existing `send*ListChanged()` calls feed straight into
|
|
21054
|
-
* `routeOutbound()`.
|
|
21601
|
+
* Connecting a `Server` binds the instance to the classified modern revision
|
|
21602
|
+
* when its `supportedProtocolVersions` lists it and the SDK implements it.
|
|
21055
21603
|
*/
|
|
21056
|
-
var
|
|
21057
|
-
|
|
21058
|
-
|
|
21059
|
-
/**
|
|
21060
|
-
* The serving instance's declared capabilities. Filled in by the entry
|
|
21061
|
-
* once the modern instance is constructed (the router is created before
|
|
21062
|
-
* the instance exists), so the acknowledged filter is narrowed against
|
|
21063
|
-
* what the server can actually deliver.
|
|
21064
|
-
*/
|
|
21065
|
-
_serverCapabilities;
|
|
21066
|
-
/**
|
|
21067
|
-
* The serving instance's identity, stamped onto the graceful-close
|
|
21068
|
-
* results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends
|
|
21069
|
-
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
21070
|
-
*/
|
|
21071
|
-
_serverInfo;
|
|
21072
|
-
constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
|
|
21073
|
-
this._maxSubscriptions = _maxSubscriptions;
|
|
21074
|
-
this._serverCapabilities = serverCapabilities;
|
|
21075
|
-
this._serverInfo = serverInfo;
|
|
21604
|
+
var PerRequestHTTPServerTransport = class {
|
|
21605
|
+
static {
|
|
21606
|
+
readClassification = (transport) => transport._classification;
|
|
21076
21607
|
}
|
|
21077
|
-
|
|
21078
|
-
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21082
|
-
|
|
21083
|
-
|
|
21084
|
-
|
|
21085
|
-
|
|
21608
|
+
onclose;
|
|
21609
|
+
onerror;
|
|
21610
|
+
onmessage;
|
|
21611
|
+
_classification;
|
|
21612
|
+
_responseMode;
|
|
21613
|
+
_started = false;
|
|
21614
|
+
_used = false;
|
|
21615
|
+
_closed = false;
|
|
21616
|
+
_terminalDelivered = false;
|
|
21617
|
+
/**
|
|
21618
|
+
* `true` only while the inbound message is being delivered synchronously
|
|
21619
|
+
* to the connected protocol layer. The pre-handler gates (the era
|
|
21620
|
+
* registry gate, the edge→instance handoff check, the missing-handler
|
|
21621
|
+
* rejection) answer inside this window; request handlers always run
|
|
21622
|
+
* after it (the protocol layer defers them to a microtask). An error
|
|
21623
|
+
* sent inside the window is therefore ladder-originated, and an error
|
|
21624
|
+
* sent after it is handler-produced.
|
|
21625
|
+
*/
|
|
21626
|
+
_dispatchWindowOpen = false;
|
|
21627
|
+
_requestId;
|
|
21628
|
+
_deferredResponse;
|
|
21629
|
+
_sse;
|
|
21630
|
+
_abortCleanup;
|
|
21631
|
+
_keepAliveMs;
|
|
21632
|
+
constructor(options) {
|
|
21633
|
+
this._classification = options.classification;
|
|
21634
|
+
this._responseMode = options.responseMode ?? "auto";
|
|
21635
|
+
this._keepAliveMs = options.keepAliveMs ?? 15e3;
|
|
21086
21636
|
}
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
|
|
21637
|
+
async start() {
|
|
21638
|
+
if (this._started) throw new Error("PerRequestHTTPServerTransport is already started");
|
|
21639
|
+
this._started = true;
|
|
21090
21640
|
}
|
|
21091
21641
|
/**
|
|
21092
|
-
*
|
|
21093
|
-
*
|
|
21094
|
-
* capacity / params rejection, the in-band JSON-RPC error response).
|
|
21642
|
+
* Serves the single exchange: delivers the classified message to the
|
|
21643
|
+
* connected server instance and resolves with the HTTP response.
|
|
21095
21644
|
*
|
|
21096
|
-
*
|
|
21097
|
-
*
|
|
21098
|
-
*
|
|
21099
|
-
*
|
|
21100
|
-
*
|
|
21101
|
-
*/
|
|
21102
|
-
|
|
21103
|
-
if (this.
|
|
21104
|
-
if (this.
|
|
21105
|
-
|
|
21106
|
-
|
|
21107
|
-
|
|
21108
|
-
|
|
21109
|
-
|
|
21110
|
-
|
|
21645
|
+
* Throws when called a second time (the transport is strictly
|
|
21646
|
+
* single-use), or before a server has been connected to the transport.
|
|
21647
|
+
* The returned promise rejects with a connection-closed error when the
|
|
21648
|
+
* transport is closed before a response was produced (for example because
|
|
21649
|
+
* the client disconnected).
|
|
21650
|
+
*/
|
|
21651
|
+
async handleMessage(message, extra) {
|
|
21652
|
+
if (this._used) throw new Error("PerRequestHTTPServerTransport serves exactly one exchange; construct a new transport per request");
|
|
21653
|
+
if (!this._started || this.onmessage === void 0) throw new Error("PerRequestHTTPServerTransport is not connected: connect a server to this transport before handling a message");
|
|
21654
|
+
if (this._closed) throw new Error("PerRequestHTTPServerTransport is closed");
|
|
21655
|
+
this._used = true;
|
|
21656
|
+
const signal = extra?.request?.signal;
|
|
21657
|
+
if (signal?.aborted) {
|
|
21658
|
+
await this.close();
|
|
21659
|
+
throw new SdkError(SdkErrorCode.ConnectionClosed, "The request was aborted before it could be handled");
|
|
21660
|
+
}
|
|
21661
|
+
const messageExtra = {
|
|
21662
|
+
classification: this._classification,
|
|
21663
|
+
...extra?.request !== void 0 && { request: extra.request },
|
|
21664
|
+
...extra?.authInfo !== void 0 && { authInfo: extra.authInfo }
|
|
21111
21665
|
};
|
|
21112
|
-
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
|
|
21117
|
-
|
|
21118
|
-
|
|
21666
|
+
if (isJSONRPCRequest(message)) {
|
|
21667
|
+
this._requestId = message.id;
|
|
21668
|
+
let resolve;
|
|
21669
|
+
let reject;
|
|
21670
|
+
const promise = new Promise((promiseResolve, promiseReject) => {
|
|
21671
|
+
resolve = promiseResolve;
|
|
21672
|
+
reject = promiseReject;
|
|
21673
|
+
});
|
|
21674
|
+
this._deferredResponse = {
|
|
21675
|
+
promise,
|
|
21676
|
+
resolve,
|
|
21677
|
+
reject,
|
|
21678
|
+
settled: false
|
|
21679
|
+
};
|
|
21680
|
+
if (signal !== void 0) {
|
|
21681
|
+
const onAbort = () => void this.close();
|
|
21682
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
21683
|
+
this._abortCleanup = () => signal.removeEventListener("abort", onAbort);
|
|
21119
21684
|
}
|
|
21120
|
-
|
|
21121
|
-
|
|
21122
|
-
|
|
21123
|
-
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
|
|
21685
|
+
this._dispatchWindowOpen = true;
|
|
21686
|
+
try {
|
|
21687
|
+
this.onmessage(message, messageExtra);
|
|
21688
|
+
} finally {
|
|
21689
|
+
this._dispatchWindowOpen = false;
|
|
21690
|
+
}
|
|
21691
|
+
if (this._responseMode === "sse" && !this._closed && !this._deferredResponse.settled) this.upgradeToSse();
|
|
21692
|
+
return promise;
|
|
21693
|
+
}
|
|
21694
|
+
this.onmessage(message, messageExtra);
|
|
21695
|
+
return new Response(null, { status: 202 });
|
|
21127
21696
|
}
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21132
|
-
|
|
21133
|
-
|
|
21134
|
-
|
|
21697
|
+
async send(message, options) {
|
|
21698
|
+
if (this._closed) return;
|
|
21699
|
+
const isResponse = isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message);
|
|
21700
|
+
const relatedId = isResponse ? message.id : options?.relatedRequestId;
|
|
21701
|
+
if (this._requestId === void 0 || relatedId === void 0 || relatedId !== this._requestId) {
|
|
21702
|
+
if (isResponse) this.onerror?.(/* @__PURE__ */ new Error(`Received a response for an unknown request id: ${String(message.id)}`));
|
|
21703
|
+
return;
|
|
21704
|
+
}
|
|
21705
|
+
if (isResponse) {
|
|
21706
|
+
if (this._terminalDelivered) return;
|
|
21707
|
+
this._terminalDelivered = true;
|
|
21708
|
+
const errorCode = isJSONRPCErrorResponse(message) ? message.error.code : void 0;
|
|
21709
|
+
const ladderStatus = errorCode !== void 0 && (this._dispatchWindowOpen || errorCode === ProtocolErrorCode.MissingRequiredClientCapability) ? LADDER_ERROR_HTTP_STATUS[errorCode] : void 0;
|
|
21710
|
+
if (ladderStatus !== void 0 && this._sse === void 0) {
|
|
21711
|
+
this.settleResponse(Response.json(message, {
|
|
21712
|
+
status: ladderStatus,
|
|
21713
|
+
headers: { "Content-Type": "application/json" }
|
|
21714
|
+
}));
|
|
21715
|
+
queueMicrotask(() => void this.close());
|
|
21716
|
+
return;
|
|
21717
|
+
}
|
|
21718
|
+
if (this._sse !== void 0 || this._responseMode === "sse") {
|
|
21719
|
+
if (this._sse === void 0) this.upgradeToSse();
|
|
21720
|
+
this.writeMessageFrame(message);
|
|
21721
|
+
this.finalizeStream();
|
|
21722
|
+
return;
|
|
21723
|
+
}
|
|
21724
|
+
this.settleResponse(Response.json(message, {
|
|
21725
|
+
status: 200,
|
|
21726
|
+
headers: { "Content-Type": "application/json" }
|
|
21727
|
+
}));
|
|
21728
|
+
queueMicrotask(() => void this.close());
|
|
21729
|
+
return;
|
|
21730
|
+
}
|
|
21731
|
+
if (this._responseMode === "json") return;
|
|
21732
|
+
if (this._sse === void 0) this.upgradeToSse();
|
|
21733
|
+
this.writeMessageFrame(message);
|
|
21135
21734
|
}
|
|
21136
21735
|
/**
|
|
21137
|
-
*
|
|
21138
|
-
*
|
|
21139
|
-
* - For a subscription-gated change notification, returns one stamped copy
|
|
21140
|
-
* per subscription that opted in to it (an empty array means it is
|
|
21141
|
-
* dropped — the modern era never delivers an un-requested change type).
|
|
21142
|
-
* - For any other outbound message, returns `'passthrough'` (the entry
|
|
21143
|
-
* forwards it as-is).
|
|
21736
|
+
* Writes an SSE comment frame (a keep-alive heartbeat). Dropped when the
|
|
21737
|
+
* exchange is not currently streaming.
|
|
21144
21738
|
*/
|
|
21145
|
-
|
|
21146
|
-
if (
|
|
21147
|
-
const
|
|
21148
|
-
|
|
21149
|
-
const event = notificationToServerEvent(message.method, uri);
|
|
21150
|
-
const out = [];
|
|
21151
|
-
for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
|
|
21152
|
-
method: message.method,
|
|
21153
|
-
params: message.params ?? {}
|
|
21154
|
-
}, subscriptionId));
|
|
21155
|
-
return out;
|
|
21739
|
+
writeCommentFrame(comment) {
|
|
21740
|
+
if (this._closed || this._sse === void 0 || this._sse.closed) return;
|
|
21741
|
+
const frame = comment.split("\n").map((line) => `: ${line}`).join("\n");
|
|
21742
|
+
this.writeFrame(`${frame}\n\n`);
|
|
21156
21743
|
}
|
|
21157
|
-
|
|
21158
|
-
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
|
|
21163
|
-
|
|
21164
|
-
|
|
21165
|
-
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21170
|
-
|
|
21171
|
-
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
|
|
21744
|
+
async close() {
|
|
21745
|
+
if (this._closed) return;
|
|
21746
|
+
this._closed = true;
|
|
21747
|
+
this._abortCleanup?.();
|
|
21748
|
+
this._abortCleanup = void 0;
|
|
21749
|
+
if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
|
|
21750
|
+
if (this._sse !== void 0 && !this._sse.closed) {
|
|
21751
|
+
this._sse.closed = true;
|
|
21752
|
+
try {
|
|
21753
|
+
this._sse.controller.close();
|
|
21754
|
+
} catch {}
|
|
21755
|
+
}
|
|
21756
|
+
if (this._deferredResponse !== void 0 && !this._deferredResponse.settled) {
|
|
21757
|
+
this._deferredResponse.settled = true;
|
|
21758
|
+
this._deferredResponse.reject(new SdkError(SdkErrorCode.ConnectionClosed, "Connection closed before a response was produced"));
|
|
21759
|
+
}
|
|
21760
|
+
this.onclose?.();
|
|
21761
|
+
}
|
|
21762
|
+
settleResponse(response) {
|
|
21763
|
+
if (this._deferredResponse === void 0 || this._deferredResponse.settled) return;
|
|
21764
|
+
this._deferredResponse.settled = true;
|
|
21765
|
+
this._deferredResponse.resolve(response);
|
|
21766
|
+
}
|
|
21767
|
+
upgradeToSse() {
|
|
21768
|
+
let controller;
|
|
21769
|
+
const readable = new ReadableStream({
|
|
21770
|
+
start: (streamController) => {
|
|
21771
|
+
controller = streamController;
|
|
21772
|
+
},
|
|
21773
|
+
cancel: () => {
|
|
21774
|
+
this.close();
|
|
21175
21775
|
}
|
|
21176
21776
|
});
|
|
21177
|
-
this.
|
|
21178
|
-
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
function notificationToServerEvent(method, uri) {
|
|
21182
|
-
switch (method) {
|
|
21183
|
-
case "notifications/tools/list_changed": return { kind: "tools_list_changed" };
|
|
21184
|
-
case "notifications/prompts/list_changed": return { kind: "prompts_list_changed" };
|
|
21185
|
-
case "notifications/resources/list_changed": return { kind: "resources_list_changed" };
|
|
21186
|
-
default: return {
|
|
21187
|
-
kind: "resource_updated",
|
|
21188
|
-
uri: uri ?? ""
|
|
21777
|
+
this._sse = {
|
|
21778
|
+
controller,
|
|
21779
|
+
encoder: new TextEncoder(),
|
|
21780
|
+
closed: false
|
|
21189
21781
|
};
|
|
21782
|
+
this._sse.keepAliveTimer = armSseKeepAlive(this._keepAliveMs, () => this.writeCommentFrame("keepalive"));
|
|
21783
|
+
this.settleResponse(new Response(readable, {
|
|
21784
|
+
status: 200,
|
|
21785
|
+
headers: {
|
|
21786
|
+
"Content-Type": "text/event-stream",
|
|
21787
|
+
"Cache-Control": "no-cache, no-transform",
|
|
21788
|
+
Connection: "keep-alive",
|
|
21789
|
+
"X-Accel-Buffering": "no"
|
|
21790
|
+
}
|
|
21791
|
+
}));
|
|
21792
|
+
}
|
|
21793
|
+
finalizeStream() {
|
|
21794
|
+
if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
|
|
21795
|
+
if (this._sse !== void 0 && !this._sse.closed) {
|
|
21796
|
+
this._sse.closed = true;
|
|
21797
|
+
try {
|
|
21798
|
+
this._sse.controller.close();
|
|
21799
|
+
} catch {}
|
|
21800
|
+
}
|
|
21801
|
+
queueMicrotask(() => void this.close());
|
|
21190
21802
|
}
|
|
21803
|
+
writeMessageFrame(message) {
|
|
21804
|
+
this.writeFrame(`event: message\ndata: ${JSON.stringify(message)}\n\n`);
|
|
21805
|
+
}
|
|
21806
|
+
writeFrame(frame) {
|
|
21807
|
+
if (this._sse === void 0 || this._sse.closed) return;
|
|
21808
|
+
try {
|
|
21809
|
+
this._sse.controller.enqueue(this._sse.encoder.encode(frame));
|
|
21810
|
+
} catch (error) {
|
|
21811
|
+
this.onerror?.(/* @__PURE__ */ new Error(`Failed to write to the response stream: ${error}`));
|
|
21812
|
+
}
|
|
21813
|
+
}
|
|
21814
|
+
};
|
|
21815
|
+
/** Package-internal: the classification a per-request transport serves; `undefined` for any other transport. Not public API. */
|
|
21816
|
+
function perRequestClassificationOf(transport) {
|
|
21817
|
+
return transport instanceof PerRequestHTTPServerTransport ? readClassification(transport) : void 0;
|
|
21191
21818
|
}
|
|
21192
21819
|
/** @internal */
|
|
21193
21820
|
function supportsScopeChallengeResolver(transport) {
|
|
@@ -21396,6 +22023,7 @@ var Server = class extends Protocol {
|
|
|
21396
22023
|
_requestStateVerify;
|
|
21397
22024
|
_inputRequiredServing;
|
|
21398
22025
|
_legacyShim;
|
|
22026
|
+
_boundFromTransport = false;
|
|
21399
22027
|
/** Lazily-built legacy shim; the loop lives in legacyInputRequiredShim.ts behind a narrow host contract. */
|
|
21400
22028
|
_legacyInputRequiredShim() {
|
|
21401
22029
|
return this._legacyShim ??= new LegacyInputRequiredShim({
|
|
@@ -21435,6 +22063,15 @@ var Server = class extends Protocol {
|
|
|
21435
22063
|
/** Attaches to the given transport; rejects while this instance is connected to another one. */
|
|
21436
22064
|
async connect(transport) {
|
|
21437
22065
|
if (this.transport !== void 0) throw new SdkError(SdkErrorCode.AlreadyConnected, "Use a separate Server instance per connection: this instance is already connected to a transport. To connect it to a new transport, call close() first.");
|
|
22066
|
+
if (this._boundFromTransport) {
|
|
22067
|
+
this._boundFromTransport = false;
|
|
22068
|
+
this._negotiatedProtocolVersion = void 0;
|
|
22069
|
+
}
|
|
22070
|
+
const revision = perRequestClassificationOf(transport)?.revision;
|
|
22071
|
+
if (revision !== void 0 && !this._servedModernEra() && SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(revision) && modernProtocolVersions(this._supportedProtocolVersions).includes(revision)) {
|
|
22072
|
+
this._negotiatedProtocolVersion = revision;
|
|
22073
|
+
this._boundFromTransport = true;
|
|
22074
|
+
}
|
|
21438
22075
|
await super.connect(transport);
|
|
21439
22076
|
}
|
|
21440
22077
|
/**
|
|
@@ -21745,8 +22382,8 @@ var Server = class extends Protocol {
|
|
|
21745
22382
|
* @deprecated Read client identity from the per-request handler context instead: on
|
|
21746
22383
|
* 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` carries the client's
|
|
21747
22384
|
* declared capabilities, while on 2025-era connections this accessor keeps returning the
|
|
21748
|
-
* `initialize`-scoped value. The accessor remains functional
|
|
21749
|
-
* 2026-07-28 era
|
|
22385
|
+
* `initialize`-scoped value. The accessor remains functional where `createMcpHandler`
|
|
22386
|
+
* serves the 2026-07-28 era: it backfills it per request from the validated envelope.
|
|
21750
22387
|
*/
|
|
21751
22388
|
getClientCapabilities() {
|
|
21752
22389
|
return this._clientCapabilities;
|
|
@@ -21757,8 +22394,8 @@ var Server = class extends Protocol {
|
|
|
21757
22394
|
* @deprecated Read client identity from the per-request handler context instead: on
|
|
21758
22395
|
* 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` carries the client's
|
|
21759
22396
|
* name and version, while on 2025-era connections this accessor keeps returning the
|
|
21760
|
-
* `initialize`-scoped value. The accessor remains functional
|
|
21761
|
-
* 2026-07-28 era
|
|
22397
|
+
* `initialize`-scoped value. The accessor remains functional where `createMcpHandler`
|
|
22398
|
+
* serves the 2026-07-28 era: it backfills it per request from the validated envelope.
|
|
21762
22399
|
*/
|
|
21763
22400
|
getClientVersion() {
|
|
21764
22401
|
return this._clientVersion;
|
|
@@ -22351,8 +22988,14 @@ var McpServer = class {
|
|
|
22351
22988
|
if (updates.uri) this._registeredResources[updates.uri] = registeredResource;
|
|
22352
22989
|
}
|
|
22353
22990
|
if (updates.name !== void 0) registeredResource.name = updates.name;
|
|
22354
|
-
if (updates.title !== void 0) registeredResource.title = updates.title;
|
|
22355
22991
|
if (updates.metadata !== void 0) registeredResource.metadata = updates.metadata;
|
|
22992
|
+
if (updates.title !== void 0) {
|
|
22993
|
+
registeredResource.title = updates.title;
|
|
22994
|
+
registeredResource.metadata = {
|
|
22995
|
+
...registeredResource.metadata,
|
|
22996
|
+
title: updates.title
|
|
22997
|
+
};
|
|
22998
|
+
}
|
|
22356
22999
|
if (updates.callback !== void 0) registeredResource.readCallback = updates.callback;
|
|
22357
23000
|
if (updates.scopeChallenge !== void 0) registeredResource.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
|
|
22358
23001
|
if (updates.enabled !== void 0) registeredResource.enabled = updates.enabled;
|
|
@@ -22378,9 +23021,15 @@ var McpServer = class {
|
|
|
22378
23021
|
delete this._registeredResourceTemplates[name];
|
|
22379
23022
|
if (updates.name) this._registeredResourceTemplates[updates.name] = registeredResourceTemplate;
|
|
22380
23023
|
}
|
|
22381
|
-
if (updates.title !== void 0) registeredResourceTemplate.title = updates.title;
|
|
22382
23024
|
if (updates.template !== void 0) registeredResourceTemplate.resourceTemplate = updates.template;
|
|
22383
23025
|
if (updates.metadata !== void 0) registeredResourceTemplate.metadata = updates.metadata;
|
|
23026
|
+
if (updates.title !== void 0) {
|
|
23027
|
+
registeredResourceTemplate.title = updates.title;
|
|
23028
|
+
registeredResourceTemplate.metadata = {
|
|
23029
|
+
...registeredResourceTemplate.metadata,
|
|
23030
|
+
title: updates.title
|
|
23031
|
+
};
|
|
23032
|
+
}
|
|
22384
23033
|
if (updates.callback !== void 0) registeredResourceTemplate.readCallback = updates.callback;
|
|
22385
23034
|
if (updates.scopeChallenge !== void 0) registeredResourceTemplate.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
|
|
22386
23035
|
if (updates.enabled !== void 0) registeredResourceTemplate.enabled = updates.enabled;
|
|
@@ -22654,7 +23303,228 @@ function unwrapOptionalSchema(schema) {
|
|
|
22654
23303
|
if (!isOptionalSchema(schema)) return schema;
|
|
22655
23304
|
return schema.def?.innerType ?? schema;
|
|
22656
23305
|
}
|
|
22657
|
-
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
23306
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/listenRouter-Bartj63y.mjs
|
|
23307
|
+
/**
|
|
23308
|
+
* Whether a `subscriptions/listen` filter accepts a given change event.
|
|
23309
|
+
*
|
|
23310
|
+
* Pure: no I/O, no mutation. The filter governs ONLY the four
|
|
23311
|
+
* subscription-gated change types — non-gated notifications never reach the
|
|
23312
|
+
* bus and are not modeled here.
|
|
23313
|
+
*
|
|
23314
|
+
* `resource_updated` matches only when `resourceSubscriptions` is present and
|
|
23315
|
+
* contains the event's URI exactly (per the spec: "for these resource URIs").
|
|
23316
|
+
*/
|
|
23317
|
+
function listenFilterAccepts(filter, event) {
|
|
23318
|
+
switch (event.kind) {
|
|
23319
|
+
case "tools_list_changed": return filter.toolsListChanged === true;
|
|
23320
|
+
case "prompts_list_changed": return filter.promptsListChanged === true;
|
|
23321
|
+
case "resources_list_changed": return filter.resourcesListChanged === true;
|
|
23322
|
+
case "resource_updated": return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
|
|
23323
|
+
}
|
|
23324
|
+
}
|
|
23325
|
+
/**
|
|
23326
|
+
* The honored subset of a requested filter: keeps only the fields the client
|
|
23327
|
+
* explicitly opted in to (drops `false` and absent fields), narrowed against
|
|
23328
|
+
* the server's declared capabilities when supplied. The serving entry sends
|
|
23329
|
+
* this back in `notifications/subscriptions/acknowledged` so the ack reflects
|
|
23330
|
+
* what the server can actually deliver.
|
|
23331
|
+
*
|
|
23332
|
+
* - `toolsListChanged` is honored only when `capabilities.tools.listChanged`
|
|
23333
|
+
* is advertised; likewise `promptsListChanged` / `resourcesListChanged`.
|
|
23334
|
+
* - `resourceSubscriptions` is honored only when
|
|
23335
|
+
* `capabilities.resources.subscribe` is advertised.
|
|
23336
|
+
*
|
|
23337
|
+
* `capabilities` is optional on this pure helper for test convenience only —
|
|
23338
|
+
* both wired routers REQUIRE capabilities at the call site (the HTTP router's
|
|
23339
|
+
* `serve()` takes a required parameter; `StdioListenRouter.serve()` throws
|
|
23340
|
+
* before `setServerCapabilities()` was called), so the fail-open
|
|
23341
|
+
* `undefined → honor everything` branch is never reachable on a wired entry.
|
|
23342
|
+
*/
|
|
23343
|
+
function honoredSubset(requested, capabilities) {
|
|
23344
|
+
const honored = {};
|
|
23345
|
+
const allow = (bit) => capabilities === void 0 || bit === true;
|
|
23346
|
+
if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
|
|
23347
|
+
if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
|
|
23348
|
+
if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
|
|
23349
|
+
if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
|
|
23350
|
+
return honored;
|
|
23351
|
+
}
|
|
23352
|
+
/** Default capacity guard: refuse a new subscription when this many are already open. */
|
|
23353
|
+
const DEFAULT_MAX_SUBSCRIPTIONS = 1024;
|
|
23354
|
+
/** Stamp the subscription id onto a notification's `_meta`. Non-mutating. */
|
|
23355
|
+
function stampSubscriptionId(notification, subscriptionId) {
|
|
23356
|
+
return {
|
|
23357
|
+
method: notification.method,
|
|
23358
|
+
params: {
|
|
23359
|
+
...notification.params,
|
|
23360
|
+
_meta: {
|
|
23361
|
+
...notification.params?._meta,
|
|
23362
|
+
[SUBSCRIPTION_ID_META_KEY]: subscriptionId
|
|
23363
|
+
}
|
|
23364
|
+
}
|
|
23365
|
+
};
|
|
23366
|
+
}
|
|
23367
|
+
/**
|
|
23368
|
+
* Read the requested filter off a `subscriptions/listen` request body.
|
|
23369
|
+
* Returns the validated filter, or `undefined` when `params.notifications`
|
|
23370
|
+
* is absent or fails the schema (the caller answers `-32602` — the spec
|
|
23371
|
+
* marks `notifications` REQUIRED on the listen request).
|
|
23372
|
+
*/
|
|
23373
|
+
function parseListenFilter(message) {
|
|
23374
|
+
const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
|
|
23375
|
+
return outcome.ok ? outcome.value.params?.notifications : void 0;
|
|
23376
|
+
}
|
|
23377
|
+
const CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
|
|
23378
|
+
"notifications/tools/list_changed",
|
|
23379
|
+
"notifications/prompts/list_changed",
|
|
23380
|
+
"notifications/resources/list_changed",
|
|
23381
|
+
"notifications/resources/updated"
|
|
23382
|
+
]);
|
|
23383
|
+
/**
|
|
23384
|
+
* Per-connection listen state for the stdio entry. One instance is held by
|
|
23385
|
+
* `serveStdio` for the connection lifetime; it routes inbound
|
|
23386
|
+
* `subscriptions/listen` / `notifications/cancelled` and rewrites outbound
|
|
23387
|
+
* change notifications onto the active subscriptions. No bus — the long-lived
|
|
23388
|
+
* pinned instance's existing `send*ListChanged()` calls feed straight into
|
|
23389
|
+
* `routeOutbound()`.
|
|
23390
|
+
*/
|
|
23391
|
+
var StdioListenRouter = class {
|
|
23392
|
+
/** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */
|
|
23393
|
+
_subs = /* @__PURE__ */ new Map();
|
|
23394
|
+
/**
|
|
23395
|
+
* The serving instance's declared capabilities. Filled in by the entry
|
|
23396
|
+
* once the modern instance is constructed (the router is created before
|
|
23397
|
+
* the instance exists), so the acknowledged filter is narrowed against
|
|
23398
|
+
* what the server can actually deliver.
|
|
23399
|
+
*/
|
|
23400
|
+
_serverCapabilities;
|
|
23401
|
+
/**
|
|
23402
|
+
* The serving instance's identity, stamped onto the graceful-close
|
|
23403
|
+
* results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends
|
|
23404
|
+
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
23405
|
+
*/
|
|
23406
|
+
_serverInfo;
|
|
23407
|
+
constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
|
|
23408
|
+
this._maxSubscriptions = _maxSubscriptions;
|
|
23409
|
+
this._serverCapabilities = serverCapabilities;
|
|
23410
|
+
this._serverInfo = serverInfo;
|
|
23411
|
+
}
|
|
23412
|
+
/**
|
|
23413
|
+
* Record the serving instance's declared capabilities and identity once
|
|
23414
|
+
* it has been constructed. Called by `serveStdio`'s connect path;
|
|
23415
|
+
* subsequent `serve()` calls narrow the honored filter against the
|
|
23416
|
+
* capabilities, and `teardownAll()` stamps the identity.
|
|
23417
|
+
*/
|
|
23418
|
+
setServerCapabilities(capabilities, serverInfo) {
|
|
23419
|
+
this._serverCapabilities = capabilities;
|
|
23420
|
+
if (serverInfo !== void 0) this._serverInfo = serverInfo;
|
|
23421
|
+
}
|
|
23422
|
+
/** Whether `id` is an active listen subscription on this connection. */
|
|
23423
|
+
has(id) {
|
|
23424
|
+
return this._subs.has(id);
|
|
23425
|
+
}
|
|
23426
|
+
/**
|
|
23427
|
+
* Serve one inbound `subscriptions/listen` request: registers the
|
|
23428
|
+
* subscription and returns the stamped acknowledged notification (or, on
|
|
23429
|
+
* capacity / params rejection, the in-band JSON-RPC error response).
|
|
23430
|
+
*
|
|
23431
|
+
* @throws when called before {@linkcode setServerCapabilities} (or the
|
|
23432
|
+
* constructor) has supplied the serving instance's capabilities. Honoring a
|
|
23433
|
+
* filter without knowing the server's advertised capabilities would fail
|
|
23434
|
+
* open (deliver unadvertised types); the entry guarantees capabilities are
|
|
23435
|
+
* set before any listen request is routed here.
|
|
23436
|
+
*/
|
|
23437
|
+
serve(message) {
|
|
23438
|
+
if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities");
|
|
23439
|
+
if (this._subs.size >= this._maxSubscriptions) return {
|
|
23440
|
+
jsonrpc: "2.0",
|
|
23441
|
+
id: message.id,
|
|
23442
|
+
error: {
|
|
23443
|
+
code: -32603,
|
|
23444
|
+
message: "Subscription limit reached"
|
|
23445
|
+
}
|
|
23446
|
+
};
|
|
23447
|
+
const filter = parseListenFilter(message);
|
|
23448
|
+
if (filter === void 0) return {
|
|
23449
|
+
jsonrpc: "2.0",
|
|
23450
|
+
id: message.id,
|
|
23451
|
+
error: {
|
|
23452
|
+
code: -32602,
|
|
23453
|
+
message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"
|
|
23454
|
+
}
|
|
23455
|
+
};
|
|
23456
|
+
const honored = honoredSubset(filter, this._serverCapabilities);
|
|
23457
|
+
this._subs.set(message.id, honored);
|
|
23458
|
+
return stampSubscriptionId({
|
|
23459
|
+
method: "notifications/subscriptions/acknowledged",
|
|
23460
|
+
params: { notifications: honored }
|
|
23461
|
+
}, message.id);
|
|
23462
|
+
}
|
|
23463
|
+
/**
|
|
23464
|
+
* Tear down one subscription (inbound `notifications/cancelled`). Returns
|
|
23465
|
+
* `true` when a subscription was removed. After this call NOTHING further
|
|
23466
|
+
* is delivered for that subscription id (the post-cancel hardening).
|
|
23467
|
+
*/
|
|
23468
|
+
cancel(id) {
|
|
23469
|
+
return this._subs.delete(id);
|
|
23470
|
+
}
|
|
23471
|
+
/**
|
|
23472
|
+
* Route an outbound notification through the active subscriptions.
|
|
23473
|
+
*
|
|
23474
|
+
* - For a subscription-gated change notification, returns one stamped copy
|
|
23475
|
+
* per subscription that opted in to it (an empty array means it is
|
|
23476
|
+
* dropped — the modern era never delivers an un-requested change type).
|
|
23477
|
+
* - For any other outbound message, returns `'passthrough'` (the entry
|
|
23478
|
+
* forwards it as-is).
|
|
23479
|
+
*/
|
|
23480
|
+
routeOutbound(message) {
|
|
23481
|
+
if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough";
|
|
23482
|
+
const uriParam = message.params?.["uri"];
|
|
23483
|
+
const uri = typeof uriParam === "string" ? uriParam : void 0;
|
|
23484
|
+
const event = notificationToServerEvent(message.method, uri);
|
|
23485
|
+
const out = [];
|
|
23486
|
+
for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
|
|
23487
|
+
method: message.method,
|
|
23488
|
+
params: message.params ?? {}
|
|
23489
|
+
}, subscriptionId));
|
|
23490
|
+
return out;
|
|
23491
|
+
}
|
|
23492
|
+
/**
|
|
23493
|
+
* Server-side graceful teardown of every active subscription: returns the
|
|
23494
|
+
* empty `subscriptions/listen` JSON-RPC result for each subscription id —
|
|
23495
|
+
* the spec's graceful-close signal, `_meta` carrying the subscription id
|
|
23496
|
+
* and the serving instance's identity — for the entry to emit before
|
|
23497
|
+
* closing the wire. Clears the set so nothing further is delivered.
|
|
23498
|
+
*/
|
|
23499
|
+
teardownAll() {
|
|
23500
|
+
const out = [];
|
|
23501
|
+
for (const id of this._subs.keys()) out.push({
|
|
23502
|
+
jsonrpc: "2.0",
|
|
23503
|
+
id,
|
|
23504
|
+
result: {
|
|
23505
|
+
resultType: "complete",
|
|
23506
|
+
_meta: {
|
|
23507
|
+
[SUBSCRIPTION_ID_META_KEY]: id,
|
|
23508
|
+
...this._serverInfo !== void 0 && { ["io.modelcontextprotocol/serverInfo"]: this._serverInfo }
|
|
23509
|
+
}
|
|
23510
|
+
}
|
|
23511
|
+
});
|
|
23512
|
+
this._subs.clear();
|
|
23513
|
+
return out;
|
|
23514
|
+
}
|
|
23515
|
+
};
|
|
23516
|
+
function notificationToServerEvent(method, uri) {
|
|
23517
|
+
switch (method) {
|
|
23518
|
+
case "notifications/tools/list_changed": return { kind: "tools_list_changed" };
|
|
23519
|
+
case "notifications/prompts/list_changed": return { kind: "prompts_list_changed" };
|
|
23520
|
+
case "notifications/resources/list_changed": return { kind: "resources_list_changed" };
|
|
23521
|
+
default: return {
|
|
23522
|
+
kind: "resource_updated",
|
|
23523
|
+
uri: uri ?? ""
|
|
23524
|
+
};
|
|
23525
|
+
}
|
|
23526
|
+
}
|
|
23527
|
+
// ../../node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
|
|
22658
23528
|
/**
|
|
22659
23529
|
* Marks a stdout `'error'` listener that a closed transport left attached purely to
|
|
22660
23530
|
* swallow late write failures (see {@link StdioServerTransport.close}). A fresh
|
|
@@ -23233,7 +24103,7 @@ function toError(value) {
|
|
|
23233
24103
|
return value instanceof Error ? value : new Error(String(value));
|
|
23234
24104
|
}
|
|
23235
24105
|
// package.json
|
|
23236
|
-
var version = "0.26.
|
|
24106
|
+
var version = "0.26.2";
|
|
23237
24107
|
// ../fountain/src/inline.ts
|
|
23238
24108
|
const MARKERS$1 = /[*_\\]/;
|
|
23239
24109
|
const isSpace$10 = (code) => code === void 0 || /\s/.test(String.fromCharCode(code));
|
|
@@ -39512,7 +40382,7 @@ export {};
|
|
|
39512
40382
|
* with the code of the packages below inside it. Each one’s licence follows, in full.
|
|
39513
40383
|
*
|
|
39514
40384
|
* ----------------------------------------------------------------------
|
|
39515
|
-
* @modelcontextprotocol/core 2.
|
|
40385
|
+
* @modelcontextprotocol/core 2.4.0 (Apache-2.0)
|
|
39516
40386
|
*
|
|
39517
40387
|
* The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
|
|
39518
40388
|
*
|
|
@@ -39732,7 +40602,7 @@ export {};
|
|
|
39732
40602
|
* the full license text.
|
|
39733
40603
|
*
|
|
39734
40604
|
* ----------------------------------------------------------------------
|
|
39735
|
-
* @modelcontextprotocol/server 2.
|
|
40605
|
+
* @modelcontextprotocol/server 2.4.0 (Apache-2.0)
|
|
39736
40606
|
*
|
|
39737
40607
|
* The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
|
|
39738
40608
|
*
|
|
@@ -40053,14 +40923,12 @@ export {};
|
|
|
40053
40923
|
* SOFTWARE.
|
|
40054
40924
|
*
|
|
40055
40925
|
* ----------------------------------------------------------------------
|
|
40056
|
-
* fast-uri 3.1.
|
|
40926
|
+
* fast-uri 3.1.8 (BSD-3-Clause), carried inside @modelcontextprotocol/server
|
|
40057
40927
|
*
|
|
40058
40928
|
* Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
|
|
40059
|
-
* Copyright (c) 2021-present The Fastify team
|
|
40929
|
+
* Copyright (c) 2021-present The Fastify team <https://github.com/fastify/fastify#team>
|
|
40060
40930
|
* All rights reserved.
|
|
40061
40931
|
*
|
|
40062
|
-
* The Fastify team members are listed at https://github.com/fastify/fastify#team.
|
|
40063
|
-
*
|
|
40064
40932
|
* Redistribution and use in source and binary forms, with or without
|
|
40065
40933
|
* modification, are permitted provided that the following conditions are met:
|
|
40066
40934
|
* * Redistributions of source code must retain the above copyright
|