splitwise-mcp 2.3.0 → 2.4.1
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +742 -223
- package/dist/index.js +1 -1
- package/dist/project.js +184 -0
- package/dist/tools/_confirm.js +2 -2
- package/dist/tools/expenses.js +11 -8
- package/dist/tools/friends.js +10 -6
- package/dist/tools/groups.js +15 -10
- package/dist/tools/receipts.js +2 -2
- package/dist/tools/user.js +13 -8
- package/dist/tools/utilities.js +14 -9
- package/package.json +2 -2
- package/server.json +2 -2
- package/skills/splitwise-mcp/SKILL.md +78 -7
package/dist/bundle.js
CHANGED
|
@@ -3117,9 +3117,28 @@ var require_utils = __commonJS({
|
|
|
3117
3117
|
"use strict";
|
|
3118
3118
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3119
3119
|
var 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);
|
|
3120
|
+
var isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
3120
3121
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3121
3122
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3122
|
-
var isPathCharacter = RegExp.prototype.test.bind(/^[
|
|
3123
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
3124
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
3125
|
+
var isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
3126
|
+
var BYTE_HEX = new Array(256);
|
|
3127
|
+
{
|
|
3128
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
3129
|
+
for (let i2 = 0; i2 < 256; i2++) {
|
|
3130
|
+
BYTE_HEX[i2] = "%" + HEX_DIGITS[i2 >> 4] + HEX_DIGITS[i2 & 15];
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
function percentEncodeNonAscii(cp) {
|
|
3134
|
+
if (cp < 2048) {
|
|
3135
|
+
return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
3136
|
+
}
|
|
3137
|
+
if (cp < 65536) {
|
|
3138
|
+
return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3139
|
+
}
|
|
3140
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
3141
|
+
}
|
|
3123
3142
|
function stringArrayToHexStripped(input) {
|
|
3124
3143
|
let acc = "";
|
|
3125
3144
|
let code = 0;
|
|
@@ -3144,91 +3163,105 @@ var require_utils = __commonJS({
|
|
|
3144
3163
|
}
|
|
3145
3164
|
return acc;
|
|
3146
3165
|
}
|
|
3166
|
+
var isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
3167
|
+
var isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
3168
|
+
var isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
3147
3169
|
var nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
3148
|
-
function
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
if (hex3 !== "") {
|
|
3156
|
-
address.push(hex3);
|
|
3157
|
-
} else {
|
|
3158
|
-
output.error = true;
|
|
3159
|
-
return false;
|
|
3170
|
+
function isZoneIdentifier(zone) {
|
|
3171
|
+
if (zone.length === 0) return false;
|
|
3172
|
+
for (let i2 = 0; i2 < zone.length; i2++) {
|
|
3173
|
+
if (isZoneCharacter(zone[i2])) continue;
|
|
3174
|
+
if (zone[i2] === "%" && i2 + 2 < zone.length && isHexPair(zone.slice(i2 + 1, i2 + 3))) {
|
|
3175
|
+
i2 += 2;
|
|
3176
|
+
continue;
|
|
3160
3177
|
}
|
|
3161
|
-
|
|
3178
|
+
return false;
|
|
3162
3179
|
}
|
|
3163
3180
|
return true;
|
|
3164
3181
|
}
|
|
3165
|
-
function
|
|
3166
|
-
let
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
let
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
}
|
|
3178
|
-
if (cursor === ":") {
|
|
3179
|
-
if (endipv6Encountered === true) {
|
|
3180
|
-
endIpv6 = true;
|
|
3182
|
+
function compressIPv6ZeroRun(hextets) {
|
|
3183
|
+
let bestStart = -1;
|
|
3184
|
+
let bestLength = 0;
|
|
3185
|
+
let runStart = -1;
|
|
3186
|
+
let runLength = 0;
|
|
3187
|
+
for (let i2 = 0; i2 < hextets.length; i2++) {
|
|
3188
|
+
if (hextets[i2] === "0") {
|
|
3189
|
+
if (runStart === -1) runStart = i2;
|
|
3190
|
+
runLength++;
|
|
3191
|
+
if (runLength > bestLength) {
|
|
3192
|
+
bestLength = runLength;
|
|
3193
|
+
bestStart = runStart;
|
|
3181
3194
|
}
|
|
3182
|
-
if (!consume(buffer, address, output)) {
|
|
3183
|
-
break;
|
|
3184
|
-
}
|
|
3185
|
-
if (++tokenCount > 7) {
|
|
3186
|
-
output.error = true;
|
|
3187
|
-
break;
|
|
3188
|
-
}
|
|
3189
|
-
if (i2 > 0 && input[i2 - 1] === ":") {
|
|
3190
|
-
endipv6Encountered = true;
|
|
3191
|
-
}
|
|
3192
|
-
address.push(":");
|
|
3193
|
-
continue;
|
|
3194
|
-
} else if (cursor === "%") {
|
|
3195
|
-
if (!consume(buffer, address, output)) {
|
|
3196
|
-
break;
|
|
3197
|
-
}
|
|
3198
|
-
consume = consumeIsZone;
|
|
3199
3195
|
} else {
|
|
3200
|
-
|
|
3196
|
+
runStart = -1;
|
|
3197
|
+
runLength = 0;
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
if (bestLength < 2) return hextets.join(":");
|
|
3201
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
3202
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
3203
|
+
return head + "::" + tail;
|
|
3204
|
+
}
|
|
3205
|
+
function normalizeIPv6Address(input) {
|
|
3206
|
+
const compression = input.indexOf("::");
|
|
3207
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
3208
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
3209
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
3210
|
+
if (compression !== -1) {
|
|
3211
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
3212
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
3213
|
+
}
|
|
3214
|
+
const parts = left.concat(right);
|
|
3215
|
+
let hextetCount = 0;
|
|
3216
|
+
for (let i2 = 0; i2 < parts.length; i2++) {
|
|
3217
|
+
const part = parts[i2];
|
|
3218
|
+
if (part === "") return void 0;
|
|
3219
|
+
if (part.indexOf(".") !== -1) {
|
|
3220
|
+
if (i2 !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
3221
|
+
hextetCount += 2;
|
|
3201
3222
|
continue;
|
|
3202
3223
|
}
|
|
3224
|
+
if (!isHextet(part)) return void 0;
|
|
3225
|
+
parts[i2] = parseInt(part, 16).toString(16);
|
|
3226
|
+
hextetCount++;
|
|
3203
3227
|
}
|
|
3204
|
-
if (
|
|
3205
|
-
if (
|
|
3206
|
-
|
|
3207
|
-
} else if (endIpv6) {
|
|
3208
|
-
address.push(buffer.join(""));
|
|
3209
|
-
} else {
|
|
3210
|
-
address.push(stringArrayToHexStripped(buffer));
|
|
3211
|
-
}
|
|
3228
|
+
if (compression === -1) {
|
|
3229
|
+
if (hextetCount !== 8) return void 0;
|
|
3230
|
+
return compressIPv6ZeroRun(parts);
|
|
3212
3231
|
}
|
|
3213
|
-
|
|
3214
|
-
|
|
3232
|
+
if (hextetCount >= 8) return void 0;
|
|
3233
|
+
const expanded = parts.slice(0, left.length);
|
|
3234
|
+
for (let i2 = hextetCount; i2 < 8; i2++) expanded.push("0");
|
|
3235
|
+
for (let i2 = left.length; i2 < parts.length; i2++) expanded.push(parts[i2]);
|
|
3236
|
+
return compressIPv6ZeroRun(expanded);
|
|
3215
3237
|
}
|
|
3216
3238
|
function normalizeIPv6(host) {
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
}
|
|
3220
|
-
|
|
3221
|
-
if (
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3239
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
3240
|
+
const hasBracket = host[0] === "[" || host[host.length - 1] === "]";
|
|
3241
|
+
if (hasBracket && !bracketed) return { host, isIPV6: false, error: true };
|
|
3242
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
3243
|
+
if (bracketed && isIPvFuture(input)) {
|
|
3244
|
+
input = input.toLowerCase();
|
|
3245
|
+
return { host: `[${input}]`, escapedHost: input, isIPV6: false, isIPVFuture: true };
|
|
3246
|
+
}
|
|
3247
|
+
if (findToken(input, ":") < 2) {
|
|
3248
|
+
return { host, isIPV6: false, error: bracketed };
|
|
3249
|
+
}
|
|
3250
|
+
let zoneIdentifier = "";
|
|
3251
|
+
const zoneSeparator = input.indexOf("%");
|
|
3252
|
+
if (zoneSeparator !== -1) {
|
|
3253
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
3254
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
3255
|
+
if (!isZoneIdentifier(zoneIdentifier)) return { host, isIPV6: false, error: true };
|
|
3256
|
+
input = input.slice(0, zoneSeparator);
|
|
3257
|
+
}
|
|
3258
|
+
const address = normalizeIPv6Address(input);
|
|
3259
|
+
if (address === void 0) return { host, isIPV6: false, error: true };
|
|
3260
|
+
return {
|
|
3261
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
3262
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
3263
|
+
isIPV6: true
|
|
3264
|
+
};
|
|
3232
3265
|
}
|
|
3233
3266
|
function findToken(str, token) {
|
|
3234
3267
|
let ind = 0;
|
|
@@ -3347,7 +3380,8 @@ var require_utils = __commonJS({
|
|
|
3347
3380
|
function normalizePathEncoding(input) {
|
|
3348
3381
|
let output = "";
|
|
3349
3382
|
for (let i2 = 0; i2 < input.length; i2++) {
|
|
3350
|
-
|
|
3383
|
+
const ch2 = input[i2];
|
|
3384
|
+
if (ch2 === "%" && i2 + 2 < input.length) {
|
|
3351
3385
|
const hex3 = input.slice(i2 + 1, i2 + 3);
|
|
3352
3386
|
if (isHexPair(hex3)) {
|
|
3353
3387
|
const normalizedHex = hex3.toUpperCase();
|
|
@@ -3361,10 +3395,152 @@ var require_utils = __commonJS({
|
|
|
3361
3395
|
continue;
|
|
3362
3396
|
}
|
|
3363
3397
|
}
|
|
3364
|
-
if (isPathCharacter(
|
|
3365
|
-
output +=
|
|
3398
|
+
if (isPathCharacter(ch2)) {
|
|
3399
|
+
output += ch2;
|
|
3400
|
+
} else {
|
|
3401
|
+
const code = input.charCodeAt(i2);
|
|
3402
|
+
if (code < 128) {
|
|
3403
|
+
output += isEscapeSafe(code) ? ch2 : BYTE_HEX[code];
|
|
3404
|
+
} else if (code < 55296 || code > 57343) {
|
|
3405
|
+
output += percentEncodeNonAscii(code);
|
|
3406
|
+
} else if (code <= 56319 && i2 + 1 < input.length) {
|
|
3407
|
+
const low = input.charCodeAt(i2 + 1);
|
|
3408
|
+
if (low >= 56320 && low <= 57343) {
|
|
3409
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3410
|
+
i2++;
|
|
3411
|
+
} else {
|
|
3412
|
+
output += percentEncodeNonAscii(65533);
|
|
3413
|
+
}
|
|
3414
|
+
} else {
|
|
3415
|
+
output += percentEncodeNonAscii(65533);
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
return output;
|
|
3420
|
+
}
|
|
3421
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
3422
|
+
let output = "";
|
|
3423
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
3424
|
+
for (let i2 = 0; i2 < input.length; i2++) {
|
|
3425
|
+
const ch2 = input[i2];
|
|
3426
|
+
if (ch2 === "%" && i2 + 2 < input.length) {
|
|
3427
|
+
const hex3 = input.slice(i2 + 1, i2 + 3);
|
|
3428
|
+
if (isHexPair(hex3)) {
|
|
3429
|
+
output += "%" + hex3.toUpperCase();
|
|
3430
|
+
i2 += 2;
|
|
3431
|
+
continue;
|
|
3432
|
+
}
|
|
3433
|
+
}
|
|
3434
|
+
if (ch2 === "/") {
|
|
3435
|
+
firstSegment = false;
|
|
3436
|
+
}
|
|
3437
|
+
if (isPathCharacter(ch2) && (ch2 !== ":" || !firstSegment)) {
|
|
3438
|
+
output += ch2;
|
|
3366
3439
|
} else {
|
|
3367
|
-
|
|
3440
|
+
const code = input.charCodeAt(i2);
|
|
3441
|
+
if (code < 128) {
|
|
3442
|
+
output += BYTE_HEX[code];
|
|
3443
|
+
} else if (code < 55296 || code > 57343) {
|
|
3444
|
+
output += percentEncodeNonAscii(code);
|
|
3445
|
+
} else if (code <= 56319 && i2 + 1 < input.length) {
|
|
3446
|
+
const low = input.charCodeAt(i2 + 1);
|
|
3447
|
+
if (low >= 56320 && low <= 57343) {
|
|
3448
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3449
|
+
i2++;
|
|
3450
|
+
} else {
|
|
3451
|
+
output += percentEncodeNonAscii(65533);
|
|
3452
|
+
}
|
|
3453
|
+
} else {
|
|
3454
|
+
output += percentEncodeNonAscii(65533);
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
return output;
|
|
3459
|
+
}
|
|
3460
|
+
function encodeComponent(input, isAllowed) {
|
|
3461
|
+
let output = "";
|
|
3462
|
+
for (let i2 = 0; i2 < input.length; i2++) {
|
|
3463
|
+
const ch2 = input[i2];
|
|
3464
|
+
if (ch2 === "%" && i2 + 2 < input.length) {
|
|
3465
|
+
const hex3 = input.slice(i2 + 1, i2 + 3);
|
|
3466
|
+
if (isHexPair(hex3)) {
|
|
3467
|
+
output += "%" + hex3.toUpperCase();
|
|
3468
|
+
i2 += 2;
|
|
3469
|
+
continue;
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
if (isAllowed(ch2)) {
|
|
3473
|
+
output += ch2;
|
|
3474
|
+
} else {
|
|
3475
|
+
const code = input.charCodeAt(i2);
|
|
3476
|
+
if (code < 128) {
|
|
3477
|
+
output += BYTE_HEX[code];
|
|
3478
|
+
} else if (code < 55296 || code > 57343) {
|
|
3479
|
+
output += percentEncodeNonAscii(code);
|
|
3480
|
+
} else if (code <= 56319 && i2 + 1 < input.length) {
|
|
3481
|
+
const low = input.charCodeAt(i2 + 1);
|
|
3482
|
+
if (low >= 56320 && low <= 57343) {
|
|
3483
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3484
|
+
i2++;
|
|
3485
|
+
} else {
|
|
3486
|
+
output += percentEncodeNonAscii(65533);
|
|
3487
|
+
}
|
|
3488
|
+
} else {
|
|
3489
|
+
output += percentEncodeNonAscii(65533);
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
return output;
|
|
3494
|
+
}
|
|
3495
|
+
function encodeUserinfo(input) {
|
|
3496
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
3497
|
+
}
|
|
3498
|
+
function encodeQuery(input) {
|
|
3499
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3500
|
+
}
|
|
3501
|
+
function encodeFragment(input) {
|
|
3502
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
3503
|
+
}
|
|
3504
|
+
function isEscapeSafe(cp) {
|
|
3505
|
+
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;
|
|
3506
|
+
}
|
|
3507
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3508
|
+
let output = "";
|
|
3509
|
+
for (let i2 = 0; i2 < input.length; i2++) {
|
|
3510
|
+
const ch2 = input[i2];
|
|
3511
|
+
if (ch2 === "%" && i2 + 2 < input.length) {
|
|
3512
|
+
const hex3 = input.slice(i2 + 1, i2 + 3);
|
|
3513
|
+
if (isHexPair(hex3)) {
|
|
3514
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3515
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3516
|
+
if (isUnreserved(decoded)) {
|
|
3517
|
+
output += decoded;
|
|
3518
|
+
} else {
|
|
3519
|
+
output += "%" + normalizedHex;
|
|
3520
|
+
}
|
|
3521
|
+
i2 += 2;
|
|
3522
|
+
continue;
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
if (isQueryFragmentCharacter(ch2)) {
|
|
3526
|
+
output += ch2;
|
|
3527
|
+
} else {
|
|
3528
|
+
const code = input.charCodeAt(i2);
|
|
3529
|
+
if (code < 128) {
|
|
3530
|
+
output += isEscapeSafe(code) ? ch2 : BYTE_HEX[code];
|
|
3531
|
+
} else if (code < 55296 || code > 57343) {
|
|
3532
|
+
output += percentEncodeNonAscii(code);
|
|
3533
|
+
} else if (code <= 56319 && i2 + 1 < input.length) {
|
|
3534
|
+
const low = input.charCodeAt(i2 + 1);
|
|
3535
|
+
if (low >= 56320 && low <= 57343) {
|
|
3536
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3537
|
+
i2++;
|
|
3538
|
+
} else {
|
|
3539
|
+
output += percentEncodeNonAscii(65533);
|
|
3540
|
+
}
|
|
3541
|
+
} else {
|
|
3542
|
+
output += percentEncodeNonAscii(65533);
|
|
3543
|
+
}
|
|
3368
3544
|
}
|
|
3369
3545
|
}
|
|
3370
3546
|
return output;
|
|
@@ -3387,14 +3563,18 @@ var require_utils = __commonJS({
|
|
|
3387
3563
|
function recomposeAuthority(component) {
|
|
3388
3564
|
const uriTokens = [];
|
|
3389
3565
|
if (component.userinfo !== void 0) {
|
|
3390
|
-
uriTokens.push(component.userinfo);
|
|
3566
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
3391
3567
|
uriTokens.push("@");
|
|
3392
3568
|
}
|
|
3393
3569
|
if (component.host !== void 0) {
|
|
3394
|
-
let host =
|
|
3570
|
+
let host = component.host;
|
|
3395
3571
|
if (!isIPv4(host)) {
|
|
3396
|
-
|
|
3397
|
-
if (ipV6res.isIPV6
|
|
3572
|
+
let ipV6res = normalizeIPv6(host);
|
|
3573
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
3574
|
+
host = normalizePercentEncoding(host, true);
|
|
3575
|
+
ipV6res = normalizeIPv6(host);
|
|
3576
|
+
}
|
|
3577
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) {
|
|
3398
3578
|
host = `[${ipV6res.escapedHost}]`;
|
|
3399
3579
|
} else {
|
|
3400
3580
|
host = reescapeHostDelimiters(host, false);
|
|
@@ -3403,8 +3583,12 @@ var require_utils = __commonJS({
|
|
|
3403
3583
|
uriTokens.push(host);
|
|
3404
3584
|
}
|
|
3405
3585
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
3586
|
+
const port = String(component.port);
|
|
3587
|
+
if (!isPort(port)) {
|
|
3588
|
+
throw new TypeError("URI port is malformed.");
|
|
3589
|
+
}
|
|
3406
3590
|
uriTokens.push(":");
|
|
3407
|
-
uriTokens.push(
|
|
3591
|
+
uriTokens.push(port);
|
|
3408
3592
|
}
|
|
3409
3593
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
3410
3594
|
}
|
|
@@ -3414,6 +3598,11 @@ var require_utils = __commonJS({
|
|
|
3414
3598
|
reescapeHostDelimiters,
|
|
3415
3599
|
normalizePercentEncoding,
|
|
3416
3600
|
normalizePathEncoding,
|
|
3601
|
+
serializePathEncoding,
|
|
3602
|
+
normalizeQueryFragmentEncoding,
|
|
3603
|
+
encodeUserinfo,
|
|
3604
|
+
encodeQuery,
|
|
3605
|
+
encodeFragment,
|
|
3417
3606
|
escapePreservingEscapes,
|
|
3418
3607
|
removeDotSegments,
|
|
3419
3608
|
isIPv4,
|
|
@@ -3429,7 +3618,7 @@ var require_schemes = __commonJS({
|
|
|
3429
3618
|
"node_modules/fast-uri/lib/schemes.js"(exports, module) {
|
|
3430
3619
|
"use strict";
|
|
3431
3620
|
var { isUUID } = require_utils();
|
|
3432
|
-
var URN_REG =
|
|
3621
|
+
var URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
3433
3622
|
var supportedSchemeNames = (
|
|
3434
3623
|
/** @type {const} */
|
|
3435
3624
|
[
|
|
@@ -3490,9 +3679,10 @@ var require_schemes = __commonJS({
|
|
|
3490
3679
|
wsComponent.secure = void 0;
|
|
3491
3680
|
}
|
|
3492
3681
|
if (wsComponent.resourceName) {
|
|
3493
|
-
const
|
|
3682
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
3683
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
3494
3684
|
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
3495
|
-
wsComponent.query =
|
|
3685
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
3496
3686
|
wsComponent.resourceName = void 0;
|
|
3497
3687
|
}
|
|
3498
3688
|
wsComponent.fragment = void 0;
|
|
@@ -3504,7 +3694,7 @@ var require_schemes = __commonJS({
|
|
|
3504
3694
|
return urnComponent;
|
|
3505
3695
|
}
|
|
3506
3696
|
const matches = urnComponent.path.match(URN_REG);
|
|
3507
|
-
if (matches) {
|
|
3697
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
3508
3698
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
3509
3699
|
urnComponent.nid = matches[1].toLowerCase();
|
|
3510
3700
|
urnComponent.nss = matches[2];
|
|
@@ -3638,8 +3828,17 @@ var require_schemes = __commonJS({
|
|
|
3638
3828
|
var require_fast_uri = __commonJS({
|
|
3639
3829
|
"node_modules/fast-uri/index.js"(exports, module) {
|
|
3640
3830
|
"use strict";
|
|
3641
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding,
|
|
3831
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3642
3832
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3833
|
+
var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
3834
|
+
var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
3835
|
+
function decodeValidScheme(scheme) {
|
|
3836
|
+
const decodedScheme = unescape(String(scheme));
|
|
3837
|
+
if (!VALID_SCHEME.test(decodedScheme)) {
|
|
3838
|
+
throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
3839
|
+
}
|
|
3840
|
+
return decodedScheme;
|
|
3841
|
+
}
|
|
3643
3842
|
function normalize(uri, options) {
|
|
3644
3843
|
if (typeof uri === "string") {
|
|
3645
3844
|
uri = /** @type {T} */
|
|
@@ -3652,12 +3851,34 @@ var require_fast_uri = __commonJS({
|
|
|
3652
3851
|
}
|
|
3653
3852
|
function resolve2(baseURI, relativeURI, options) {
|
|
3654
3853
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3655
|
-
const {
|
|
3656
|
-
|
|
3657
|
-
|
|
3854
|
+
const {
|
|
3855
|
+
parsed: baseParsed,
|
|
3856
|
+
malformedAuthorityOrPort: baseMalformed,
|
|
3857
|
+
malformedPercentEncoding: baseMalformedPercentEncoding,
|
|
3858
|
+
malformedSchemeSpecific: baseMalformedSchemeSpecific,
|
|
3859
|
+
malformedHost: baseMalformedHost,
|
|
3860
|
+
malformedScheme: baseMalformedScheme
|
|
3861
|
+
} = parseWithStatus(baseURI, schemelessOptions);
|
|
3862
|
+
const {
|
|
3863
|
+
parsed: relativeParsed,
|
|
3864
|
+
malformedAuthorityOrPort: relativeMalformed,
|
|
3865
|
+
malformedPercentEncoding: relativeMalformedPercentEncoding,
|
|
3866
|
+
malformedSchemeSpecific: relativeMalformedSchemeSpecific,
|
|
3867
|
+
malformedHost: relativeMalformedHost,
|
|
3868
|
+
malformedScheme: relativeMalformedScheme
|
|
3869
|
+
} = parseWithStatus(relativeURI, schemelessOptions);
|
|
3870
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) {
|
|
3658
3871
|
throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
3659
3872
|
}
|
|
3660
3873
|
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
3874
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
3875
|
+
const resolvedHost = resolved.host;
|
|
3876
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
3877
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
3878
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
3879
|
+
if (resolved.error && !encodedASCIIHost) {
|
|
3880
|
+
throw new Error(resolved.error);
|
|
3881
|
+
}
|
|
3661
3882
|
schemelessOptions.skipEscape = true;
|
|
3662
3883
|
return serialize(resolved, schemelessOptions);
|
|
3663
3884
|
}
|
|
@@ -3717,7 +3938,7 @@ var require_fast_uri = __commonJS({
|
|
|
3717
3938
|
function equal(uriA, uriB, options) {
|
|
3718
3939
|
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3719
3940
|
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3720
|
-
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA
|
|
3941
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
3721
3942
|
}
|
|
3722
3943
|
function serialize(cmpts, opts) {
|
|
3723
3944
|
const component = {
|
|
@@ -3738,19 +3959,22 @@ var require_fast_uri = __commonJS({
|
|
|
3738
3959
|
};
|
|
3739
3960
|
const options = Object.assign({}, opts);
|
|
3740
3961
|
const uriTokens = [];
|
|
3962
|
+
if (component.scheme) {
|
|
3963
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3964
|
+
}
|
|
3741
3965
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
3742
3966
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3967
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
3968
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
3743
3969
|
if (component.path !== void 0) {
|
|
3744
3970
|
if (!options.skipEscape) {
|
|
3745
|
-
component.path =
|
|
3746
|
-
if (component.scheme !== void 0) {
|
|
3747
|
-
component.path = component.path.split("%3A").join(":");
|
|
3748
|
-
}
|
|
3971
|
+
component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
3749
3972
|
} else {
|
|
3750
3973
|
component.path = normalizePercentEncoding(component.path);
|
|
3751
3974
|
}
|
|
3752
3975
|
}
|
|
3753
3976
|
if (options.reference !== "suffix" && component.scheme) {
|
|
3977
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
3754
3978
|
uriTokens.push(component.scheme, ":");
|
|
3755
3979
|
}
|
|
3756
3980
|
const authority = recomposeAuthority(component);
|
|
@@ -3768,16 +3992,19 @@ var require_fast_uri = __commonJS({
|
|
|
3768
3992
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
|
|
3769
3993
|
s2 = removeDotSegments(s2);
|
|
3770
3994
|
}
|
|
3995
|
+
if (pathNoScheme) {
|
|
3996
|
+
s2 = serializePathEncoding(s2, true);
|
|
3997
|
+
}
|
|
3771
3998
|
if (authority === void 0 && s2[0] === "/" && s2[1] === "/") {
|
|
3772
3999
|
s2 = "/%2F" + s2.slice(2);
|
|
3773
4000
|
}
|
|
3774
4001
|
uriTokens.push(s2);
|
|
3775
4002
|
}
|
|
3776
4003
|
if (component.query !== void 0) {
|
|
3777
|
-
uriTokens.push("?", component.query);
|
|
4004
|
+
uriTokens.push("?", encodeQuery(component.query));
|
|
3778
4005
|
}
|
|
3779
4006
|
if (component.fragment !== void 0) {
|
|
3780
|
-
uriTokens.push("#", component.fragment);
|
|
4007
|
+
uriTokens.push("#", encodeFragment(component.fragment));
|
|
3781
4008
|
}
|
|
3782
4009
|
return uriTokens.join("");
|
|
3783
4010
|
}
|
|
@@ -3793,6 +4020,35 @@ var require_fast_uri = __commonJS({
|
|
|
3793
4020
|
}
|
|
3794
4021
|
return void 0;
|
|
3795
4022
|
}
|
|
4023
|
+
function hasMalformedPercentEncoding(component) {
|
|
4024
|
+
if (component === void 0) return false;
|
|
4025
|
+
let percent = component.indexOf("%");
|
|
4026
|
+
while (percent !== -1) {
|
|
4027
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) {
|
|
4028
|
+
return true;
|
|
4029
|
+
}
|
|
4030
|
+
percent = component.indexOf("%", percent + 3);
|
|
4031
|
+
}
|
|
4032
|
+
return false;
|
|
4033
|
+
}
|
|
4034
|
+
function isIPLiteral(host) {
|
|
4035
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
4036
|
+
}
|
|
4037
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
4038
|
+
const host = matches[4];
|
|
4039
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
4040
|
+
}
|
|
4041
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
4042
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
4043
|
+
try {
|
|
4044
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
4045
|
+
} catch (e2) {
|
|
4046
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e2;
|
|
4047
|
+
return true;
|
|
4048
|
+
}
|
|
4049
|
+
}
|
|
4050
|
+
return false;
|
|
4051
|
+
}
|
|
3796
4052
|
function parseWithStatus(uri, opts) {
|
|
3797
4053
|
const options = Object.assign({}, opts);
|
|
3798
4054
|
const parsed = {
|
|
@@ -3805,6 +4061,11 @@ var require_fast_uri = __commonJS({
|
|
|
3805
4061
|
fragment: void 0
|
|
3806
4062
|
};
|
|
3807
4063
|
let malformedAuthorityOrPort = false;
|
|
4064
|
+
let malformedPercentEncoding = false;
|
|
4065
|
+
let malformedSchemeSpecific = false;
|
|
4066
|
+
let malformedHost = false;
|
|
4067
|
+
let malformedIPLiteral = false;
|
|
4068
|
+
let malformedScheme = false;
|
|
3808
4069
|
let isIP = false;
|
|
3809
4070
|
if (options.reference === "suffix") {
|
|
3810
4071
|
if (options.scheme) {
|
|
@@ -3841,6 +4102,19 @@ var require_fast_uri = __commonJS({
|
|
|
3841
4102
|
parsed.path = matches[6] || "";
|
|
3842
4103
|
parsed.query = matches[7];
|
|
3843
4104
|
parsed.fragment = matches[8];
|
|
4105
|
+
if (parsed.scheme !== void 0) {
|
|
4106
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
4107
|
+
if (VALID_SCHEME.test(decodedScheme)) {
|
|
4108
|
+
parsed.scheme = decodedScheme.toLowerCase();
|
|
4109
|
+
} else {
|
|
4110
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
4111
|
+
malformedScheme = true;
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
4115
|
+
if (malformedPercentEncoding) {
|
|
4116
|
+
parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
4117
|
+
}
|
|
3844
4118
|
if (isNaN(parsed.port)) {
|
|
3845
4119
|
parsed.port = matches[5];
|
|
3846
4120
|
}
|
|
@@ -3852,9 +4126,16 @@ var require_fast_uri = __commonJS({
|
|
|
3852
4126
|
if (parsed.host) {
|
|
3853
4127
|
const ipv4result = isIPv4(parsed.host);
|
|
3854
4128
|
if (ipv4result === false) {
|
|
4129
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
4130
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
3855
4131
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
3856
|
-
|
|
3857
|
-
|
|
4132
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
4133
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
4134
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
4135
|
+
if (malformedIPLiteral) {
|
|
4136
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
4137
|
+
malformedAuthorityOrPort = true;
|
|
4138
|
+
}
|
|
3858
4139
|
} else {
|
|
3859
4140
|
isIP = true;
|
|
3860
4141
|
}
|
|
@@ -3872,42 +4153,36 @@ var require_fast_uri = __commonJS({
|
|
|
3872
4153
|
parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
3873
4154
|
}
|
|
3874
4155
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
3875
|
-
if (!
|
|
3876
|
-
|
|
3877
|
-
try {
|
|
3878
|
-
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3879
|
-
} catch (e2) {
|
|
3880
|
-
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e2;
|
|
3881
|
-
}
|
|
3882
|
-
}
|
|
4156
|
+
if (!malformedIPLiteral) {
|
|
4157
|
+
malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
3883
4158
|
}
|
|
3884
4159
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
3885
4160
|
if (uri.indexOf("%") !== -1) {
|
|
3886
|
-
if (parsed.
|
|
3887
|
-
parsed.
|
|
3888
|
-
|
|
3889
|
-
if (parsed.host !== void 0) {
|
|
3890
|
-
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
4161
|
+
if (parsed.host !== void 0 && !malformedIPLiteral) {
|
|
4162
|
+
const host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
4163
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
3891
4164
|
}
|
|
3892
4165
|
}
|
|
3893
4166
|
if (parsed.path) {
|
|
3894
4167
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3895
4168
|
}
|
|
4169
|
+
if (parsed.query) {
|
|
4170
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
4171
|
+
}
|
|
3896
4172
|
if (parsed.fragment) {
|
|
3897
|
-
|
|
3898
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3899
|
-
} catch {
|
|
3900
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3901
|
-
}
|
|
4173
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3902
4174
|
}
|
|
3903
4175
|
}
|
|
3904
4176
|
if (schemeHandler && schemeHandler.parse) {
|
|
3905
4177
|
schemeHandler.parse(parsed, options);
|
|
4178
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) {
|
|
4179
|
+
malformedSchemeSpecific = true;
|
|
4180
|
+
}
|
|
3906
4181
|
}
|
|
3907
4182
|
} else {
|
|
3908
4183
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3909
4184
|
}
|
|
3910
|
-
return { parsed, malformedAuthorityOrPort };
|
|
4185
|
+
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
3911
4186
|
}
|
|
3912
4187
|
function parse3(uri, opts) {
|
|
3913
4188
|
return parseWithStatus(uri, opts).parsed;
|
|
@@ -3916,20 +4191,28 @@ var require_fast_uri = __commonJS({
|
|
|
3916
4191
|
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3917
4192
|
}
|
|
3918
4193
|
function normalizeStringWithStatus(uri, opts) {
|
|
3919
|
-
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
4194
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
3920
4195
|
return {
|
|
3921
|
-
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3922
|
-
malformedAuthorityOrPort
|
|
4196
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
4197
|
+
malformedAuthorityOrPort,
|
|
4198
|
+
malformedPercentEncoding,
|
|
4199
|
+
malformedSchemeSpecific,
|
|
4200
|
+
malformedHost,
|
|
4201
|
+
malformedScheme
|
|
3923
4202
|
};
|
|
3924
4203
|
}
|
|
3925
4204
|
function normalizeComparableURI(uri, opts) {
|
|
3926
|
-
if (typeof uri
|
|
3927
|
-
|
|
3928
|
-
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
4205
|
+
if (typeof uri !== "string" && typeof uri !== "object") {
|
|
4206
|
+
return void 0;
|
|
3929
4207
|
}
|
|
3930
|
-
|
|
3931
|
-
|
|
4208
|
+
let value;
|
|
4209
|
+
try {
|
|
4210
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
4211
|
+
} catch {
|
|
4212
|
+
return void 0;
|
|
3932
4213
|
}
|
|
4214
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
4215
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
3933
4216
|
}
|
|
3934
4217
|
var fastUri = {
|
|
3935
4218
|
SCHEMES,
|
|
@@ -10599,7 +10882,7 @@ function getVerbosityLevel() {
|
|
|
10599
10882
|
function info(e2) {
|
|
10600
10883
|
zo >= Fo.INFOS && console.info(`Info: ${e2}`);
|
|
10601
10884
|
}
|
|
10602
|
-
function
|
|
10885
|
+
function warn2(e2) {
|
|
10603
10886
|
zo >= Fo.WARNINGS && console.warn(`Warning: ${e2}`);
|
|
10604
10887
|
}
|
|
10605
10888
|
function unreachable(e2) {
|
|
@@ -10747,7 +11030,7 @@ function getFilenameFromUrl(e2) {
|
|
|
10747
11030
|
}
|
|
10748
11031
|
function getPdfFilenameFromUrl(e2, t2 = `document.pdf`) {
|
|
10749
11032
|
if (typeof e2 != `string`) return t2;
|
|
10750
|
-
if (isDataScheme(e2)) return
|
|
11033
|
+
if (isDataScheme(e2)) return warn2(`getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.`), t2;
|
|
10751
11034
|
let getURL = (e3) => {
|
|
10752
11035
|
try {
|
|
10753
11036
|
return new URL(e3);
|
|
@@ -10815,7 +11098,7 @@ function getRGBA(e2) {
|
|
|
10815
11098
|
}
|
|
10816
11099
|
function getRGB(e2) {
|
|
10817
11100
|
let t2 = getRGBA(e2);
|
|
10818
|
-
return t2 ? t2.slice(0, 3) : (
|
|
11101
|
+
return t2 ? t2.slice(0, 3) : (warn2(`Not a valid color format: "${e2}"`), [0, 0, 0]);
|
|
10819
11102
|
}
|
|
10820
11103
|
function getColorValues(e2) {
|
|
10821
11104
|
let t2 = document.createElement(`span`);
|
|
@@ -10952,7 +11235,7 @@ function makePathFromDrawOPS(e2) {
|
|
|
10952
11235
|
t2.closePath();
|
|
10953
11236
|
break;
|
|
10954
11237
|
default:
|
|
10955
|
-
|
|
11238
|
+
warn2(`Unrecognized drawing path operator: ${e2[n2 - 1]}`);
|
|
10956
11239
|
break;
|
|
10957
11240
|
}
|
|
10958
11241
|
return t2;
|
|
@@ -34522,15 +34805,15 @@ var init_pdfjs = __esm({
|
|
|
34522
34805
|
Wo = class XfaText {
|
|
34523
34806
|
static textContent(e2) {
|
|
34524
34807
|
let t2 = [], n2 = { items: t2, styles: /* @__PURE__ */ Object.create(null) };
|
|
34525
|
-
function
|
|
34808
|
+
function walk2(e3) {
|
|
34526
34809
|
if (!e3) return;
|
|
34527
34810
|
let n3 = null, r2 = e3.name;
|
|
34528
34811
|
if (r2 === `#text`) n3 = e3.value;
|
|
34529
34812
|
else if (XfaText.shouldBuildText(r2)) e3?.attributes?.textContent ? n3 = e3.attributes.textContent : e3.value && (n3 = e3.value);
|
|
34530
34813
|
else return;
|
|
34531
|
-
if (n3 !== null && t2.push({ str: n3 }), e3.children) for (let t3 of e3.children)
|
|
34814
|
+
if (n3 !== null && t2.push({ str: n3 }), e3.children) for (let t3 of e3.children) walk2(t3);
|
|
34532
34815
|
}
|
|
34533
|
-
return
|
|
34816
|
+
return walk2(e2), n2;
|
|
34534
34817
|
}
|
|
34535
34818
|
static shouldBuildText(e2) {
|
|
34536
34819
|
return e2 !== `textarea` && e2 !== `input` && e2 !== `option` && e2 !== `select`;
|
|
@@ -34659,10 +34942,10 @@ var init_pdfjs = __esm({
|
|
|
34659
34942
|
#e = /* @__PURE__ */ new Map();
|
|
34660
34943
|
times = [];
|
|
34661
34944
|
time(e2) {
|
|
34662
|
-
this.#e.has(e2) &&
|
|
34945
|
+
this.#e.has(e2) && warn2(`Timer is already running for ${e2}`), this.#e.set(e2, Date.now());
|
|
34663
34946
|
}
|
|
34664
34947
|
timeEnd(e2) {
|
|
34665
|
-
this.#e.has(e2) ||
|
|
34948
|
+
this.#e.has(e2) || warn2(`Timer has not been started for ${e2}`), this.times.push({ name: e2, start: this.#e.get(e2), end: Date.now() }), this.#e.delete(e2);
|
|
34666
34949
|
}
|
|
34667
34950
|
toString() {
|
|
34668
34951
|
let e2 = Math.max(...this.times.map((e3) => e3.name.length));
|
|
@@ -34987,7 +35270,7 @@ var init_pdfjs = __esm({
|
|
|
34987
35270
|
} else n2.bitmap = await createImageBitmap(e3);
|
|
34988
35271
|
n2.refCounter = 1;
|
|
34989
35272
|
} catch (e3) {
|
|
34990
|
-
|
|
35273
|
+
warn2(e3), n2 = null;
|
|
34991
35274
|
}
|
|
34992
35275
|
return this.#n.set(e2, n2), n2 && this.#n.set(n2.id, n2), n2;
|
|
34993
35276
|
}
|
|
@@ -35126,12 +35409,12 @@ var init_pdfjs = __esm({
|
|
|
35126
35409
|
continue;
|
|
35127
35410
|
}
|
|
35128
35411
|
if (t2 !== null) {
|
|
35129
|
-
|
|
35412
|
+
warn2(`KeyboardManager: multiple keys in shortcut "${e2}"`);
|
|
35130
35413
|
break;
|
|
35131
35414
|
}
|
|
35132
35415
|
t2 = i2 === `SPACE` ? ` ` : r2;
|
|
35133
35416
|
}
|
|
35134
|
-
return t2 === null &&
|
|
35417
|
+
return t2 === null && warn2(`KeyboardManager: no key found in shortcut "${e2}"`), [t2, n2];
|
|
35135
35418
|
}
|
|
35136
35419
|
static #t(e2) {
|
|
35137
35420
|
let t2 = /^(?:Key([A-Z])|(?:Digit|Numpad)(\d))$/.exec(e2);
|
|
@@ -35562,7 +35845,7 @@ var init_pdfjs = __esm({
|
|
|
35562
35845
|
try {
|
|
35563
35846
|
n2 = JSON.parse(n2);
|
|
35564
35847
|
} catch (e3) {
|
|
35565
|
-
|
|
35848
|
+
warn2(`paste: "${e3.message}".`);
|
|
35566
35849
|
return;
|
|
35567
35850
|
}
|
|
35568
35851
|
if (!Array.isArray(n2)) return;
|
|
@@ -35583,7 +35866,7 @@ var init_pdfjs = __esm({
|
|
|
35583
35866
|
};
|
|
35584
35867
|
this.addCommands({ cmd, undo, mustExec: true });
|
|
35585
35868
|
} catch (e3) {
|
|
35586
|
-
|
|
35869
|
+
warn2(`paste: "${e3.message}".`);
|
|
35587
35870
|
}
|
|
35588
35871
|
}
|
|
35589
35872
|
keydown(e2) {
|
|
@@ -37788,7 +38071,7 @@ var init_pdfjs = __esm({
|
|
|
37788
38071
|
try {
|
|
37789
38072
|
await a2.load(), this.#e.add(t3), n2?.(e2);
|
|
37790
38073
|
} catch {
|
|
37791
|
-
|
|
38074
|
+
warn2(`Cannot load system font: ${e2.baseFontName}, installing it could help to improve PDF rendering.`), this.removeNativeFontFace(a2);
|
|
37792
38075
|
}
|
|
37793
38076
|
return;
|
|
37794
38077
|
}
|
|
@@ -37808,7 +38091,7 @@ var init_pdfjs = __esm({
|
|
|
37808
38091
|
try {
|
|
37809
38092
|
await t3.loaded;
|
|
37810
38093
|
} catch (n2) {
|
|
37811
|
-
throw
|
|
38094
|
+
throw warn2(`Failed to load font '${t3.family}': '${n2}'.`), e2.disableFontFace = true, n2;
|
|
37812
38095
|
}
|
|
37813
38096
|
}
|
|
37814
38097
|
return;
|
|
@@ -37859,7 +38142,7 @@ var init_pdfjs = __esm({
|
|
|
37859
38142
|
let a2 = i2.getContext(`2d`), o2 = 0;
|
|
37860
38143
|
function isFontReady(e3, t3) {
|
|
37861
38144
|
if (++o2 > 30) {
|
|
37862
|
-
|
|
38145
|
+
warn2(`Load test font never loaded.`), t3();
|
|
37863
38146
|
return;
|
|
37864
38147
|
}
|
|
37865
38148
|
if (a2.font = `30px ` + e3, a2.fillText(`.`, 0, 20), a2.getImageData(0, 0, 1, 1).data[3] > 0) {
|
|
@@ -37918,7 +38201,7 @@ var init_pdfjs = __esm({
|
|
|
37918
38201
|
try {
|
|
37919
38202
|
r2 = e2.get(n2);
|
|
37920
38203
|
} catch (e3) {
|
|
37921
|
-
|
|
38204
|
+
warn2(`getPathGenerator - ignoring character: "${e3}".`);
|
|
37922
38205
|
}
|
|
37923
38206
|
let i2 = makePathFromDrawOPS(r2?.path);
|
|
37924
38207
|
return this.fontExtraProperties || e2.delete(n2), this.compiledGlyphs[t2] = i2;
|
|
@@ -38275,7 +38558,7 @@ var init_pdfjs = __esm({
|
|
|
38275
38558
|
if (n2?.signal instanceof AbortSignal) {
|
|
38276
38559
|
let { signal: r2 } = n2;
|
|
38277
38560
|
if (r2.aborted) {
|
|
38278
|
-
|
|
38561
|
+
warn2("LoopbackPort - cannot use an `aborted` signal.");
|
|
38279
38562
|
return;
|
|
38280
38563
|
}
|
|
38281
38564
|
let onAbort = () => this.removeEventListener(e2, t2);
|
|
@@ -38567,7 +38850,7 @@ var init_pdfjs = __esm({
|
|
|
38567
38850
|
if (this.#e === void 0) {
|
|
38568
38851
|
this.#e = ``;
|
|
38569
38852
|
let e3 = this.#i.URL;
|
|
38570
|
-
e3 !== this.#i.baseURI && (isDataScheme(e3) ?
|
|
38853
|
+
e3 !== this.#i.baseURI && (isDataScheme(e3) ? warn2(`#createUrl: ignore "data:"-URL for performance reasons.`) : this.#e = updateUrlHash(e3, ``));
|
|
38571
38854
|
}
|
|
38572
38855
|
return `url(${this.#e}#${e2})`;
|
|
38573
38856
|
}
|
|
@@ -39508,7 +39791,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
39508
39791
|
this.dependencyTracker?.recordSimpleData(`font`, e2).recordSimpleDataFromNamed(`fontObj`, t2, e2);
|
|
39509
39792
|
let r2 = this.commonObjs.get(t2), i2 = this.current;
|
|
39510
39793
|
if (!r2) throw Error(`Can't find font for ${t2}`);
|
|
39511
|
-
if (i2.fontMatrix = r2.fontMatrix || xo, (i2.fontMatrix[0] === 0 || i2.fontMatrix[3] === 0) &&
|
|
39794
|
+
if (i2.fontMatrix = r2.fontMatrix || xo, (i2.fontMatrix[0] === 0 || i2.fontMatrix[3] === 0) && warn2(`Invalid font matrix for font ` + t2), n2 < 0 ? (n2 = -n2, i2.fontDirection = -1) : i2.fontDirection = 1, this.current.font = r2, this.current.fontSize = n2, r2.isType3Font) return;
|
|
39512
39795
|
let a2 = r2.loadedName || `sans-serif`, o2 = r2.systemFontInfo?.css || `"${a2}", ${r2.fallbackName}`, s2 = `normal`;
|
|
39513
39796
|
r2.black ? s2 = `900` : r2.bold && (s2 = `bold`);
|
|
39514
39797
|
let c2 = r2.italic ? `italic` : `normal`, l2 = MathClamp(n2, 16, 100);
|
|
@@ -39650,7 +39933,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
39650
39933
|
continue;
|
|
39651
39934
|
}
|
|
39652
39935
|
let e3 = (h2.isSpace ? l2 : 0) + c2, o3 = i2.charProcOperatorList[h2.operatorListId];
|
|
39653
|
-
o3 ? this.contentVisible && (this.save(), o3.fnArray[0] === Io.setCharWidth && (r2.fillAlpha = r2.strokeAlpha = 1, n2.globalAlpha = 1), n2.scale(a2, a2), n2.transform(...d2), this.executeOperatorList(o3), this.restore()) :
|
|
39936
|
+
o3 ? this.contentVisible && (this.save(), o3.fnArray[0] === Io.setCharWidth && (r2.fillAlpha = r2.strokeAlpha = 1, n2.globalAlpha = 1), n2.scale(a2, a2), n2.transform(...d2), this.executeOperatorList(o3), this.restore()) : warn2(`Type3 character "${h2.operatorListId}" is not available.`);
|
|
39654
39937
|
let f3 = [h2.width, 0];
|
|
39655
39938
|
Util.applyTransform(f3, d2), g2 = f3[0] * a2 + e3, n2.translate(g2, 0), r2.x += g2 * u2;
|
|
39656
39939
|
}
|
|
@@ -39870,7 +40153,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
39870
40153
|
if (!this.contentVisible) return;
|
|
39871
40154
|
let n2 = this.getObject(e2, t2);
|
|
39872
40155
|
if (!n2) {
|
|
39873
|
-
|
|
40156
|
+
warn2(`Dependent image isn't ready yet`);
|
|
39874
40157
|
return;
|
|
39875
40158
|
}
|
|
39876
40159
|
this.paintInlineImageXObject(e2, n2);
|
|
@@ -39879,7 +40162,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
39879
40162
|
if (!this.contentVisible) return;
|
|
39880
40163
|
let a2 = this.getObject(e2, t2);
|
|
39881
40164
|
if (!a2) {
|
|
39882
|
-
|
|
40165
|
+
warn2(`Dependent image isn't ready yet`);
|
|
39883
40166
|
return;
|
|
39884
40167
|
}
|
|
39885
40168
|
let o2 = a2.width, s2 = a2.height, c2 = [];
|
|
@@ -40267,7 +40550,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
40267
40550
|
let i2 = network_getArrayBuffer(e2.response);
|
|
40268
40551
|
if (r2 === 206) {
|
|
40269
40552
|
let t3 = e2.getResponseHeader(`Content-Range`);
|
|
40270
|
-
/bytes \d+-\d+\/\d+/.test(t3) ? n2.onDone(i2) : (
|
|
40553
|
+
/bytes \d+-\d+\/\d+/.test(t3) ? n2.onDone(i2) : (warn2(`Missing or invalid "Content-Range" header.`), n2.onError(0));
|
|
40271
40554
|
} else i2 ? n2.onDone(i2) : n2.onError(e2.status);
|
|
40272
40555
|
}
|
|
40273
40556
|
_abortRequest(e2) {
|
|
@@ -40497,7 +40780,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
40497
40780
|
let t3 = e2[r2], i2;
|
|
40498
40781
|
if (Array.isArray(t3)) i2 = this.#a(t3);
|
|
40499
40782
|
else if (this.#t.has(t3)) i2 = this.#t.get(t3).visible;
|
|
40500
|
-
else return
|
|
40783
|
+
else return warn2(`Optional content group not found: ${t3}`), true;
|
|
40501
40784
|
switch (n2) {
|
|
40502
40785
|
case `And`:
|
|
40503
40786
|
if (!i2) return false;
|
|
@@ -40516,42 +40799,42 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
40516
40799
|
isVisible(e2) {
|
|
40517
40800
|
if (this.#t.size === 0) return true;
|
|
40518
40801
|
if (!e2) return info(`Optional content group not defined.`), true;
|
|
40519
|
-
if (e2.type === `OCG`) return this.#t.has(e2.id) ? this.#t.get(e2.id).visible : (
|
|
40802
|
+
if (e2.type === `OCG`) return this.#t.has(e2.id) ? this.#t.get(e2.id).visible : (warn2(`Optional content group not found: ${e2.id}`), true);
|
|
40520
40803
|
if (e2.type === `OCMD`) {
|
|
40521
40804
|
if (e2.expression) return this.#a(e2.expression);
|
|
40522
40805
|
if (!e2.policy || e2.policy === `AnyOn`) {
|
|
40523
40806
|
for (let t2 of e2.ids) {
|
|
40524
|
-
if (!this.#t.has(t2)) return
|
|
40807
|
+
if (!this.#t.has(t2)) return warn2(`Optional content group not found: ${t2}`), true;
|
|
40525
40808
|
if (this.#t.get(t2).visible) return true;
|
|
40526
40809
|
}
|
|
40527
40810
|
return false;
|
|
40528
40811
|
} else if (e2.policy === `AllOn`) {
|
|
40529
40812
|
for (let t2 of e2.ids) {
|
|
40530
|
-
if (!this.#t.has(t2)) return
|
|
40813
|
+
if (!this.#t.has(t2)) return warn2(`Optional content group not found: ${t2}`), true;
|
|
40531
40814
|
if (!this.#t.get(t2).visible) return false;
|
|
40532
40815
|
}
|
|
40533
40816
|
return true;
|
|
40534
40817
|
} else if (e2.policy === `AnyOff`) {
|
|
40535
40818
|
for (let t2 of e2.ids) {
|
|
40536
|
-
if (!this.#t.has(t2)) return
|
|
40819
|
+
if (!this.#t.has(t2)) return warn2(`Optional content group not found: ${t2}`), true;
|
|
40537
40820
|
if (!this.#t.get(t2).visible) return true;
|
|
40538
40821
|
}
|
|
40539
40822
|
return false;
|
|
40540
40823
|
} else if (e2.policy === `AllOff`) {
|
|
40541
40824
|
for (let t2 of e2.ids) {
|
|
40542
|
-
if (!this.#t.has(t2)) return
|
|
40825
|
+
if (!this.#t.has(t2)) return warn2(`Optional content group not found: ${t2}`), true;
|
|
40543
40826
|
if (this.#t.get(t2).visible) return false;
|
|
40544
40827
|
}
|
|
40545
40828
|
return true;
|
|
40546
40829
|
}
|
|
40547
|
-
return
|
|
40830
|
+
return warn2(`Unknown optional content policy ${e2.policy}.`), true;
|
|
40548
40831
|
}
|
|
40549
|
-
return
|
|
40832
|
+
return warn2(`Unknown group type ${e2.type}.`), true;
|
|
40550
40833
|
}
|
|
40551
40834
|
setVisibility(e2, t2 = true, n2 = true) {
|
|
40552
40835
|
let r2 = this.#t.get(e2);
|
|
40553
40836
|
if (!r2) {
|
|
40554
|
-
|
|
40837
|
+
warn2(`Optional content group not found: ${e2}`);
|
|
40555
40838
|
return;
|
|
40556
40839
|
}
|
|
40557
40840
|
if (n2 && t2 && r2.rbGroups.length) for (let t3 of r2.rbGroups) for (let n3 of t3) n3 !== e2 && this.#t.get(n3)?._setVisible(ks, false, true);
|
|
@@ -40847,7 +41130,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
40847
41130
|
let t2 = this.#g, n2 = this.#m;
|
|
40848
41131
|
for (let r2 of e2) {
|
|
40849
41132
|
if (t2.length > 1e5) {
|
|
40850
|
-
|
|
41133
|
+
warn2(`Ignoring additional textDivs for performance reasons.`), this.#n = true;
|
|
40851
41134
|
return;
|
|
40852
41135
|
}
|
|
40853
41136
|
if (r2.str === void 0) {
|
|
@@ -40924,7 +41207,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
40924
41207
|
let a2 = i2.measureText(``), o2 = a2.fontBoundingBoxAscent, s2 = Math.abs(a2.fontBoundingBoxDescent);
|
|
40925
41208
|
i2.canvas.width = i2.canvas.height = 0;
|
|
40926
41209
|
let c2 = 0.8;
|
|
40927
|
-
return o2 ? c2 = o2 / (o2 + s2) : (FeatureTest.platform.isFirefox &&
|
|
41210
|
+
return o2 ? c2 = o2 / (o2 + s2) : (FeatureTest.platform.isFirefox && warn2("Enable the `dom.textMetrics.fontBoundingBox.enabled` preference in `about:config` to improve TextLayer rendering."), t2.ascent ? c2 = t2.ascent : t2.descent && (c2 = 1 + t2.descent)), this.#y.set(e2, c2), c2;
|
|
40928
41211
|
}
|
|
40929
41212
|
};
|
|
40930
41213
|
Ns = class PDFDocumentLoadingTask {
|
|
@@ -41358,7 +41641,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
41358
41641
|
this.#u();
|
|
41359
41642
|
}
|
|
41360
41643
|
#u() {
|
|
41361
|
-
PDFWorker.#a ||= (
|
|
41644
|
+
PDFWorker.#a ||= (warn2(`Setting up fake worker.`), true), PDFWorker._setupFakeWorkerGlobal.then((e2) => {
|
|
41362
41645
|
if (this.destroyed) {
|
|
41363
41646
|
this.#e.reject(Error(`Worker was destroyed`));
|
|
41364
41647
|
return;
|
|
@@ -41435,7 +41718,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
41435
41718
|
a2 = wo.PRINT;
|
|
41436
41719
|
break;
|
|
41437
41720
|
default:
|
|
41438
|
-
|
|
41721
|
+
warn2(`getRenderingIntent - invalid intent: ${e2}`);
|
|
41439
41722
|
}
|
|
41440
41723
|
let s2 = a2 & wo.PRINT && n2 instanceof PrintAnnotationStorage ? n2 : this.annotationStorage;
|
|
41441
41724
|
switch (t2) {
|
|
@@ -41451,7 +41734,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
41451
41734
|
a2 += wo.ANNOTATIONS_STORAGE, o2 = s2.serializable;
|
|
41452
41735
|
break;
|
|
41453
41736
|
default:
|
|
41454
|
-
|
|
41737
|
+
warn2(`getRenderingIntent - invalid annotationMode: ${t2}`);
|
|
41455
41738
|
}
|
|
41456
41739
|
r2 && (a2 += wo.IS_EDITING), i2 && (a2 += wo.OPLIST);
|
|
41457
41740
|
let { ids: c2, hash: l2 } = s2.modifiedIds, u2 = [a2, o2.hash, l2];
|
|
@@ -41538,7 +41821,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
41538
41821
|
case `Font`:
|
|
41539
41822
|
if (`error` in r2) {
|
|
41540
41823
|
let e3 = r2.error;
|
|
41541
|
-
|
|
41824
|
+
warn2(`Error during font loading: ${e3}`), this.commonObjs.resolve(t3, e3);
|
|
41542
41825
|
break;
|
|
41543
41826
|
}
|
|
41544
41827
|
let i2 = new FontFaceObject(new FontInfo(r2), this._params.pdfBug && globalThis.FontInspector?.enabled ? (e3, t4) => globalThis.FontInspector.fontAdded(e3, t4) : null, r2.charProcOperatorList, r2.extra);
|
|
@@ -41599,7 +41882,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
41599
41882
|
return this.messageHandler.sendWithPromise(`GetData`, null);
|
|
41600
41883
|
}
|
|
41601
41884
|
saveDocument() {
|
|
41602
|
-
this.annotationStorage.size <= 0 &&
|
|
41885
|
+
this.annotationStorage.size <= 0 && warn2("saveDocument called while `annotationStorage` is empty, please use the getData-method instead.");
|
|
41603
41886
|
let { map: e2, transfer: t2 } = this.annotationStorage.serializable;
|
|
41604
41887
|
return this.messageHandler.sendWithPromise(`SaveDocument`, { isPureXfa: !!this._htmlForXfa, numPages: this._numPages, annotationStorage: e2, filename: this.#e?.filename ?? null }, t2).finally(() => {
|
|
41605
41888
|
this.annotationStorage.resetModified();
|
|
@@ -42188,10 +42471,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
42188
42471
|
a2.borderStyle = `dashed`;
|
|
42189
42472
|
break;
|
|
42190
42473
|
case Po.BEVELED:
|
|
42191
|
-
|
|
42474
|
+
warn2(`Unimplemented border style: beveled`);
|
|
42192
42475
|
break;
|
|
42193
42476
|
case Po.INSET:
|
|
42194
|
-
|
|
42477
|
+
warn2(`Unimplemented border style: inset`);
|
|
42195
42478
|
break;
|
|
42196
42479
|
case Po.UNDERLINE:
|
|
42197
42480
|
a2.borderBottomStyle = `solid`;
|
|
@@ -42311,7 +42594,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
42311
42594
|
if (e3 === -1 || i2 === t2) continue;
|
|
42312
42595
|
let r3 = typeof a2 == `string` ? a2 : null, o2 = document.querySelector(`[data-element-id="${i2}"]`);
|
|
42313
42596
|
if (o2 && !Hs.has(o2)) {
|
|
42314
|
-
|
|
42597
|
+
warn2(`_getElementsByName - element not allowed: ${i2}`);
|
|
42315
42598
|
continue;
|
|
42316
42599
|
}
|
|
42317
42600
|
n2.push({ id: i2, exportValue: r3, domElement: o2 });
|
|
@@ -42431,7 +42714,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
42431
42714
|
_bindResetFormAction(e2, t2) {
|
|
42432
42715
|
let n2 = e2.onclick;
|
|
42433
42716
|
if (n2 || (e2.href = this.linkService.getAnchorUrl(``)), this.#e(), !this._fieldObjects) {
|
|
42434
|
-
|
|
42717
|
+
warn2('_bindResetFormAction - "resetForm" action not supported, ensure that the `fieldObjects` parameter is provided.'), n2 || (e2.onclick = () => false);
|
|
42435
42718
|
return;
|
|
42436
42719
|
}
|
|
42437
42720
|
e2.onclick = () => {
|
|
@@ -42472,7 +42755,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
42472
42755
|
let n3 = document.querySelector(`[data-element-id="${t3}"]`);
|
|
42473
42756
|
if (n3) {
|
|
42474
42757
|
if (!Hs.has(n3)) {
|
|
42475
|
-
|
|
42758
|
+
warn2(`_bindResetFormAction - element not allowed: ${t3}`);
|
|
42476
42759
|
continue;
|
|
42477
42760
|
}
|
|
42478
42761
|
n3.dispatchEvent(new Event(`resetform`));
|
|
@@ -45413,7 +45696,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
45413
45696
|
}
|
|
45414
45697
|
return { areContours: d2, thickness: f2, outlines: h2, width: l2, height: u2 };
|
|
45415
45698
|
} catch (e3) {
|
|
45416
|
-
return
|
|
45699
|
+
return warn2(`decompressSignature: ${e3}`), null;
|
|
45417
45700
|
}
|
|
45418
45701
|
}
|
|
45419
45702
|
};
|
|
@@ -70950,12 +71233,98 @@ function messageOf(err) {
|
|
|
70950
71233
|
return String(err);
|
|
70951
71234
|
}
|
|
70952
71235
|
|
|
70953
|
-
// node_modules/@chrischall/mcp-utils/dist/response/
|
|
70954
|
-
|
|
70955
|
-
|
|
70956
|
-
|
|
70957
|
-
|
|
71236
|
+
// node_modules/@chrischall/mcp-utils/dist/response/view.js
|
|
71237
|
+
var VIEWS = ["compact", "full", "raw"];
|
|
71238
|
+
var DEFAULT_VIEW = "compact";
|
|
71239
|
+
var BLURB = {
|
|
71240
|
+
compact: '"compact" (default) drops fields the response already carries elsewhere',
|
|
71241
|
+
full: '"full" returns every field this server understands',
|
|
71242
|
+
raw: '"raw" returns the upstream payload unprojected'
|
|
71243
|
+
};
|
|
71244
|
+
function viewParam(honoured, opts = {}) {
|
|
71245
|
+
if (honoured.length < 2) {
|
|
71246
|
+
throw new Error("viewParam needs at least two rungs: a parameter offering one value decides nothing");
|
|
71247
|
+
}
|
|
71248
|
+
if (!honoured.includes("compact")) {
|
|
71249
|
+
throw new Error('viewParam must offer "compact": a tool with no cheap rung has nothing to default to');
|
|
71250
|
+
}
|
|
71251
|
+
const ordered = VIEWS.filter((v2) => honoured.includes(v2));
|
|
71252
|
+
const sentence = `Response shape: ${ordered.map((v2) => BLURB[v2]).join("; ")}.`;
|
|
71253
|
+
return external_exports.enum(Object.fromEntries(ordered.map((v2) => [v2, v2]))).optional().describe(opts.note ? `${sentence} ${opts.note}` : sentence);
|
|
71254
|
+
}
|
|
71255
|
+
function resolveView(value, honoured) {
|
|
71256
|
+
return value !== void 0 && honoured.includes(value) ? value : DEFAULT_VIEW;
|
|
71257
|
+
}
|
|
71258
|
+
function minifiedResult(data) {
|
|
71259
|
+
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
71260
|
+
}
|
|
71261
|
+
function projectOrRaw(value, project, opts) {
|
|
71262
|
+
try {
|
|
71263
|
+
const projected = project(value);
|
|
71264
|
+
if (projected === void 0) {
|
|
71265
|
+
warn(opts, "the projection produced nothing");
|
|
71266
|
+
return value;
|
|
71267
|
+
}
|
|
71268
|
+
return projected;
|
|
71269
|
+
} catch (error51) {
|
|
71270
|
+
warn(opts, error51 instanceof Error ? error51.message : String(error51));
|
|
71271
|
+
return value;
|
|
71272
|
+
}
|
|
71273
|
+
}
|
|
71274
|
+
function warn(opts, why) {
|
|
71275
|
+
console.error(`[${opts.label}] WARNING: could not project ${opts.context} (${why}); returning the unprojected payload. The upstream shape has probably changed \u2014 the projection needs updating.`);
|
|
71276
|
+
}
|
|
71277
|
+
|
|
71278
|
+
// node_modules/@chrischall/mcp-utils/dist/response/media.js
|
|
71279
|
+
var MEDIA_NOUN = "(?:avatar|picture|photo|thumbnail|thumb|image|icon|banner|profile_pic(?:ture)?|logo)";
|
|
71280
|
+
var MEDIA_QUALIFIER = "(?:primary|secondary|main|default|cover|hero|profile|master|rendered|small|medium|large|full|original|tall)";
|
|
71281
|
+
var MEDIA_KEY = new RegExp(`^(?:(?:${MEDIA_QUALIFIER}|${MEDIA_NOUN})[_-]?)?${MEDIA_NOUN}s?(?:[_-]?(?:link|uri|url|src)s?)?$`, "i");
|
|
71282
|
+
var MEDIA_URL = /^https?:\/\/[^\s]+?\.(png|jpe?g|gif|webp|svg|avif|bmp|ico)([?#]|$)/i;
|
|
71283
|
+
function stripMediaUrls(value, opts = {}) {
|
|
71284
|
+
const keep = normalizeRules(opts.keep ?? []);
|
|
71285
|
+
const drop = normalizeRules(opts.drop ?? []);
|
|
71286
|
+
return walk(value, keep, drop);
|
|
71287
|
+
}
|
|
71288
|
+
function normalizeRules(rules) {
|
|
71289
|
+
return rules.map((rule) => typeof rule === "string" ? rule.toLowerCase() : new RegExp(rule.source, rule.flags));
|
|
71290
|
+
}
|
|
71291
|
+
function matchesRule(key, rules) {
|
|
71292
|
+
const lower = key.toLowerCase();
|
|
71293
|
+
for (const rule of rules) {
|
|
71294
|
+
if (typeof rule === "string") {
|
|
71295
|
+
if (rule === lower)
|
|
71296
|
+
return true;
|
|
71297
|
+
continue;
|
|
71298
|
+
}
|
|
71299
|
+
rule.lastIndex = 0;
|
|
71300
|
+
if (rule.test(key))
|
|
71301
|
+
return true;
|
|
71302
|
+
}
|
|
71303
|
+
return false;
|
|
70958
71304
|
}
|
|
71305
|
+
function walk(value, keep, drop) {
|
|
71306
|
+
if (Array.isArray(value))
|
|
71307
|
+
return value.map((v2) => walk(v2, keep, drop));
|
|
71308
|
+
if (value === null || typeof value !== "object")
|
|
71309
|
+
return value;
|
|
71310
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
|
|
71311
|
+
return value;
|
|
71312
|
+
const out = {};
|
|
71313
|
+
for (const [key, v2] of Object.entries(value)) {
|
|
71314
|
+
if (matchesRule(key, keep)) {
|
|
71315
|
+
out[key] = v2;
|
|
71316
|
+
continue;
|
|
71317
|
+
}
|
|
71318
|
+
if (MEDIA_KEY.test(key) || matchesRule(key, drop))
|
|
71319
|
+
continue;
|
|
71320
|
+
if (typeof v2 === "string" && MEDIA_URL.test(v2))
|
|
71321
|
+
continue;
|
|
71322
|
+
out[key] = walk(v2, keep, drop);
|
|
71323
|
+
}
|
|
71324
|
+
return out;
|
|
71325
|
+
}
|
|
71326
|
+
|
|
71327
|
+
// node_modules/@chrischall/mcp-utils/dist/response/index.js
|
|
70959
71328
|
function imageResult(base643, mimeType) {
|
|
70960
71329
|
return {
|
|
70961
71330
|
content: [{ type: "image", data: base643, mimeType }]
|
|
@@ -71477,10 +71846,117 @@ var SplitwiseClient = class {
|
|
|
71477
71846
|
};
|
|
71478
71847
|
var client = new SplitwiseClient();
|
|
71479
71848
|
|
|
71849
|
+
// src/project.ts
|
|
71850
|
+
var SW_VIEWS = ["compact", "full"];
|
|
71851
|
+
var LABEL = "splitwise-mcp";
|
|
71852
|
+
function asDict(v2) {
|
|
71853
|
+
return v2 !== null && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
71854
|
+
}
|
|
71855
|
+
function asList(v2) {
|
|
71856
|
+
return Array.isArray(v2) ? v2 : [];
|
|
71857
|
+
}
|
|
71858
|
+
function nameOf(user) {
|
|
71859
|
+
if (!user) return void 0;
|
|
71860
|
+
const parts = [user.first_name, user.last_name].filter((p2) => typeof p2 === "string" && p2 !== "");
|
|
71861
|
+
return parts.length > 0 ? parts.join(" ") : void 0;
|
|
71862
|
+
}
|
|
71863
|
+
var PERSON_VIEW_NOTE = 'compact returns {id, name, email, registration_status, balance} per person \u2014 `name` is first_name + last_name joined, so the separate fields are on "full" only; "full" returns Splitwise\'s whole record.';
|
|
71864
|
+
function compactPerson(raw) {
|
|
71865
|
+
const u2 = asDict(raw) ?? {};
|
|
71866
|
+
return pruneUndefined({
|
|
71867
|
+
id: u2.id,
|
|
71868
|
+
name: nameOf(u2),
|
|
71869
|
+
email: u2.email,
|
|
71870
|
+
registration_status: u2.registration_status,
|
|
71871
|
+
balance: asList(u2.balance).length > 0 ? u2.balance : void 0
|
|
71872
|
+
});
|
|
71873
|
+
}
|
|
71874
|
+
function compactGroup(raw) {
|
|
71875
|
+
const g2 = asDict(raw) ?? {};
|
|
71876
|
+
return pruneUndefined({
|
|
71877
|
+
id: g2.id,
|
|
71878
|
+
name: g2.name,
|
|
71879
|
+
group_type: g2.group_type,
|
|
71880
|
+
updated_at: g2.updated_at,
|
|
71881
|
+
members: asList(g2.members).map(compactPerson),
|
|
71882
|
+
simplified_debts: asList(g2.simplified_debts).length > 0 ? g2.simplified_debts : void 0,
|
|
71883
|
+
invite_link: g2.invite_link
|
|
71884
|
+
});
|
|
71885
|
+
}
|
|
71886
|
+
function compactExpense(raw) {
|
|
71887
|
+
const e2 = asDict(raw) ?? {};
|
|
71888
|
+
const receipt = asDict(e2.receipt);
|
|
71889
|
+
const original = receipt?.original;
|
|
71890
|
+
return pruneUndefined({
|
|
71891
|
+
id: e2.id,
|
|
71892
|
+
group_id: e2.group_id,
|
|
71893
|
+
description: e2.description,
|
|
71894
|
+
details: e2.details,
|
|
71895
|
+
cost: e2.cost,
|
|
71896
|
+
currency_code: e2.currency_code,
|
|
71897
|
+
date: e2.date,
|
|
71898
|
+
category: asDict(e2.category)?.name,
|
|
71899
|
+
payment: e2.payment === true ? true : void 0,
|
|
71900
|
+
created_by: nameOf(asDict(e2.created_by)),
|
|
71901
|
+
updated_at: e2.updated_at,
|
|
71902
|
+
// Kept only when set. A deleted expense still comes back from the list
|
|
71903
|
+
// endpoint, and a caller that cannot see `deleted_at` will count it.
|
|
71904
|
+
deleted_at: e2.deleted_at ?? void 0,
|
|
71905
|
+
comments_count: e2.comments_count,
|
|
71906
|
+
repayments: e2.repayments,
|
|
71907
|
+
users: asList(e2.users).map((entry) => {
|
|
71908
|
+
const u2 = asDict(entry) ?? {};
|
|
71909
|
+
return {
|
|
71910
|
+
id: u2.user_id ?? asDict(u2.user)?.id,
|
|
71911
|
+
name: nameOf(asDict(u2.user)),
|
|
71912
|
+
paid_share: u2.paid_share,
|
|
71913
|
+
owed_share: u2.owed_share,
|
|
71914
|
+
net_balance: u2.net_balance
|
|
71915
|
+
};
|
|
71916
|
+
}),
|
|
71917
|
+
// A receipt is evidence; `sw_get_receipt` is how a caller fetches it.
|
|
71918
|
+
has_receipt: typeof original === "string" ? true : void 0
|
|
71919
|
+
});
|
|
71920
|
+
}
|
|
71921
|
+
function projectList(view, payload, key, map2, context) {
|
|
71922
|
+
if (view !== "compact") return payload;
|
|
71923
|
+
return projectOrRaw(
|
|
71924
|
+
payload,
|
|
71925
|
+
(p2) => {
|
|
71926
|
+
const box = asDict(p2);
|
|
71927
|
+
const items = box?.[key];
|
|
71928
|
+
if (!box || !Array.isArray(items)) throw new Error(`expected a ${key}[] array`);
|
|
71929
|
+
return { ...box, [key]: items.map(map2) };
|
|
71930
|
+
},
|
|
71931
|
+
{ label: LABEL, context }
|
|
71932
|
+
);
|
|
71933
|
+
}
|
|
71934
|
+
var viewGroups = (view, p2) => projectList(view, p2, "groups", compactGroup, "GET /get_groups");
|
|
71935
|
+
var viewFriends = (view, p2) => projectList(view, p2, "friends", compactPerson, "GET /get_friends");
|
|
71936
|
+
var viewExpenses = (view, p2) => projectList(view, p2, "expenses", compactExpense, "GET /get_expenses");
|
|
71937
|
+
function projectOne(view, payload, key, map2, context) {
|
|
71938
|
+
if (view !== "compact") return payload;
|
|
71939
|
+
return projectOrRaw(
|
|
71940
|
+
payload,
|
|
71941
|
+
(p2) => {
|
|
71942
|
+
const box = asDict(p2);
|
|
71943
|
+
if (!box || box[key] === void 0) throw new Error(`expected a ${key} object`);
|
|
71944
|
+
return { ...box, [key]: map2(box[key]) };
|
|
71945
|
+
},
|
|
71946
|
+
{ label: LABEL, context }
|
|
71947
|
+
);
|
|
71948
|
+
}
|
|
71949
|
+
var viewGroup = (view, p2) => projectOne(view, p2, "group", compactGroup, "GET /get_group/{id}");
|
|
71950
|
+
var viewExpense = (view, p2) => projectOne(view, p2, "expense", compactExpense, "GET /get_expense/{id}");
|
|
71951
|
+
var viewUser = (view, p2) => projectOne(view, p2, "user", compactPerson, "GET /get_user/{id}");
|
|
71952
|
+
function viewGeneric(view, payload) {
|
|
71953
|
+
return view === "compact" ? stripMediaUrls(payload) : payload;
|
|
71954
|
+
}
|
|
71955
|
+
|
|
71480
71956
|
// src/tools/_confirm.ts
|
|
71481
71957
|
function previewUnlessConfirmed(confirm, action, method, path, body) {
|
|
71482
71958
|
if (confirm === true) return null;
|
|
71483
|
-
return
|
|
71959
|
+
return minifiedResult({
|
|
71484
71960
|
dryRun: true,
|
|
71485
71961
|
action,
|
|
71486
71962
|
method,
|
|
@@ -71493,21 +71969,25 @@ function previewUnlessConfirmed(confirm, action, method, path, body) {
|
|
|
71493
71969
|
// src/tools/user.ts
|
|
71494
71970
|
function registerUserTools(server, client2) {
|
|
71495
71971
|
server.registerTool("sw_get_current_user", {
|
|
71496
|
-
description: "Get the authenticated Splitwise user's profile
|
|
71497
|
-
annotations: { readOnlyHint: true }
|
|
71498
|
-
|
|
71972
|
+
description: "Get the authenticated Splitwise user's profile. Use the returned id when building custom expense splits. The compact default returns id, name (first_name + last_name joined), email and registration_status; pass view:'full' for Splitwise's raw record, which keeps first_name and last_name separate \u2014 the form sw_update_user takes.",
|
|
71973
|
+
annotations: { readOnlyHint: true },
|
|
71974
|
+
inputSchema: {
|
|
71975
|
+
view: viewParam(SW_VIEWS, { note: PERSON_VIEW_NOTE })
|
|
71976
|
+
}
|
|
71977
|
+
}, async ({ view }) => {
|
|
71499
71978
|
const data = await client2.request("GET", "/get_current_user");
|
|
71500
|
-
return
|
|
71979
|
+
return minifiedResult(viewUser(resolveView(view, SW_VIEWS), data));
|
|
71501
71980
|
});
|
|
71502
71981
|
server.registerTool("sw_get_user", {
|
|
71503
|
-
description: "Get another Splitwise user's profile by id.",
|
|
71982
|
+
description: "Get another Splitwise user's profile by id. Same shape as sw_get_current_user: the compact default merges first_name/last_name into name, and view:'full' keeps them separate.",
|
|
71504
71983
|
annotations: { readOnlyHint: true },
|
|
71505
71984
|
inputSchema: {
|
|
71985
|
+
view: viewParam(SW_VIEWS, { note: PERSON_VIEW_NOTE }),
|
|
71506
71986
|
id: external_exports.number().describe("User ID")
|
|
71507
71987
|
}
|
|
71508
|
-
}, async ({ id }) => {
|
|
71988
|
+
}, async ({ id, view }) => {
|
|
71509
71989
|
const data = await client2.request("GET", `/get_user/${id}`);
|
|
71510
|
-
return
|
|
71990
|
+
return minifiedResult(viewUser(resolveView(view, SW_VIEWS), data));
|
|
71511
71991
|
});
|
|
71512
71992
|
server.registerTool("sw_update_user", {
|
|
71513
71993
|
description: "Update the current user's profile fields. id must be the current user's id.",
|
|
@@ -71527,7 +72007,7 @@ function registerUserTools(server, client2) {
|
|
|
71527
72007
|
const gate = previewUnlessConfirmed(confirm, `Update current Splitwise user ${id} profile`, "POST", `/update_user/${id}`, previewBody);
|
|
71528
72008
|
if (gate) return gate;
|
|
71529
72009
|
const data = await client2.request("POST", `/update_user/${id}`, body);
|
|
71530
|
-
return
|
|
72010
|
+
return minifiedResult(data);
|
|
71531
72011
|
});
|
|
71532
72012
|
}
|
|
71533
72013
|
|
|
@@ -71538,6 +72018,18 @@ function statusOf(err) {
|
|
|
71538
72018
|
const s2 = err.status ?? err.statusCode;
|
|
71539
72019
|
return typeof s2 === "number" ? s2 : void 0;
|
|
71540
72020
|
}
|
|
72021
|
+
var CREDENTIAL_ARMS = /* @__PURE__ */ new Set([
|
|
72022
|
+
"ok",
|
|
72023
|
+
"no_credential",
|
|
72024
|
+
"credential_rejected",
|
|
72025
|
+
"timeout",
|
|
72026
|
+
"http",
|
|
72027
|
+
"transport",
|
|
72028
|
+
"unknown"
|
|
72029
|
+
]);
|
|
72030
|
+
function isArm(kind) {
|
|
72031
|
+
return kind !== void 0 && CREDENTIAL_ARMS.has(kind);
|
|
72032
|
+
}
|
|
71541
72033
|
function credentialHint(arm, prefix, hostLabel, source) {
|
|
71542
72034
|
switch (arm) {
|
|
71543
72035
|
case "ok":
|
|
@@ -71575,13 +72067,27 @@ function registerCredentialHealthcheckTool(args) {
|
|
|
71575
72067
|
try {
|
|
71576
72068
|
state = await resolveCredential();
|
|
71577
72069
|
} catch (e2) {
|
|
72070
|
+
const classified = classifyThrown?.(e2);
|
|
71578
72071
|
const result2 = {
|
|
71579
72072
|
ok: false,
|
|
72073
|
+
// Still false, and still no source: a classification explains WHY
|
|
72074
|
+
// nothing resolved, it does not invent a credential that did.
|
|
71580
72075
|
credential: { source: null, resolved: false },
|
|
71581
72076
|
// No `url`: nothing was probed, and naming one implies it was tried.
|
|
71582
72077
|
probe: { elapsed_ms: 0 },
|
|
71583
|
-
error: {
|
|
71584
|
-
|
|
72078
|
+
error: {
|
|
72079
|
+
kind: classified?.kind ?? "no_credential",
|
|
72080
|
+
message: truncateErrorMessage(messageOf(e2)),
|
|
72081
|
+
...classified?.detail !== void 0 ? { detail: classified.detail } : {}
|
|
72082
|
+
},
|
|
72083
|
+
// The hint must follow the KIND beside it. Falling back to
|
|
72084
|
+
// `no_credential`'s copy under a classified kind would state a cause
|
|
72085
|
+
// the kind contradicts — the same disagreement this path exists to
|
|
72086
|
+
// remove. So: an inline hint wins; else the classified arm's own
|
|
72087
|
+
// copy (consumer override first); else, for a kind this module has
|
|
72088
|
+
// no copy for, the neutral `unknown` text rather than one that
|
|
72089
|
+
// asserts a cause; else the unclassified `no_credential` default.
|
|
72090
|
+
hint: classified?.hint ?? (isArm(classified?.kind) ? hints?.[classified.kind] ?? credentialHint(classified.kind, prefix, hostLabel, null) : classified !== void 0 ? credentialHint("unknown", prefix, hostLabel, null) : hints?.no_credential ?? credentialHint("no_credential", prefix, hostLabel, null))
|
|
71585
72091
|
};
|
|
71586
72092
|
return { content: [{ type: "text", text: JSON.stringify(result2, null, 2) }] };
|
|
71587
72093
|
}
|
|
@@ -71663,20 +72169,24 @@ function registerHealthcheckTools(server, client2) {
|
|
|
71663
72169
|
function registerGroupTools(server, client2) {
|
|
71664
72170
|
server.registerTool("sw_list_groups", {
|
|
71665
72171
|
description: "List all Splitwise groups the current user belongs to. Returns id, name, and members for each group. Use this to resolve a group name to its id.",
|
|
71666
|
-
annotations: { readOnlyHint: true }
|
|
71667
|
-
|
|
72172
|
+
annotations: { readOnlyHint: true },
|
|
72173
|
+
inputSchema: {
|
|
72174
|
+
view: viewParam(SW_VIEWS, { note: `compact drops the avatar/cover-photo URLs (60% of a live 51-group response, which does not fit in a tool result at all) and the whiteboard/reminder settings; "full" returns Splitwise's whole records.` })
|
|
72175
|
+
}
|
|
72176
|
+
}, async ({ view }) => {
|
|
71668
72177
|
const data = await client2.request("GET", "/get_groups");
|
|
71669
|
-
return
|
|
72178
|
+
return minifiedResult(viewGroups(resolveView(view, SW_VIEWS), data));
|
|
71670
72179
|
});
|
|
71671
72180
|
server.registerTool("sw_get_group", {
|
|
71672
72181
|
description: "Get details of a single Splitwise group including all members and balances.",
|
|
71673
72182
|
annotations: { readOnlyHint: true },
|
|
71674
72183
|
inputSchema: {
|
|
72184
|
+
view: viewParam(SW_VIEWS, { note: `compact drops the avatar/cover-photo URLs (60% of a live 51-group response, which does not fit in a tool result at all) and the whiteboard/reminder settings; "full" returns Splitwise's whole records.` }),
|
|
71675
72185
|
id: external_exports.number().describe("Group ID")
|
|
71676
72186
|
}
|
|
71677
|
-
}, async ({ id }) => {
|
|
72187
|
+
}, async ({ id, view }) => {
|
|
71678
72188
|
const data = await client2.request("GET", `/get_group/${id}`);
|
|
71679
|
-
return
|
|
72189
|
+
return minifiedResult(viewGroup(resolveView(view, SW_VIEWS), data));
|
|
71680
72190
|
});
|
|
71681
72191
|
server.registerTool("sw_create_group", {
|
|
71682
72192
|
description: "Create a new Splitwise group.",
|
|
@@ -71692,7 +72202,7 @@ function registerGroupTools(server, client2) {
|
|
|
71692
72202
|
const gate = previewUnlessConfirmed(confirm, `Create Splitwise group "${name}"`, "POST", "/create_group", body);
|
|
71693
72203
|
if (gate) return gate;
|
|
71694
72204
|
const data = await client2.request("POST", "/create_group", body);
|
|
71695
|
-
return
|
|
72205
|
+
return minifiedResult(data);
|
|
71696
72206
|
});
|
|
71697
72207
|
server.registerTool("sw_add_user_to_group", {
|
|
71698
72208
|
description: "Add a user to a Splitwise group. Provide user_id (preferred, use sw_list_friends to resolve a name) or first_name + last_name + email to invite by email.",
|
|
@@ -71717,7 +72227,7 @@ function registerGroupTools(server, client2) {
|
|
|
71717
72227
|
const gate = previewUnlessConfirmed(confirm, `Add a user to Splitwise group ${group_id} (may send an invite email)`, "POST", "/add_user_to_group", body);
|
|
71718
72228
|
if (gate) return gate;
|
|
71719
72229
|
const data = await client2.request("POST", "/add_user_to_group", body);
|
|
71720
|
-
return
|
|
72230
|
+
return minifiedResult(data);
|
|
71721
72231
|
});
|
|
71722
72232
|
server.registerTool("sw_remove_user_from_group", {
|
|
71723
72233
|
description: "Remove a user from a Splitwise group. Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it removes the user.",
|
|
@@ -71731,7 +72241,7 @@ function registerGroupTools(server, client2) {
|
|
|
71731
72241
|
const gate = previewUnlessConfirmed(confirm, `Remove user ${user_id} from Splitwise group ${group_id}`, "POST", "/remove_user_from_group", { group_id, user_id });
|
|
71732
72242
|
if (gate) return gate;
|
|
71733
72243
|
const data = await client2.request("POST", "/remove_user_from_group", { group_id, user_id });
|
|
71734
|
-
return
|
|
72244
|
+
return minifiedResult(data);
|
|
71735
72245
|
});
|
|
71736
72246
|
server.registerTool("sw_delete_group", {
|
|
71737
72247
|
description: "Soft-delete a Splitwise group. Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it deletes.",
|
|
@@ -71744,7 +72254,7 @@ function registerGroupTools(server, client2) {
|
|
|
71744
72254
|
const gate = previewUnlessConfirmed(confirm, `Soft-delete Splitwise group ${id}`, "POST", `/delete_group/${id}`);
|
|
71745
72255
|
if (gate) return gate;
|
|
71746
72256
|
const data = await client2.request("POST", `/delete_group/${id}`);
|
|
71747
|
-
return
|
|
72257
|
+
return minifiedResult(data);
|
|
71748
72258
|
});
|
|
71749
72259
|
server.registerTool("sw_undelete_group", {
|
|
71750
72260
|
description: "Restore a soft-deleted Splitwise group.",
|
|
@@ -71753,18 +72263,21 @@ function registerGroupTools(server, client2) {
|
|
|
71753
72263
|
}
|
|
71754
72264
|
}, async ({ id }) => {
|
|
71755
72265
|
const data = await client2.request("POST", `/undelete_group/${id}`);
|
|
71756
|
-
return
|
|
72266
|
+
return minifiedResult(data);
|
|
71757
72267
|
});
|
|
71758
72268
|
}
|
|
71759
72269
|
|
|
71760
72270
|
// src/tools/friends.ts
|
|
71761
72271
|
function registerFriendTools(server, client2) {
|
|
71762
72272
|
server.registerTool("sw_list_friends", {
|
|
71763
|
-
description: "List all Splitwise friends
|
|
71764
|
-
annotations: { readOnlyHint: true }
|
|
71765
|
-
|
|
72273
|
+
description: "List all Splitwise friends. Use this to resolve a friend's name to a user_id before adding them to a group or building a custom expense split. The compact default returns id, name (first_name + last_name joined), email, registration_status and any non-empty balance per friend; pass view:'full' for Splitwise's raw records, which keep first_name and last_name separate.",
|
|
72274
|
+
annotations: { readOnlyHint: true },
|
|
72275
|
+
inputSchema: {
|
|
72276
|
+
view: viewParam(SW_VIEWS, { note: PERSON_VIEW_NOTE })
|
|
72277
|
+
}
|
|
72278
|
+
}, async ({ view }) => {
|
|
71766
72279
|
const data = await client2.request("GET", "/get_friends");
|
|
71767
|
-
return
|
|
72280
|
+
return minifiedResult(viewFriends(resolveView(view, SW_VIEWS), data));
|
|
71768
72281
|
});
|
|
71769
72282
|
server.registerTool("sw_create_friend", {
|
|
71770
72283
|
description: "Add a Splitwise friend by email (sends them an invite). Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it adds the friend.",
|
|
@@ -71780,7 +72293,7 @@ function registerFriendTools(server, client2) {
|
|
|
71780
72293
|
const gate = previewUnlessConfirmed(confirm, `Add ${user_email} as a Splitwise friend`, "POST", "/create_friend", body);
|
|
71781
72294
|
if (gate) return gate;
|
|
71782
72295
|
const data = await client2.request("POST", "/create_friend", body);
|
|
71783
|
-
return
|
|
72296
|
+
return minifiedResult(data);
|
|
71784
72297
|
});
|
|
71785
72298
|
server.registerTool("sw_delete_friend", {
|
|
71786
72299
|
description: "Remove a Splitwise friendship by user id. Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it removes the friendship.",
|
|
@@ -71793,7 +72306,7 @@ function registerFriendTools(server, client2) {
|
|
|
71793
72306
|
const gate = previewUnlessConfirmed(confirm, `Remove Splitwise friendship with user ${id}`, "POST", `/delete_friend/${id}`);
|
|
71794
72307
|
if (gate) return gate;
|
|
71795
72308
|
const data = await client2.request("POST", `/delete_friend/${id}`);
|
|
71796
|
-
return
|
|
72309
|
+
return minifiedResult(data);
|
|
71797
72310
|
});
|
|
71798
72311
|
}
|
|
71799
72312
|
|
|
@@ -71830,6 +72343,7 @@ function registerExpenseTools(server, client2) {
|
|
|
71830
72343
|
description: "List or search Splitwise expenses. All filters are optional. Use group_id to filter by group, dated_after/dated_before for date ranges.",
|
|
71831
72344
|
annotations: { readOnlyHint: true },
|
|
71832
72345
|
inputSchema: {
|
|
72346
|
+
view: viewParam(SW_VIEWS, { note: `compact keeps the share breakdown, repayments and receipt presence and drops the avatars and the repeat/reminder/transaction block; "full" returns Splitwise's whole records.` }),
|
|
71833
72347
|
group_id: external_exports.number().describe("Only expenses in this group").optional(),
|
|
71834
72348
|
friend_id: external_exports.number().describe("Only expenses with this friend").optional(),
|
|
71835
72349
|
dated_after: external_exports.string().describe("ISO 8601 date \u2014 only expenses on or after this date").optional(),
|
|
@@ -71851,17 +72365,18 @@ function registerExpenseTools(server, client2) {
|
|
|
71851
72365
|
offset: args.offset
|
|
71852
72366
|
});
|
|
71853
72367
|
const data = await client2.request("GET", `/get_expenses${qs2}`);
|
|
71854
|
-
return
|
|
72368
|
+
return minifiedResult(viewExpenses(resolveView(args.view, SW_VIEWS), data));
|
|
71855
72369
|
});
|
|
71856
72370
|
server.registerTool("sw_get_expense", {
|
|
71857
72371
|
description: "Get full details of a single Splitwise expense by id.",
|
|
71858
72372
|
annotations: { readOnlyHint: true },
|
|
71859
72373
|
inputSchema: {
|
|
72374
|
+
view: viewParam(SW_VIEWS, { note: `compact keeps the share breakdown, repayments and receipt presence and drops the avatars and the repeat/reminder/transaction block; "full" returns Splitwise's whole records.` }),
|
|
71860
72375
|
id: external_exports.number().describe("Expense ID")
|
|
71861
72376
|
}
|
|
71862
|
-
}, async ({ id }) => {
|
|
72377
|
+
}, async ({ id, view }) => {
|
|
71863
72378
|
const data = await client2.request("GET", `/get_expense/${id}`);
|
|
71864
|
-
return
|
|
72379
|
+
return minifiedResult(viewExpense(resolveView(view, SW_VIEWS), data));
|
|
71865
72380
|
});
|
|
71866
72381
|
server.registerTool("sw_create_expense", {
|
|
71867
72382
|
description: 'Create a Splitwise expense. Use split_equally:true to split evenly among group members, or provide a users array for custom per-person splits (paid_share and owed_share as decimal strings like "25.00"). cost must be a decimal string. Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it creates the expense.',
|
|
@@ -71882,7 +72397,7 @@ function registerExpenseTools(server, client2) {
|
|
|
71882
72397
|
const gate = previewUnlessConfirmed(args.confirm, `Create a Splitwise expense "${args.description}" (${args.cost}) \u2014 notifies group members`, "POST", "/create_expense", body);
|
|
71883
72398
|
if (gate) return gate;
|
|
71884
72399
|
const data = await client2.request("POST", "/create_expense", body);
|
|
71885
|
-
return
|
|
72400
|
+
return minifiedResult(data);
|
|
71886
72401
|
});
|
|
71887
72402
|
server.registerTool("sw_update_expense", {
|
|
71888
72403
|
description: "Edit an existing Splitwise expense. Provide expense_id and any fields to change. For custom split updates, the full users array must be provided (the API replaces the entire split). Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it updates the expense.",
|
|
@@ -71904,7 +72419,7 @@ function registerExpenseTools(server, client2) {
|
|
|
71904
72419
|
const gate = previewUnlessConfirmed(args.confirm, `Update Splitwise expense ${expense_id} \u2014 notifies group members`, "POST", `/update_expense/${expense_id}`, body);
|
|
71905
72420
|
if (gate) return gate;
|
|
71906
72421
|
const data = await client2.request("POST", `/update_expense/${expense_id}`, body);
|
|
71907
|
-
return
|
|
72422
|
+
return minifiedResult(data);
|
|
71908
72423
|
});
|
|
71909
72424
|
server.registerTool("sw_delete_expense", {
|
|
71910
72425
|
description: "Soft-delete a Splitwise expense by id. Returns {success: true} on success. Use sw_undelete_expense to restore. Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it deletes.",
|
|
@@ -71917,7 +72432,7 @@ function registerExpenseTools(server, client2) {
|
|
|
71917
72432
|
const gate = previewUnlessConfirmed(confirm, `Soft-delete Splitwise expense ${id}`, "POST", `/delete_expense/${id}`);
|
|
71918
72433
|
if (gate) return gate;
|
|
71919
72434
|
const data = await client2.request("POST", `/delete_expense/${id}`);
|
|
71920
|
-
return
|
|
72435
|
+
return minifiedResult(data);
|
|
71921
72436
|
});
|
|
71922
72437
|
server.registerTool("sw_undelete_expense", {
|
|
71923
72438
|
description: "Restore a soft-deleted Splitwise expense.",
|
|
@@ -71926,7 +72441,7 @@ function registerExpenseTools(server, client2) {
|
|
|
71926
72441
|
}
|
|
71927
72442
|
}, async ({ id }) => {
|
|
71928
72443
|
const data = await client2.request("POST", `/undelete_expense/${id}`);
|
|
71929
|
-
return
|
|
72444
|
+
return minifiedResult(data);
|
|
71930
72445
|
});
|
|
71931
72446
|
}
|
|
71932
72447
|
|
|
@@ -72061,7 +72576,7 @@ function registerReceiptTools(server, client2) {
|
|
|
72061
72576
|
].join(" ")
|
|
72062
72577
|
);
|
|
72063
72578
|
}
|
|
72064
|
-
const result =
|
|
72579
|
+
const result = minifiedResult({
|
|
72065
72580
|
expense_id: id,
|
|
72066
72581
|
size: served,
|
|
72067
72582
|
...served !== wanted ? { requested_size: wanted, note: `Expense ${id} has no ${wanted} rendition; fetched ${served}.` } : {},
|
|
@@ -72094,34 +72609,38 @@ function registerReceiptTools(server, client2) {
|
|
|
72094
72609
|
function registerUtilityTools(server, client2) {
|
|
72095
72610
|
server.registerTool("sw_get_notifications", {
|
|
72096
72611
|
description: "Get recent Splitwise activity notifications for the current user.",
|
|
72097
|
-
annotations: { readOnlyHint: true }
|
|
72098
|
-
|
|
72612
|
+
annotations: { readOnlyHint: true },
|
|
72613
|
+
inputSchema: {
|
|
72614
|
+
view: viewParam(SW_VIEWS, { note: `compact drops the avatar URLs; "full" returns Splitwise's whole record.` })
|
|
72615
|
+
}
|
|
72616
|
+
}, async ({ view }) => {
|
|
72099
72617
|
const data = await client2.request("GET", "/get_notifications");
|
|
72100
|
-
return
|
|
72618
|
+
return minifiedResult(viewGeneric(resolveView(view, SW_VIEWS), data));
|
|
72101
72619
|
});
|
|
72102
72620
|
server.registerTool("sw_get_categories", {
|
|
72103
72621
|
description: "Get the hierarchical list of Splitwise expense categories. Use the returned id as category_id when creating expenses.",
|
|
72104
72622
|
annotations: { readOnlyHint: true }
|
|
72105
72623
|
}, async () => {
|
|
72106
72624
|
const data = await client2.request("GET", "/get_categories");
|
|
72107
|
-
return
|
|
72625
|
+
return minifiedResult(data);
|
|
72108
72626
|
});
|
|
72109
72627
|
server.registerTool("sw_get_currencies", {
|
|
72110
72628
|
description: "Get all Splitwise-supported currency codes and units. Use the currency_code value when creating expenses in non-default currencies.",
|
|
72111
72629
|
annotations: { readOnlyHint: true }
|
|
72112
72630
|
}, async () => {
|
|
72113
72631
|
const data = await client2.request("GET", "/get_currencies");
|
|
72114
|
-
return
|
|
72632
|
+
return minifiedResult(data);
|
|
72115
72633
|
});
|
|
72116
72634
|
server.registerTool("sw_get_comments", {
|
|
72117
72635
|
description: "Get all comments on a Splitwise expense.",
|
|
72118
72636
|
annotations: { readOnlyHint: true },
|
|
72119
72637
|
inputSchema: {
|
|
72638
|
+
view: viewParam(SW_VIEWS, { note: `compact drops the avatar URLs; "full" returns Splitwise's whole record.` }),
|
|
72120
72639
|
expense_id: external_exports.number().describe("Expense ID to get comments for")
|
|
72121
72640
|
}
|
|
72122
|
-
}, async ({ expense_id }) => {
|
|
72641
|
+
}, async ({ expense_id, view }) => {
|
|
72123
72642
|
const data = await client2.request("GET", `/get_comments${buildQueryString({ expense_id })}`);
|
|
72124
|
-
return
|
|
72643
|
+
return minifiedResult(viewGeneric(resolveView(view, SW_VIEWS), data));
|
|
72125
72644
|
});
|
|
72126
72645
|
server.registerTool("sw_create_comment", {
|
|
72127
72646
|
description: "Add a comment to a Splitwise expense (visible to other participants). Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it posts.",
|
|
@@ -72135,7 +72654,7 @@ function registerUtilityTools(server, client2) {
|
|
|
72135
72654
|
const gate = previewUnlessConfirmed(confirm, `Comment on Splitwise expense ${expense_id} (visible to participants)`, "POST", "/create_comment", { expense_id, content });
|
|
72136
72655
|
if (gate) return gate;
|
|
72137
72656
|
const data = await client2.request("POST", "/create_comment", { expense_id, content });
|
|
72138
|
-
return
|
|
72657
|
+
return minifiedResult(data);
|
|
72139
72658
|
});
|
|
72140
72659
|
server.registerTool("sw_delete_comment", {
|
|
72141
72660
|
description: "Delete a comment by id. Without confirm:true this returns a dry-run preview and makes NO network call; with confirm:true it deletes.",
|
|
@@ -72148,14 +72667,14 @@ function registerUtilityTools(server, client2) {
|
|
|
72148
72667
|
const gate = previewUnlessConfirmed(confirm, `Delete Splitwise comment ${id}`, "POST", `/delete_comment/${id}`);
|
|
72149
72668
|
if (gate) return gate;
|
|
72150
72669
|
const data = await client2.request("POST", `/delete_comment/${id}`);
|
|
72151
|
-
return
|
|
72670
|
+
return minifiedResult(data);
|
|
72152
72671
|
});
|
|
72153
72672
|
}
|
|
72154
72673
|
|
|
72155
72674
|
// src/index.ts
|
|
72156
72675
|
await runMcp({
|
|
72157
72676
|
name: "splitwise-mcp",
|
|
72158
|
-
version: "2.
|
|
72677
|
+
version: "2.4.1",
|
|
72159
72678
|
// x-release-please-version
|
|
72160
72679
|
deps: client,
|
|
72161
72680
|
banner: "[splitwise-mcp] This project was developed and is maintained by AI (Claude Sonnet 4.6). Use at your own discretion.",
|