@kehto/paja 0.1.0 → 0.3.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/dist/browser-host.js +1797 -168
- package/dist/browser-host.js.map +1 -1
- package/dist/{chunk-BM6ROSMJ.js → chunk-5HWERUMK.js} +26 -2
- package/dist/chunk-5HWERUMK.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/{options-D3xZz-aS.d.ts → options-D4tneY-c.d.ts} +1 -1
- package/package.json +20 -20
- package/dist/chunk-BM6ROSMJ.js.map +0 -1
package/dist/browser-host.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../acl/dist/chunk-
|
|
1
|
+
// ../acl/dist/chunk-6GH7LZSY.js
|
|
2
2
|
var ALL_CAPABILITIES = [
|
|
3
3
|
// v1.1 kept:
|
|
4
4
|
"relay:read",
|
|
@@ -224,7 +224,7 @@ function configMap(action) {
|
|
|
224
224
|
return { senderCap: "config:read", recipientCap: null };
|
|
225
225
|
}
|
|
226
226
|
function resourceMap(action) {
|
|
227
|
-
if (action === "bytes.result" || action === "bytes.error") {
|
|
227
|
+
if (action === "bytes.result" || action === "bytes.error" || action === "bytesMany.result" || action === "bytesMany.error") {
|
|
228
228
|
return { senderCap: null, recipientCap: "resource:fetch" };
|
|
229
229
|
}
|
|
230
230
|
return { senderCap: "resource:fetch", recipientCap: null };
|
|
@@ -593,7 +593,7 @@ function deserialize2(json) {
|
|
|
593
593
|
return defaultConfig();
|
|
594
594
|
}
|
|
595
595
|
|
|
596
|
-
// ../../node_modules/.pnpm/@napplet+core@0.
|
|
596
|
+
// ../../node_modules/.pnpm/@napplet+core@0.21.0/node_modules/@napplet/core/dist/index.js
|
|
597
597
|
function createDispatch() {
|
|
598
598
|
const handlers = /* @__PURE__ */ new Map();
|
|
599
599
|
function registerNap2(domain, handler) {
|
|
@@ -1704,7 +1704,13 @@ function createRuntimeDomainHandlers(context) {
|
|
|
1704
1704
|
cvm: (windowId, msg) => handleServiceOnlyMessage(context, "cvm", windowId, msg),
|
|
1705
1705
|
outbox: (windowId, msg) => handleServiceOnlyMessage(context, "outbox", windowId, msg),
|
|
1706
1706
|
upload: (windowId, msg) => handleServiceOnlyMessage(context, "upload", windowId, msg),
|
|
1707
|
-
intent: (windowId, msg) => handleServiceOnlyMessage(context, "intent", windowId, msg)
|
|
1707
|
+
intent: (windowId, msg) => handleServiceOnlyMessage(context, "intent", windowId, msg),
|
|
1708
|
+
link: (windowId, msg) => handleServiceOnlyMessage(context, "link", windowId, msg),
|
|
1709
|
+
common: (windowId, msg) => handleServiceOnlyMessage(context, "common", windowId, msg),
|
|
1710
|
+
lists: (windowId, msg) => handleServiceOnlyMessage(context, "lists", windowId, msg),
|
|
1711
|
+
serial: (windowId, msg) => handleServiceOnlyMessage(context, "serial", windowId, msg),
|
|
1712
|
+
ble: (windowId, msg) => handleServiceOnlyMessage(context, "ble", windowId, msg),
|
|
1713
|
+
webrtc: (windowId, msg) => handleServiceOnlyMessage(context, "webrtc", windowId, msg)
|
|
1708
1714
|
};
|
|
1709
1715
|
}
|
|
1710
1716
|
function handleStorageMessage(context, windowId, msg) {
|
|
@@ -1845,6 +1851,12 @@ function createNapEnvelopeDispatcher(handlers) {
|
|
|
1845
1851
|
napDispatch.registerNap("outbox", adapt(handlers.outbox));
|
|
1846
1852
|
napDispatch.registerNap("upload", adapt(handlers.upload));
|
|
1847
1853
|
napDispatch.registerNap("intent", adapt(handlers.intent));
|
|
1854
|
+
napDispatch.registerNap("link", adapt(handlers.link));
|
|
1855
|
+
napDispatch.registerNap("common", adapt(handlers.common));
|
|
1856
|
+
napDispatch.registerNap("lists", adapt(handlers.lists));
|
|
1857
|
+
napDispatch.registerNap("serial", adapt(handlers.serial));
|
|
1858
|
+
napDispatch.registerNap("ble", adapt(handlers.ble));
|
|
1859
|
+
napDispatch.registerNap("webrtc", adapt(handlers.webrtc));
|
|
1848
1860
|
return (windowId, envelope) => {
|
|
1849
1861
|
currentWindowId = windowId;
|
|
1850
1862
|
try {
|
|
@@ -3082,6 +3094,12 @@ function buildShellCapabilities(hooks) {
|
|
|
3082
3094
|
const domains = hooks.relayPool ? ["relay", "outbox", ...NAP_DOMAINS] : [...NAP_DOMAINS];
|
|
3083
3095
|
if (hooks.upload) domains.push("upload");
|
|
3084
3096
|
if (hooks.intent?.isAvailable()) domains.push("intent");
|
|
3097
|
+
if (hooks.link?.isAvailable()) domains.push("link");
|
|
3098
|
+
if (hooks.common?.isAvailable()) domains.push("common");
|
|
3099
|
+
if (hooks.lists?.isAvailable()) domains.push("lists");
|
|
3100
|
+
if (hooks.serial?.isAvailable()) domains.push("serial");
|
|
3101
|
+
if (hooks.ble?.isAvailable()) domains.push("ble");
|
|
3102
|
+
if (hooks.webrtc?.isAvailable()) domains.push("webrtc");
|
|
3085
3103
|
const sandbox = [];
|
|
3086
3104
|
domains.push(...sandbox);
|
|
3087
3105
|
const protocols = {};
|
|
@@ -3092,6 +3110,12 @@ function buildShellCapabilities(hooks) {
|
|
|
3092
3110
|
const naps = hooks.relayPool ? ["relay", "outbox", ...NAP_DOMAINS, ...NAP_INC_PROTOCOLS] : [...NAP_DOMAINS, ...NAP_INC_PROTOCOLS];
|
|
3093
3111
|
if (hooks.upload) naps.push("upload");
|
|
3094
3112
|
if (hooks.intent?.isAvailable()) naps.push("intent");
|
|
3113
|
+
if (hooks.link?.isAvailable()) naps.push("link");
|
|
3114
|
+
if (hooks.common?.isAvailable()) naps.push("common");
|
|
3115
|
+
if (hooks.lists?.isAvailable()) naps.push("lists");
|
|
3116
|
+
if (hooks.serial?.isAvailable()) naps.push("serial");
|
|
3117
|
+
if (hooks.ble?.isAvailable()) naps.push("ble");
|
|
3118
|
+
if (hooks.webrtc?.isAvailable()) naps.push("webrtc");
|
|
3095
3119
|
return applyCapabilityOverrides(
|
|
3096
3120
|
{ domains, protocols, naps, sandbox },
|
|
3097
3121
|
hooks.capabilities?.disabledDomains ?? []
|
|
@@ -3269,6 +3293,496 @@ function createShellBridge(hooks) {
|
|
|
3269
3293
|
};
|
|
3270
3294
|
}
|
|
3271
3295
|
|
|
3296
|
+
// ../../node_modules/.pnpm/@noble+hashes@2.0.1/node_modules/@noble/hashes/utils.js
|
|
3297
|
+
function isBytes(a) {
|
|
3298
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
3299
|
+
}
|
|
3300
|
+
function abytes(value, length, title = "") {
|
|
3301
|
+
const bytes = isBytes(value);
|
|
3302
|
+
const len = value?.length;
|
|
3303
|
+
const needsLen = length !== void 0;
|
|
3304
|
+
if (!bytes || needsLen && len !== length) {
|
|
3305
|
+
const prefix = title && `"${title}" `;
|
|
3306
|
+
const ofLen = needsLen ? ` of length ${length}` : "";
|
|
3307
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
3308
|
+
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
3309
|
+
}
|
|
3310
|
+
return value;
|
|
3311
|
+
}
|
|
3312
|
+
var hasHexBuiltin = /* @__PURE__ */ (() => (
|
|
3313
|
+
// @ts-ignore
|
|
3314
|
+
typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function"
|
|
3315
|
+
))();
|
|
3316
|
+
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
3317
|
+
function bytesToHex2(bytes) {
|
|
3318
|
+
abytes(bytes);
|
|
3319
|
+
if (hasHexBuiltin)
|
|
3320
|
+
return bytes.toHex();
|
|
3321
|
+
let hex = "";
|
|
3322
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
3323
|
+
hex += hexes[bytes[i]];
|
|
3324
|
+
}
|
|
3325
|
+
return hex;
|
|
3326
|
+
}
|
|
3327
|
+
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
3328
|
+
function asciiToBase16(ch) {
|
|
3329
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
|
3330
|
+
return ch - asciis._0;
|
|
3331
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
|
3332
|
+
return ch - (asciis.A - 10);
|
|
3333
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
|
3334
|
+
return ch - (asciis.a - 10);
|
|
3335
|
+
return;
|
|
3336
|
+
}
|
|
3337
|
+
function hexToBytes2(hex) {
|
|
3338
|
+
if (typeof hex !== "string")
|
|
3339
|
+
throw new Error("hex string expected, got " + typeof hex);
|
|
3340
|
+
if (hasHexBuiltin)
|
|
3341
|
+
return Uint8Array.fromHex(hex);
|
|
3342
|
+
const hl = hex.length;
|
|
3343
|
+
const al = hl / 2;
|
|
3344
|
+
if (hl % 2)
|
|
3345
|
+
throw new Error("hex string expected, got unpadded hex of length " + hl);
|
|
3346
|
+
const array = new Uint8Array(al);
|
|
3347
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
3348
|
+
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
|
3349
|
+
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
|
|
3350
|
+
if (n1 === void 0 || n2 === void 0) {
|
|
3351
|
+
const char = hex[hi] + hex[hi + 1];
|
|
3352
|
+
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
|
3353
|
+
}
|
|
3354
|
+
array[ai] = n1 * 16 + n2;
|
|
3355
|
+
}
|
|
3356
|
+
return array;
|
|
3357
|
+
}
|
|
3358
|
+
function concatBytes(...arrays) {
|
|
3359
|
+
let sum = 0;
|
|
3360
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
3361
|
+
const a = arrays[i];
|
|
3362
|
+
abytes(a);
|
|
3363
|
+
sum += a.length;
|
|
3364
|
+
}
|
|
3365
|
+
const res = new Uint8Array(sum);
|
|
3366
|
+
for (let i = 0, pad = 0; i < arrays.length; i++) {
|
|
3367
|
+
const a = arrays[i];
|
|
3368
|
+
res.set(a, pad);
|
|
3369
|
+
pad += a.length;
|
|
3370
|
+
}
|
|
3371
|
+
return res;
|
|
3372
|
+
}
|
|
3373
|
+
|
|
3374
|
+
// ../../node_modules/.pnpm/@scure+base@2.0.0/node_modules/@scure/base/index.js
|
|
3375
|
+
function isBytes2(a) {
|
|
3376
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
3377
|
+
}
|
|
3378
|
+
function isArrayOf(isString, arr) {
|
|
3379
|
+
if (!Array.isArray(arr))
|
|
3380
|
+
return false;
|
|
3381
|
+
if (arr.length === 0)
|
|
3382
|
+
return true;
|
|
3383
|
+
if (isString) {
|
|
3384
|
+
return arr.every((item) => typeof item === "string");
|
|
3385
|
+
} else {
|
|
3386
|
+
return arr.every((item) => Number.isSafeInteger(item));
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
function afn(input) {
|
|
3390
|
+
if (typeof input !== "function")
|
|
3391
|
+
throw new Error("function expected");
|
|
3392
|
+
return true;
|
|
3393
|
+
}
|
|
3394
|
+
function astr(label, input) {
|
|
3395
|
+
if (typeof input !== "string")
|
|
3396
|
+
throw new Error(`${label}: string expected`);
|
|
3397
|
+
return true;
|
|
3398
|
+
}
|
|
3399
|
+
function anumber(n) {
|
|
3400
|
+
if (!Number.isSafeInteger(n))
|
|
3401
|
+
throw new Error(`invalid integer: ${n}`);
|
|
3402
|
+
}
|
|
3403
|
+
function aArr(input) {
|
|
3404
|
+
if (!Array.isArray(input))
|
|
3405
|
+
throw new Error("array expected");
|
|
3406
|
+
}
|
|
3407
|
+
function astrArr(label, input) {
|
|
3408
|
+
if (!isArrayOf(true, input))
|
|
3409
|
+
throw new Error(`${label}: array of strings expected`);
|
|
3410
|
+
}
|
|
3411
|
+
function anumArr(label, input) {
|
|
3412
|
+
if (!isArrayOf(false, input))
|
|
3413
|
+
throw new Error(`${label}: array of numbers expected`);
|
|
3414
|
+
}
|
|
3415
|
+
// @__NO_SIDE_EFFECTS__
|
|
3416
|
+
function chain(...args) {
|
|
3417
|
+
const id = (a) => a;
|
|
3418
|
+
const wrap = (a, b) => (c) => a(b(c));
|
|
3419
|
+
const encode = args.map((x) => x.encode).reduceRight(wrap, id);
|
|
3420
|
+
const decode2 = args.map((x) => x.decode).reduce(wrap, id);
|
|
3421
|
+
return { encode, decode: decode2 };
|
|
3422
|
+
}
|
|
3423
|
+
// @__NO_SIDE_EFFECTS__
|
|
3424
|
+
function alphabet(letters) {
|
|
3425
|
+
const lettersA = typeof letters === "string" ? letters.split("") : letters;
|
|
3426
|
+
const len = lettersA.length;
|
|
3427
|
+
astrArr("alphabet", lettersA);
|
|
3428
|
+
const indexes = new Map(lettersA.map((l, i) => [l, i]));
|
|
3429
|
+
return {
|
|
3430
|
+
encode: (digits) => {
|
|
3431
|
+
aArr(digits);
|
|
3432
|
+
return digits.map((i) => {
|
|
3433
|
+
if (!Number.isSafeInteger(i) || i < 0 || i >= len)
|
|
3434
|
+
throw new Error(`alphabet.encode: digit index outside alphabet "${i}". Allowed: ${letters}`);
|
|
3435
|
+
return lettersA[i];
|
|
3436
|
+
});
|
|
3437
|
+
},
|
|
3438
|
+
decode: (input) => {
|
|
3439
|
+
aArr(input);
|
|
3440
|
+
return input.map((letter) => {
|
|
3441
|
+
astr("alphabet.decode", letter);
|
|
3442
|
+
const i = indexes.get(letter);
|
|
3443
|
+
if (i === void 0)
|
|
3444
|
+
throw new Error(`Unknown letter: "${letter}". Allowed: ${letters}`);
|
|
3445
|
+
return i;
|
|
3446
|
+
});
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
}
|
|
3450
|
+
// @__NO_SIDE_EFFECTS__
|
|
3451
|
+
function join(separator = "") {
|
|
3452
|
+
astr("join", separator);
|
|
3453
|
+
return {
|
|
3454
|
+
encode: (from) => {
|
|
3455
|
+
astrArr("join.decode", from);
|
|
3456
|
+
return from.join(separator);
|
|
3457
|
+
},
|
|
3458
|
+
decode: (to) => {
|
|
3459
|
+
astr("join.decode", to);
|
|
3460
|
+
return to.split(separator);
|
|
3461
|
+
}
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
var gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
|
|
3465
|
+
var radix2carry = /* @__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));
|
|
3466
|
+
var powers = /* @__PURE__ */ (() => {
|
|
3467
|
+
let res = [];
|
|
3468
|
+
for (let i = 0; i < 40; i++)
|
|
3469
|
+
res.push(2 ** i);
|
|
3470
|
+
return res;
|
|
3471
|
+
})();
|
|
3472
|
+
function convertRadix2(data, from, to, padding) {
|
|
3473
|
+
aArr(data);
|
|
3474
|
+
if (from <= 0 || from > 32)
|
|
3475
|
+
throw new Error(`convertRadix2: wrong from=${from}`);
|
|
3476
|
+
if (to <= 0 || to > 32)
|
|
3477
|
+
throw new Error(`convertRadix2: wrong to=${to}`);
|
|
3478
|
+
if (/* @__PURE__ */ radix2carry(from, to) > 32) {
|
|
3479
|
+
throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${/* @__PURE__ */ radix2carry(from, to)}`);
|
|
3480
|
+
}
|
|
3481
|
+
let carry = 0;
|
|
3482
|
+
let pos = 0;
|
|
3483
|
+
const max = powers[from];
|
|
3484
|
+
const mask = powers[to] - 1;
|
|
3485
|
+
const res = [];
|
|
3486
|
+
for (const n of data) {
|
|
3487
|
+
anumber(n);
|
|
3488
|
+
if (n >= max)
|
|
3489
|
+
throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);
|
|
3490
|
+
carry = carry << from | n;
|
|
3491
|
+
if (pos + from > 32)
|
|
3492
|
+
throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);
|
|
3493
|
+
pos += from;
|
|
3494
|
+
for (; pos >= to; pos -= to)
|
|
3495
|
+
res.push((carry >> pos - to & mask) >>> 0);
|
|
3496
|
+
const pow = powers[pos];
|
|
3497
|
+
if (pow === void 0)
|
|
3498
|
+
throw new Error("invalid carry");
|
|
3499
|
+
carry &= pow - 1;
|
|
3500
|
+
}
|
|
3501
|
+
carry = carry << to - pos & mask;
|
|
3502
|
+
if (!padding && pos >= from)
|
|
3503
|
+
throw new Error("Excess padding");
|
|
3504
|
+
if (!padding && carry > 0)
|
|
3505
|
+
throw new Error(`Non-zero padding: ${carry}`);
|
|
3506
|
+
if (padding && pos > 0)
|
|
3507
|
+
res.push(carry >>> 0);
|
|
3508
|
+
return res;
|
|
3509
|
+
}
|
|
3510
|
+
// @__NO_SIDE_EFFECTS__
|
|
3511
|
+
function radix2(bits, revPadding = false) {
|
|
3512
|
+
anumber(bits);
|
|
3513
|
+
if (bits <= 0 || bits > 32)
|
|
3514
|
+
throw new Error("radix2: bits should be in (0..32]");
|
|
3515
|
+
if (/* @__PURE__ */ radix2carry(8, bits) > 32 || /* @__PURE__ */ radix2carry(bits, 8) > 32)
|
|
3516
|
+
throw new Error("radix2: carry overflow");
|
|
3517
|
+
return {
|
|
3518
|
+
encode: (bytes) => {
|
|
3519
|
+
if (!isBytes2(bytes))
|
|
3520
|
+
throw new Error("radix2.encode input should be Uint8Array");
|
|
3521
|
+
return convertRadix2(Array.from(bytes), 8, bits, !revPadding);
|
|
3522
|
+
},
|
|
3523
|
+
decode: (digits) => {
|
|
3524
|
+
anumArr("radix2.decode", digits);
|
|
3525
|
+
return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));
|
|
3526
|
+
}
|
|
3527
|
+
};
|
|
3528
|
+
}
|
|
3529
|
+
function unsafeWrapper(fn) {
|
|
3530
|
+
afn(fn);
|
|
3531
|
+
return function(...args) {
|
|
3532
|
+
try {
|
|
3533
|
+
return fn.apply(null, args);
|
|
3534
|
+
} catch (e) {
|
|
3535
|
+
}
|
|
3536
|
+
};
|
|
3537
|
+
}
|
|
3538
|
+
var BECH_ALPHABET = /* @__PURE__ */ chain(/* @__PURE__ */ alphabet("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join(""));
|
|
3539
|
+
var POLYMOD_GENERATORS = [996825010, 642813549, 513874426, 1027748829, 705979059];
|
|
3540
|
+
function bech32Polymod(pre) {
|
|
3541
|
+
const b = pre >> 25;
|
|
3542
|
+
let chk = (pre & 33554431) << 5;
|
|
3543
|
+
for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {
|
|
3544
|
+
if ((b >> i & 1) === 1)
|
|
3545
|
+
chk ^= POLYMOD_GENERATORS[i];
|
|
3546
|
+
}
|
|
3547
|
+
return chk;
|
|
3548
|
+
}
|
|
3549
|
+
function bechChecksum(prefix, words, encodingConst = 1) {
|
|
3550
|
+
const len = prefix.length;
|
|
3551
|
+
let chk = 1;
|
|
3552
|
+
for (let i = 0; i < len; i++) {
|
|
3553
|
+
const c = prefix.charCodeAt(i);
|
|
3554
|
+
if (c < 33 || c > 126)
|
|
3555
|
+
throw new Error(`Invalid prefix (${prefix})`);
|
|
3556
|
+
chk = bech32Polymod(chk) ^ c >> 5;
|
|
3557
|
+
}
|
|
3558
|
+
chk = bech32Polymod(chk);
|
|
3559
|
+
for (let i = 0; i < len; i++)
|
|
3560
|
+
chk = bech32Polymod(chk) ^ prefix.charCodeAt(i) & 31;
|
|
3561
|
+
for (let v of words)
|
|
3562
|
+
chk = bech32Polymod(chk) ^ v;
|
|
3563
|
+
for (let i = 0; i < 6; i++)
|
|
3564
|
+
chk = bech32Polymod(chk);
|
|
3565
|
+
chk ^= encodingConst;
|
|
3566
|
+
return BECH_ALPHABET.encode(convertRadix2([chk % powers[30]], 30, 5, false));
|
|
3567
|
+
}
|
|
3568
|
+
// @__NO_SIDE_EFFECTS__
|
|
3569
|
+
function genBech32(encoding) {
|
|
3570
|
+
const ENCODING_CONST = encoding === "bech32" ? 1 : 734539939;
|
|
3571
|
+
const _words = /* @__PURE__ */ radix2(5);
|
|
3572
|
+
const fromWords = _words.decode;
|
|
3573
|
+
const toWords = _words.encode;
|
|
3574
|
+
const fromWordsUnsafe = unsafeWrapper(fromWords);
|
|
3575
|
+
function encode(prefix, words, limit = 90) {
|
|
3576
|
+
astr("bech32.encode prefix", prefix);
|
|
3577
|
+
if (isBytes2(words))
|
|
3578
|
+
words = Array.from(words);
|
|
3579
|
+
anumArr("bech32.encode", words);
|
|
3580
|
+
const plen = prefix.length;
|
|
3581
|
+
if (plen === 0)
|
|
3582
|
+
throw new TypeError(`Invalid prefix length ${plen}`);
|
|
3583
|
+
const actualLength = plen + 7 + words.length;
|
|
3584
|
+
if (limit !== false && actualLength > limit)
|
|
3585
|
+
throw new TypeError(`Length ${actualLength} exceeds limit ${limit}`);
|
|
3586
|
+
const lowered = prefix.toLowerCase();
|
|
3587
|
+
const sum = bechChecksum(lowered, words, ENCODING_CONST);
|
|
3588
|
+
return `${lowered}1${BECH_ALPHABET.encode(words)}${sum}`;
|
|
3589
|
+
}
|
|
3590
|
+
function decode2(str, limit = 90) {
|
|
3591
|
+
astr("bech32.decode input", str);
|
|
3592
|
+
const slen = str.length;
|
|
3593
|
+
if (slen < 8 || limit !== false && slen > limit)
|
|
3594
|
+
throw new TypeError(`invalid string length: ${slen} (${str}). Expected (8..${limit})`);
|
|
3595
|
+
const lowered = str.toLowerCase();
|
|
3596
|
+
if (str !== lowered && str !== str.toUpperCase())
|
|
3597
|
+
throw new Error(`String must be lowercase or uppercase`);
|
|
3598
|
+
const sepIndex = lowered.lastIndexOf("1");
|
|
3599
|
+
if (sepIndex === 0 || sepIndex === -1)
|
|
3600
|
+
throw new Error(`Letter "1" must be present between prefix and data only`);
|
|
3601
|
+
const prefix = lowered.slice(0, sepIndex);
|
|
3602
|
+
const data = lowered.slice(sepIndex + 1);
|
|
3603
|
+
if (data.length < 6)
|
|
3604
|
+
throw new Error("Data must be at least 6 characters long");
|
|
3605
|
+
const words = BECH_ALPHABET.decode(data).slice(0, -6);
|
|
3606
|
+
const sum = bechChecksum(prefix, words, ENCODING_CONST);
|
|
3607
|
+
if (!data.endsWith(sum))
|
|
3608
|
+
throw new Error(`Invalid checksum in ${str}: expected "${sum}"`);
|
|
3609
|
+
return { prefix, words };
|
|
3610
|
+
}
|
|
3611
|
+
const decodeUnsafe = unsafeWrapper(decode2);
|
|
3612
|
+
function decodeToBytes(str) {
|
|
3613
|
+
const { prefix, words } = decode2(str, false);
|
|
3614
|
+
return { prefix, words, bytes: fromWords(words) };
|
|
3615
|
+
}
|
|
3616
|
+
function encodeFromBytes(prefix, bytes) {
|
|
3617
|
+
return encode(prefix, toWords(bytes));
|
|
3618
|
+
}
|
|
3619
|
+
return {
|
|
3620
|
+
encode,
|
|
3621
|
+
decode: decode2,
|
|
3622
|
+
encodeFromBytes,
|
|
3623
|
+
decodeToBytes,
|
|
3624
|
+
decodeUnsafe,
|
|
3625
|
+
fromWords,
|
|
3626
|
+
fromWordsUnsafe,
|
|
3627
|
+
toWords
|
|
3628
|
+
};
|
|
3629
|
+
}
|
|
3630
|
+
var bech32 = /* @__PURE__ */ genBech32("bech32");
|
|
3631
|
+
|
|
3632
|
+
// ../../node_modules/.pnpm/nostr-tools@2.23.3_typescript@5.9.3/node_modules/nostr-tools/lib/esm/nip19.js
|
|
3633
|
+
var utf8Decoder = new TextDecoder("utf-8");
|
|
3634
|
+
var utf8Encoder = new TextEncoder();
|
|
3635
|
+
var Bech32MaxSize = 5e3;
|
|
3636
|
+
function integerToUint8Array(number) {
|
|
3637
|
+
const uint8Array = new Uint8Array(4);
|
|
3638
|
+
uint8Array[0] = number >> 24 & 255;
|
|
3639
|
+
uint8Array[1] = number >> 16 & 255;
|
|
3640
|
+
uint8Array[2] = number >> 8 & 255;
|
|
3641
|
+
uint8Array[3] = number & 255;
|
|
3642
|
+
return uint8Array;
|
|
3643
|
+
}
|
|
3644
|
+
function decode(code) {
|
|
3645
|
+
let { prefix, words } = bech32.decode(code, Bech32MaxSize);
|
|
3646
|
+
let data = new Uint8Array(bech32.fromWords(words));
|
|
3647
|
+
switch (prefix) {
|
|
3648
|
+
case "nprofile": {
|
|
3649
|
+
let tlv = parseTLV(data);
|
|
3650
|
+
if (!tlv[0]?.[0])
|
|
3651
|
+
throw new Error("missing TLV 0 for nprofile");
|
|
3652
|
+
if (tlv[0][0].length !== 32)
|
|
3653
|
+
throw new Error("TLV 0 should be 32 bytes");
|
|
3654
|
+
return {
|
|
3655
|
+
type: "nprofile",
|
|
3656
|
+
data: {
|
|
3657
|
+
pubkey: bytesToHex2(tlv[0][0]),
|
|
3658
|
+
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
3659
|
+
}
|
|
3660
|
+
};
|
|
3661
|
+
}
|
|
3662
|
+
case "nevent": {
|
|
3663
|
+
let tlv = parseTLV(data);
|
|
3664
|
+
if (!tlv[0]?.[0])
|
|
3665
|
+
throw new Error("missing TLV 0 for nevent");
|
|
3666
|
+
if (tlv[0][0].length !== 32)
|
|
3667
|
+
throw new Error("TLV 0 should be 32 bytes");
|
|
3668
|
+
if (tlv[2] && tlv[2][0].length !== 32)
|
|
3669
|
+
throw new Error("TLV 2 should be 32 bytes");
|
|
3670
|
+
if (tlv[3] && tlv[3][0].length !== 4)
|
|
3671
|
+
throw new Error("TLV 3 should be 4 bytes");
|
|
3672
|
+
return {
|
|
3673
|
+
type: "nevent",
|
|
3674
|
+
data: {
|
|
3675
|
+
id: bytesToHex2(tlv[0][0]),
|
|
3676
|
+
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : [],
|
|
3677
|
+
author: tlv[2]?.[0] ? bytesToHex2(tlv[2][0]) : void 0,
|
|
3678
|
+
kind: tlv[3]?.[0] ? parseInt(bytesToHex2(tlv[3][0]), 16) : void 0
|
|
3679
|
+
}
|
|
3680
|
+
};
|
|
3681
|
+
}
|
|
3682
|
+
case "naddr": {
|
|
3683
|
+
let tlv = parseTLV(data);
|
|
3684
|
+
if (!tlv[0]?.[0])
|
|
3685
|
+
throw new Error("missing TLV 0 for naddr");
|
|
3686
|
+
if (!tlv[2]?.[0])
|
|
3687
|
+
throw new Error("missing TLV 2 for naddr");
|
|
3688
|
+
if (tlv[2][0].length !== 32)
|
|
3689
|
+
throw new Error("TLV 2 should be 32 bytes");
|
|
3690
|
+
if (!tlv[3]?.[0])
|
|
3691
|
+
throw new Error("missing TLV 3 for naddr");
|
|
3692
|
+
if (tlv[3][0].length !== 4)
|
|
3693
|
+
throw new Error("TLV 3 should be 4 bytes");
|
|
3694
|
+
return {
|
|
3695
|
+
type: "naddr",
|
|
3696
|
+
data: {
|
|
3697
|
+
identifier: utf8Decoder.decode(tlv[0][0]),
|
|
3698
|
+
pubkey: bytesToHex2(tlv[2][0]),
|
|
3699
|
+
kind: parseInt(bytesToHex2(tlv[3][0]), 16),
|
|
3700
|
+
relays: tlv[1] ? tlv[1].map((d) => utf8Decoder.decode(d)) : []
|
|
3701
|
+
}
|
|
3702
|
+
};
|
|
3703
|
+
}
|
|
3704
|
+
case "nsec":
|
|
3705
|
+
return { type: prefix, data };
|
|
3706
|
+
case "npub":
|
|
3707
|
+
case "note":
|
|
3708
|
+
return { type: prefix, data: bytesToHex2(data) };
|
|
3709
|
+
default:
|
|
3710
|
+
throw new Error(`unknown prefix ${prefix}`);
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
function parseTLV(data) {
|
|
3714
|
+
let result = {};
|
|
3715
|
+
let rest = data;
|
|
3716
|
+
while (rest.length > 0) {
|
|
3717
|
+
let t = rest[0];
|
|
3718
|
+
let l = rest[1];
|
|
3719
|
+
let v = rest.slice(2, 2 + l);
|
|
3720
|
+
rest = rest.slice(2 + l);
|
|
3721
|
+
if (v.length < l)
|
|
3722
|
+
throw new Error(`not enough data to read on TLV ${t}`);
|
|
3723
|
+
result[t] = result[t] || [];
|
|
3724
|
+
result[t].push(v);
|
|
3725
|
+
}
|
|
3726
|
+
return result;
|
|
3727
|
+
}
|
|
3728
|
+
function npubEncode(hex) {
|
|
3729
|
+
return encodeBytes("npub", hexToBytes2(hex));
|
|
3730
|
+
}
|
|
3731
|
+
function noteEncode(hex) {
|
|
3732
|
+
return encodeBytes("note", hexToBytes2(hex));
|
|
3733
|
+
}
|
|
3734
|
+
function encodeBech32(prefix, data) {
|
|
3735
|
+
let words = bech32.toWords(data);
|
|
3736
|
+
return bech32.encode(prefix, words, Bech32MaxSize);
|
|
3737
|
+
}
|
|
3738
|
+
function encodeBytes(prefix, bytes) {
|
|
3739
|
+
return encodeBech32(prefix, bytes);
|
|
3740
|
+
}
|
|
3741
|
+
function nprofileEncode(profile) {
|
|
3742
|
+
let data = encodeTLV({
|
|
3743
|
+
0: [hexToBytes2(profile.pubkey)],
|
|
3744
|
+
1: (profile.relays || []).map((url) => utf8Encoder.encode(url))
|
|
3745
|
+
});
|
|
3746
|
+
return encodeBech32("nprofile", data);
|
|
3747
|
+
}
|
|
3748
|
+
function neventEncode(event) {
|
|
3749
|
+
let kindArray;
|
|
3750
|
+
if (event.kind !== void 0) {
|
|
3751
|
+
kindArray = integerToUint8Array(event.kind);
|
|
3752
|
+
}
|
|
3753
|
+
let data = encodeTLV({
|
|
3754
|
+
0: [hexToBytes2(event.id)],
|
|
3755
|
+
1: (event.relays || []).map((url) => utf8Encoder.encode(url)),
|
|
3756
|
+
2: event.author ? [hexToBytes2(event.author)] : [],
|
|
3757
|
+
3: kindArray ? [new Uint8Array(kindArray)] : []
|
|
3758
|
+
});
|
|
3759
|
+
return encodeBech32("nevent", data);
|
|
3760
|
+
}
|
|
3761
|
+
function naddrEncode(addr) {
|
|
3762
|
+
let kind = new ArrayBuffer(4);
|
|
3763
|
+
new DataView(kind).setUint32(0, addr.kind, false);
|
|
3764
|
+
let data = encodeTLV({
|
|
3765
|
+
0: [utf8Encoder.encode(addr.identifier)],
|
|
3766
|
+
1: (addr.relays || []).map((url) => utf8Encoder.encode(url)),
|
|
3767
|
+
2: [hexToBytes2(addr.pubkey)],
|
|
3768
|
+
3: [new Uint8Array(kind)]
|
|
3769
|
+
});
|
|
3770
|
+
return encodeBech32("naddr", data);
|
|
3771
|
+
}
|
|
3772
|
+
function encodeTLV(tlv) {
|
|
3773
|
+
let entries = [];
|
|
3774
|
+
Object.entries(tlv).reverse().forEach(([t, vs]) => {
|
|
3775
|
+
vs.forEach((v) => {
|
|
3776
|
+
let entry = new Uint8Array(v.length + 2);
|
|
3777
|
+
entry.set([parseInt(t)], 0);
|
|
3778
|
+
entry.set([v.length], 1);
|
|
3779
|
+
entry.set(v, 2);
|
|
3780
|
+
entries.push(entry);
|
|
3781
|
+
});
|
|
3782
|
+
});
|
|
3783
|
+
return concatBytes(...entries);
|
|
3784
|
+
}
|
|
3785
|
+
|
|
3272
3786
|
// ../services/dist/index.js
|
|
3273
3787
|
var NOTIFICATION_SERVICE_VERSION = "1.0.0";
|
|
3274
3788
|
var DEFAULT_MAX_PER_WINDOW = 100;
|
|
@@ -3432,6 +3946,184 @@ function createNotificationService(options) {
|
|
|
3432
3946
|
};
|
|
3433
3947
|
}
|
|
3434
3948
|
var IDENTITY_SERVICE_VERSION = "1.0.0";
|
|
3949
|
+
function sendProviderError(send, result, fallback, err) {
|
|
3950
|
+
send({
|
|
3951
|
+
...result,
|
|
3952
|
+
error: err?.message ?? fallback
|
|
3953
|
+
});
|
|
3954
|
+
}
|
|
3955
|
+
async function getCurrentPubkey(options) {
|
|
3956
|
+
const currentSigner = options.getSigner();
|
|
3957
|
+
if (!currentSigner?.getPublicKey) return "";
|
|
3958
|
+
try {
|
|
3959
|
+
return await currentSigner.getPublicKey() ?? "";
|
|
3960
|
+
} catch {
|
|
3961
|
+
return "";
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
function sendOptionalProviderResult(options, send, fallbackResult, errorFallback, buildResult) {
|
|
3965
|
+
if (!buildResult) {
|
|
3966
|
+
send(fallbackResult);
|
|
3967
|
+
return;
|
|
3968
|
+
}
|
|
3969
|
+
Promise.resolve(getCurrentPubkey(options)).then((pubkey) => buildResult(pubkey)).then((result) => send(result)).catch((err) => sendProviderError(send, fallbackResult, errorFallback, err));
|
|
3970
|
+
}
|
|
3971
|
+
function sendIdentityError(send, id, typeBase, error) {
|
|
3972
|
+
send({ type: `${typeBase}.error`, id, error });
|
|
3973
|
+
}
|
|
3974
|
+
function sendSignerError(send, id, typeBase, fallback, err) {
|
|
3975
|
+
sendIdentityError(send, id, typeBase, err?.message ?? fallback);
|
|
3976
|
+
}
|
|
3977
|
+
function handleGetPublicKey(options, id, send) {
|
|
3978
|
+
const signer = options.getSigner();
|
|
3979
|
+
if (!signer) {
|
|
3980
|
+
const result = {
|
|
3981
|
+
type: "identity.getPublicKey.result",
|
|
3982
|
+
id,
|
|
3983
|
+
pubkey: ""
|
|
3984
|
+
};
|
|
3985
|
+
send(result);
|
|
3986
|
+
return;
|
|
3987
|
+
}
|
|
3988
|
+
Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
|
|
3989
|
+
const result = {
|
|
3990
|
+
type: "identity.getPublicKey.result",
|
|
3991
|
+
id,
|
|
3992
|
+
pubkey: pubkey ?? ""
|
|
3993
|
+
};
|
|
3994
|
+
send(result);
|
|
3995
|
+
}).catch((err) => sendSignerError(send, id, "identity.getPublicKey", "getPublicKey failed", err));
|
|
3996
|
+
}
|
|
3997
|
+
function handleGetRelays(options, id, send) {
|
|
3998
|
+
const signer = options.getSigner();
|
|
3999
|
+
if (!signer) {
|
|
4000
|
+
sendIdentityError(send, id, "identity.getRelays", "no signer configured");
|
|
4001
|
+
return;
|
|
4002
|
+
}
|
|
4003
|
+
Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
|
|
4004
|
+
const result = {
|
|
4005
|
+
type: "identity.getRelays.result",
|
|
4006
|
+
id,
|
|
4007
|
+
relays
|
|
4008
|
+
};
|
|
4009
|
+
send(result);
|
|
4010
|
+
}).catch((err) => sendSignerError(send, id, "identity.getRelays", "getRelays failed", err));
|
|
4011
|
+
}
|
|
4012
|
+
function handleReadProvider(options, id, message, send) {
|
|
4013
|
+
switch (message.type) {
|
|
4014
|
+
case "identity.getProfile":
|
|
4015
|
+
sendOptionalProviderResult(
|
|
4016
|
+
options,
|
|
4017
|
+
send,
|
|
4018
|
+
{ type: "identity.getProfile.result", id, profile: null },
|
|
4019
|
+
"getProfile failed",
|
|
4020
|
+
options.getProfile ? async (pubkey) => ({
|
|
4021
|
+
type: "identity.getProfile.result",
|
|
4022
|
+
id,
|
|
4023
|
+
profile: await options.getProfile(pubkey, message)
|
|
4024
|
+
}) : void 0
|
|
4025
|
+
);
|
|
4026
|
+
return true;
|
|
4027
|
+
case "identity.getFollows":
|
|
4028
|
+
sendOptionalProviderResult(
|
|
4029
|
+
options,
|
|
4030
|
+
send,
|
|
4031
|
+
{ type: "identity.getFollows.result", id, pubkeys: [] },
|
|
4032
|
+
"getFollows failed",
|
|
4033
|
+
options.getFollows ? async (pubkey) => ({
|
|
4034
|
+
type: "identity.getFollows.result",
|
|
4035
|
+
id,
|
|
4036
|
+
pubkeys: await options.getFollows(pubkey, message)
|
|
4037
|
+
}) : void 0
|
|
4038
|
+
);
|
|
4039
|
+
return true;
|
|
4040
|
+
case "identity.getList":
|
|
4041
|
+
handleGetList(options, id, message, send);
|
|
4042
|
+
return true;
|
|
4043
|
+
case "identity.getZaps":
|
|
4044
|
+
sendOptionalProviderResult(
|
|
4045
|
+
options,
|
|
4046
|
+
send,
|
|
4047
|
+
{ type: "identity.getZaps.result", id, zaps: [] },
|
|
4048
|
+
"getZaps failed",
|
|
4049
|
+
options.getZaps ? async (pubkey) => ({
|
|
4050
|
+
type: "identity.getZaps.result",
|
|
4051
|
+
id,
|
|
4052
|
+
zaps: await options.getZaps(pubkey, message)
|
|
4053
|
+
}) : void 0
|
|
4054
|
+
);
|
|
4055
|
+
return true;
|
|
4056
|
+
case "identity.getMutes":
|
|
4057
|
+
sendOptionalProviderResult(
|
|
4058
|
+
options,
|
|
4059
|
+
send,
|
|
4060
|
+
{ type: "identity.getMutes.result", id, pubkeys: [] },
|
|
4061
|
+
"getMutes failed",
|
|
4062
|
+
options.getMutes ? async (pubkey) => ({
|
|
4063
|
+
type: "identity.getMutes.result",
|
|
4064
|
+
id,
|
|
4065
|
+
pubkeys: await options.getMutes(pubkey, message)
|
|
4066
|
+
}) : void 0
|
|
4067
|
+
);
|
|
4068
|
+
return true;
|
|
4069
|
+
case "identity.getBlocked":
|
|
4070
|
+
sendOptionalProviderResult(
|
|
4071
|
+
options,
|
|
4072
|
+
send,
|
|
4073
|
+
{ type: "identity.getBlocked.result", id, pubkeys: [] },
|
|
4074
|
+
"getBlocked failed",
|
|
4075
|
+
options.getBlocked ? async (pubkey) => ({
|
|
4076
|
+
type: "identity.getBlocked.result",
|
|
4077
|
+
id,
|
|
4078
|
+
pubkeys: await options.getBlocked(pubkey, message)
|
|
4079
|
+
}) : void 0
|
|
4080
|
+
);
|
|
4081
|
+
return true;
|
|
4082
|
+
case "identity.getBadges":
|
|
4083
|
+
sendOptionalProviderResult(
|
|
4084
|
+
options,
|
|
4085
|
+
send,
|
|
4086
|
+
{ type: "identity.getBadges.result", id, badges: [] },
|
|
4087
|
+
"getBadges failed",
|
|
4088
|
+
options.getBadges ? async (pubkey) => ({
|
|
4089
|
+
type: "identity.getBadges.result",
|
|
4090
|
+
id,
|
|
4091
|
+
badges: await options.getBadges(pubkey, message)
|
|
4092
|
+
}) : void 0
|
|
4093
|
+
);
|
|
4094
|
+
return true;
|
|
4095
|
+
default:
|
|
4096
|
+
return false;
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4099
|
+
function handleGetList(options, id, message, send) {
|
|
4100
|
+
sendOptionalProviderResult(
|
|
4101
|
+
options,
|
|
4102
|
+
send,
|
|
4103
|
+
{ type: "identity.getList.result", id, entries: [] },
|
|
4104
|
+
"getList failed",
|
|
4105
|
+
options.getList ? async (pubkey) => ({
|
|
4106
|
+
type: "identity.getList.result",
|
|
4107
|
+
id,
|
|
4108
|
+
entries: await options.getList(message.listType, pubkey, message)
|
|
4109
|
+
}) : void 0
|
|
4110
|
+
);
|
|
4111
|
+
}
|
|
4112
|
+
function handleIdentityServiceMessage(options, message, send) {
|
|
4113
|
+
const id = message.id ?? "";
|
|
4114
|
+
switch (message.type) {
|
|
4115
|
+
case "identity.getPublicKey":
|
|
4116
|
+
handleGetPublicKey(options, id, send);
|
|
4117
|
+
return;
|
|
4118
|
+
case "identity.getRelays":
|
|
4119
|
+
handleGetRelays(options, id, send);
|
|
4120
|
+
return;
|
|
4121
|
+
default:
|
|
4122
|
+
if (!handleReadProvider(options, id, message, send)) {
|
|
4123
|
+
sendIdentityError(send, id, message.type, `Unknown identity method: ${message.type}`);
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
3435
4127
|
function createIdentityService(options) {
|
|
3436
4128
|
return {
|
|
3437
4129
|
descriptor: {
|
|
@@ -3440,116 +4132,7 @@ function createIdentityService(options) {
|
|
|
3440
4132
|
description: "NIP-5D identity NAP reference handler (9 read-only identity queries)"
|
|
3441
4133
|
},
|
|
3442
4134
|
handleMessage(_windowId, message, send) {
|
|
3443
|
-
|
|
3444
|
-
function sendError(typeBase, error) {
|
|
3445
|
-
send({ type: `${typeBase}.error`, id, error });
|
|
3446
|
-
}
|
|
3447
|
-
function sendSignerError(typeBase, fallback, err) {
|
|
3448
|
-
sendError(typeBase, err?.message ?? fallback);
|
|
3449
|
-
}
|
|
3450
|
-
const signer = options.getSigner();
|
|
3451
|
-
switch (message.type) {
|
|
3452
|
-
case "identity.getPublicKey": {
|
|
3453
|
-
if (!signer) {
|
|
3454
|
-
const result = {
|
|
3455
|
-
type: "identity.getPublicKey.result",
|
|
3456
|
-
id,
|
|
3457
|
-
pubkey: ""
|
|
3458
|
-
};
|
|
3459
|
-
send(result);
|
|
3460
|
-
return;
|
|
3461
|
-
}
|
|
3462
|
-
Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
|
|
3463
|
-
const result = {
|
|
3464
|
-
type: "identity.getPublicKey.result",
|
|
3465
|
-
id,
|
|
3466
|
-
pubkey: pubkey ?? ""
|
|
3467
|
-
};
|
|
3468
|
-
send(result);
|
|
3469
|
-
}).catch((err) => sendSignerError("identity.getPublicKey", "getPublicKey failed", err));
|
|
3470
|
-
return;
|
|
3471
|
-
}
|
|
3472
|
-
case "identity.getRelays": {
|
|
3473
|
-
if (!signer) {
|
|
3474
|
-
sendError("identity.getRelays", "no signer configured");
|
|
3475
|
-
return;
|
|
3476
|
-
}
|
|
3477
|
-
Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
|
|
3478
|
-
const result = {
|
|
3479
|
-
type: "identity.getRelays.result",
|
|
3480
|
-
id,
|
|
3481
|
-
relays
|
|
3482
|
-
};
|
|
3483
|
-
send(result);
|
|
3484
|
-
}).catch((err) => sendSignerError("identity.getRelays", "getRelays failed", err));
|
|
3485
|
-
return;
|
|
3486
|
-
}
|
|
3487
|
-
case "identity.getProfile": {
|
|
3488
|
-
const result = {
|
|
3489
|
-
type: "identity.getProfile.result",
|
|
3490
|
-
id,
|
|
3491
|
-
profile: null
|
|
3492
|
-
};
|
|
3493
|
-
send(result);
|
|
3494
|
-
return;
|
|
3495
|
-
}
|
|
3496
|
-
case "identity.getFollows": {
|
|
3497
|
-
const result = {
|
|
3498
|
-
type: "identity.getFollows.result",
|
|
3499
|
-
id,
|
|
3500
|
-
pubkeys: []
|
|
3501
|
-
};
|
|
3502
|
-
send(result);
|
|
3503
|
-
return;
|
|
3504
|
-
}
|
|
3505
|
-
case "identity.getList": {
|
|
3506
|
-
const result = {
|
|
3507
|
-
type: "identity.getList.result",
|
|
3508
|
-
id,
|
|
3509
|
-
entries: []
|
|
3510
|
-
};
|
|
3511
|
-
send(result);
|
|
3512
|
-
return;
|
|
3513
|
-
}
|
|
3514
|
-
case "identity.getZaps": {
|
|
3515
|
-
const result = {
|
|
3516
|
-
type: "identity.getZaps.result",
|
|
3517
|
-
id,
|
|
3518
|
-
zaps: []
|
|
3519
|
-
};
|
|
3520
|
-
send(result);
|
|
3521
|
-
return;
|
|
3522
|
-
}
|
|
3523
|
-
case "identity.getMutes": {
|
|
3524
|
-
const result = {
|
|
3525
|
-
type: "identity.getMutes.result",
|
|
3526
|
-
id,
|
|
3527
|
-
pubkeys: []
|
|
3528
|
-
};
|
|
3529
|
-
send(result);
|
|
3530
|
-
return;
|
|
3531
|
-
}
|
|
3532
|
-
case "identity.getBlocked": {
|
|
3533
|
-
const result = {
|
|
3534
|
-
type: "identity.getBlocked.result",
|
|
3535
|
-
id,
|
|
3536
|
-
pubkeys: []
|
|
3537
|
-
};
|
|
3538
|
-
send(result);
|
|
3539
|
-
return;
|
|
3540
|
-
}
|
|
3541
|
-
case "identity.getBadges": {
|
|
3542
|
-
const result = {
|
|
3543
|
-
type: "identity.getBadges.result",
|
|
3544
|
-
id,
|
|
3545
|
-
badges: []
|
|
3546
|
-
};
|
|
3547
|
-
send(result);
|
|
3548
|
-
return;
|
|
3549
|
-
}
|
|
3550
|
-
default:
|
|
3551
|
-
sendError(message.type, `Unknown identity method: ${message.type}`);
|
|
3552
|
-
}
|
|
4135
|
+
handleIdentityServiceMessage(options, message, send);
|
|
3553
4136
|
},
|
|
3554
4137
|
// Identity service has no per-window state to clean up.
|
|
3555
4138
|
onWindowDestroyed(_windowId) {
|
|
@@ -4588,19 +5171,35 @@ function untrackRequest(state, requestId) {
|
|
|
4588
5171
|
state.perWindow.get(entry.windowId)?.delete(requestId);
|
|
4589
5172
|
}
|
|
4590
5173
|
}
|
|
4591
|
-
function sendResourceError(send, requestId, code, message) {
|
|
5174
|
+
function sendResourceError(send, requestId, code, message, error = toResourceError(code), type = "resource.bytes.error") {
|
|
4592
5175
|
send({
|
|
4593
|
-
type
|
|
5176
|
+
type,
|
|
5177
|
+
id: requestId,
|
|
4594
5178
|
requestId,
|
|
5179
|
+
error,
|
|
4595
5180
|
code,
|
|
4596
5181
|
message
|
|
4597
5182
|
});
|
|
4598
5183
|
}
|
|
4599
|
-
function
|
|
5184
|
+
function sendBytesManyError(send, requestId, code, message, error) {
|
|
5185
|
+
sendResourceError(send, requestId, code, message, error, "resource.bytesMany.error");
|
|
5186
|
+
}
|
|
5187
|
+
function toResourceError(code) {
|
|
5188
|
+
switch (code) {
|
|
5189
|
+
case "denied":
|
|
5190
|
+
return "blocked-by-policy";
|
|
5191
|
+
case "invalid-url":
|
|
5192
|
+
return "invalid-request";
|
|
5193
|
+
case "canceled":
|
|
5194
|
+
return "timeout";
|
|
5195
|
+
case "network-error":
|
|
5196
|
+
return "network-error";
|
|
5197
|
+
}
|
|
5198
|
+
}
|
|
5199
|
+
function parseResourceUrl(url) {
|
|
4600
5200
|
try {
|
|
4601
5201
|
return new URL(url);
|
|
4602
5202
|
} catch {
|
|
4603
|
-
sendResourceError(send, requestId, "invalid-url", `invalid URL: ${url}`);
|
|
4604
5203
|
return null;
|
|
4605
5204
|
}
|
|
4606
5205
|
}
|
|
@@ -4611,64 +5210,157 @@ function collectResponseHeaders(response) {
|
|
|
4611
5210
|
});
|
|
4612
5211
|
return headers;
|
|
4613
5212
|
}
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
if (
|
|
5213
|
+
function responseMime(response) {
|
|
5214
|
+
return response.headers.get("content-type") || "application/octet-stream";
|
|
5215
|
+
}
|
|
5216
|
+
function responseBlob(buffer, mime) {
|
|
5217
|
+
return new Blob([buffer], { type: mime });
|
|
5218
|
+
}
|
|
5219
|
+
function requestIdFromMessage(message) {
|
|
5220
|
+
if (typeof message.id === "string" && message.id.length > 0) return message.id;
|
|
5221
|
+
if (typeof message.requestId === "string" && message.requestId.length > 0) return message.requestId;
|
|
5222
|
+
return null;
|
|
5223
|
+
}
|
|
5224
|
+
function resourceInvalidRequest(url, message) {
|
|
5225
|
+
return {
|
|
5226
|
+
ok: false,
|
|
5227
|
+
url,
|
|
5228
|
+
error: "invalid-request",
|
|
5229
|
+
code: "invalid-url",
|
|
5230
|
+
message
|
|
5231
|
+
};
|
|
5232
|
+
}
|
|
5233
|
+
async function fetchResourceItem(options, identity, url, init, signal) {
|
|
5234
|
+
const parsedUrl = parseResourceUrl(url);
|
|
5235
|
+
if (!parsedUrl) return resourceInvalidRequest(url, `invalid URL: ${url}`);
|
|
4623
5236
|
const origin = parsedUrl.origin;
|
|
4624
5237
|
const grants = options.getConnectGrants(identity.dTag, identity.aggregateHash);
|
|
4625
5238
|
if (!options.isOriginGranted(origin, grants)) {
|
|
4626
|
-
|
|
4627
|
-
|
|
5239
|
+
return {
|
|
5240
|
+
ok: false,
|
|
5241
|
+
url,
|
|
5242
|
+
error: "blocked-by-policy",
|
|
5243
|
+
code: "denied",
|
|
5244
|
+
message: `origin ${origin} not granted`
|
|
5245
|
+
};
|
|
4628
5246
|
}
|
|
4629
|
-
const controller = new AbortController();
|
|
4630
|
-
trackRequest(state, requestId, windowId, controller);
|
|
4631
5247
|
try {
|
|
4632
5248
|
const response = await options.fetch(url, {
|
|
4633
5249
|
method: init?.method,
|
|
4634
5250
|
headers: init?.headers ? { ...init.headers } : void 0,
|
|
4635
|
-
signal
|
|
5251
|
+
signal
|
|
4636
5252
|
});
|
|
4637
5253
|
const buffer = await response.arrayBuffer();
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
5254
|
+
const headers = collectResponseHeaders(response);
|
|
5255
|
+
const mime = responseMime(response);
|
|
5256
|
+
return {
|
|
5257
|
+
ok: true,
|
|
5258
|
+
url,
|
|
5259
|
+
blob: responseBlob(buffer, mime),
|
|
5260
|
+
mime,
|
|
4641
5261
|
status: response.status,
|
|
4642
|
-
headers
|
|
5262
|
+
headers,
|
|
4643
5263
|
bodyBase64: arrayBufferToBase64(buffer)
|
|
4644
|
-
}
|
|
5264
|
+
};
|
|
4645
5265
|
} catch (err) {
|
|
4646
|
-
const isAbort =
|
|
4647
|
-
|
|
4648
|
-
|
|
5266
|
+
const isAbort = signal.aborted || err instanceof Error && (err.name === "AbortError" || err.name === "DOMException");
|
|
5267
|
+
return {
|
|
5268
|
+
ok: false,
|
|
5269
|
+
url,
|
|
5270
|
+
error: isAbort ? "timeout" : "network-error",
|
|
5271
|
+
code: isAbort ? "canceled" : "network-error",
|
|
5272
|
+
message: err instanceof Error ? err.message : String(err)
|
|
5273
|
+
};
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
async function handleBytes(options, state, windowId, msg, send) {
|
|
5277
|
+
const { requestId, url, init } = msg;
|
|
5278
|
+
const identity = options.resolveIdentity(windowId);
|
|
5279
|
+
if (!identity) {
|
|
5280
|
+
sendResourceError(send, requestId, "denied", "napplet identity not resolvable", "blocked-by-policy");
|
|
5281
|
+
return;
|
|
5282
|
+
}
|
|
5283
|
+
const controller = new AbortController();
|
|
5284
|
+
trackRequest(state, requestId, windowId, controller);
|
|
5285
|
+
try {
|
|
5286
|
+
const item = await fetchResourceItem(options, identity, url, init, controller.signal);
|
|
5287
|
+
if (!item.ok) {
|
|
5288
|
+
sendResourceError(send, requestId, item.code, item.message, item.error);
|
|
5289
|
+
return;
|
|
5290
|
+
}
|
|
5291
|
+
send({
|
|
5292
|
+
type: "resource.bytes.result",
|
|
5293
|
+
id: requestId,
|
|
4649
5294
|
requestId,
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
5295
|
+
blob: item.blob,
|
|
5296
|
+
mime: item.mime,
|
|
5297
|
+
status: item.status,
|
|
5298
|
+
headers: item.headers,
|
|
5299
|
+
bodyBase64: item.bodyBase64
|
|
5300
|
+
});
|
|
4653
5301
|
} finally {
|
|
4654
5302
|
untrackRequest(state, requestId);
|
|
4655
5303
|
}
|
|
4656
5304
|
}
|
|
4657
|
-
function
|
|
4658
|
-
const
|
|
4659
|
-
if (
|
|
4660
|
-
|
|
5305
|
+
async function handleBytesMany(options, state, windowId, msg, send) {
|
|
5306
|
+
const { requestId, urls, init } = msg;
|
|
5307
|
+
if (!Array.isArray(urls) || urls.length === 0 || urls.some((url) => typeof url !== "string")) {
|
|
5308
|
+
sendBytesManyError(send, requestId, "invalid-url", "resource.bytesMany requires a non-empty urls array", "invalid-request");
|
|
5309
|
+
return;
|
|
4661
5310
|
}
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
5311
|
+
const identity = options.resolveIdentity(windowId);
|
|
5312
|
+
if (!identity) {
|
|
5313
|
+
sendBytesManyError(send, requestId, "denied", "napplet identity not resolvable", "blocked-by-policy");
|
|
5314
|
+
return;
|
|
5315
|
+
}
|
|
5316
|
+
const controller = new AbortController();
|
|
5317
|
+
trackRequest(state, requestId, windowId, controller);
|
|
5318
|
+
try {
|
|
5319
|
+
const items = [];
|
|
5320
|
+
for (const url of urls) {
|
|
5321
|
+
const item = await fetchResourceItem(options, identity, url, init, controller.signal);
|
|
5322
|
+
if (item.ok) {
|
|
5323
|
+
items.push({
|
|
5324
|
+
url: item.url,
|
|
5325
|
+
ok: true,
|
|
5326
|
+
blob: item.blob,
|
|
5327
|
+
mime: item.mime
|
|
5328
|
+
});
|
|
5329
|
+
} else {
|
|
5330
|
+
items.push({
|
|
5331
|
+
url: item.url,
|
|
5332
|
+
ok: false,
|
|
5333
|
+
error: item.error,
|
|
5334
|
+
code: item.code,
|
|
5335
|
+
message: item.message
|
|
5336
|
+
});
|
|
5337
|
+
}
|
|
5338
|
+
}
|
|
5339
|
+
send({
|
|
5340
|
+
type: "resource.bytesMany.result",
|
|
5341
|
+
id: requestId,
|
|
5342
|
+
requestId,
|
|
5343
|
+
items
|
|
5344
|
+
});
|
|
5345
|
+
} finally {
|
|
5346
|
+
untrackRequest(state, requestId);
|
|
5347
|
+
}
|
|
5348
|
+
}
|
|
5349
|
+
function handleCancel(state, requestId) {
|
|
5350
|
+
const entry = state.inFlight.get(requestId);
|
|
5351
|
+
if (entry) {
|
|
5352
|
+
entry.controller.abort();
|
|
5353
|
+
}
|
|
5354
|
+
}
|
|
5355
|
+
function destroyWindowRequests(state, windowId) {
|
|
5356
|
+
const requestIds = state.perWindow.get(windowId);
|
|
5357
|
+
if (!requestIds) return;
|
|
5358
|
+
for (const requestId of requestIds) {
|
|
5359
|
+
const entry = state.inFlight.get(requestId);
|
|
5360
|
+
if (entry) {
|
|
5361
|
+
entry.controller.abort();
|
|
5362
|
+
state.inFlight.delete(requestId);
|
|
5363
|
+
}
|
|
4672
5364
|
}
|
|
4673
5365
|
state.perWindow.delete(windowId);
|
|
4674
5366
|
}
|
|
@@ -4689,13 +5381,24 @@ function createResourceService(options) {
|
|
|
4689
5381
|
switch (message.type) {
|
|
4690
5382
|
case "resource.bytes": {
|
|
4691
5383
|
const m = message;
|
|
4692
|
-
|
|
5384
|
+
const requestId = requestIdFromMessage(m);
|
|
5385
|
+
if (!requestId || typeof m.url !== "string") return;
|
|
5386
|
+
handleBytes(options, state, windowId, { requestId, url: m.url, init: m.init }, send).catch(() => {
|
|
5387
|
+
});
|
|
5388
|
+
return;
|
|
5389
|
+
}
|
|
5390
|
+
case "resource.bytesMany": {
|
|
5391
|
+
const m = message;
|
|
5392
|
+
const requestId = requestIdFromMessage(m);
|
|
5393
|
+
if (!requestId) return;
|
|
5394
|
+
handleBytesMany(options, state, windowId, { requestId, urls: m.urls ?? [], init: m.init }, send).catch(() => {
|
|
4693
5395
|
});
|
|
4694
5396
|
return;
|
|
4695
5397
|
}
|
|
4696
5398
|
case "resource.cancel": {
|
|
4697
5399
|
const m = message;
|
|
4698
|
-
|
|
5400
|
+
const requestId = requestIdFromMessage(m);
|
|
5401
|
+
if (requestId) handleCancel(state, requestId);
|
|
4699
5402
|
return;
|
|
4700
5403
|
}
|
|
4701
5404
|
default:
|
|
@@ -4973,7 +5676,7 @@ function createIntentService(options) {
|
|
|
4973
5676
|
send({ type: "intent.changed", availability });
|
|
4974
5677
|
}
|
|
4975
5678
|
});
|
|
4976
|
-
function
|
|
5679
|
+
function settle6(call, send, resultType, id, onValue) {
|
|
4977
5680
|
let pending;
|
|
4978
5681
|
try {
|
|
4979
5682
|
pending = Promise.resolve(call());
|
|
@@ -4991,7 +5694,7 @@ function createIntentService(options) {
|
|
|
4991
5694
|
send({ type: "intent.invoke.result", id, error: "invalid request" });
|
|
4992
5695
|
return;
|
|
4993
5696
|
}
|
|
4994
|
-
|
|
5697
|
+
settle6(
|
|
4995
5698
|
() => resolver.invoke(request, { windowId }),
|
|
4996
5699
|
send,
|
|
4997
5700
|
"intent.invoke.result",
|
|
@@ -5007,7 +5710,7 @@ function createIntentService(options) {
|
|
|
5007
5710
|
return;
|
|
5008
5711
|
}
|
|
5009
5712
|
const archetype = m.archetype;
|
|
5010
|
-
|
|
5713
|
+
settle6(
|
|
5011
5714
|
() => resolver.available(archetype),
|
|
5012
5715
|
send,
|
|
5013
5716
|
"intent.available.result",
|
|
@@ -5018,7 +5721,7 @@ function createIntentService(options) {
|
|
|
5018
5721
|
function handleHandlers(msg, send) {
|
|
5019
5722
|
const m = msg;
|
|
5020
5723
|
const id = m.id ?? "";
|
|
5021
|
-
|
|
5724
|
+
settle6(
|
|
5022
5725
|
() => resolver.handlers(),
|
|
5023
5726
|
send,
|
|
5024
5727
|
"intent.handlers.result",
|
|
@@ -5153,6 +5856,708 @@ function toErrorMessage5(err) {
|
|
|
5153
5856
|
if (typeof err === "string") return err;
|
|
5154
5857
|
return "cvm request failed";
|
|
5155
5858
|
}
|
|
5859
|
+
var LINK_SERVICE_VERSION = "1.0.0";
|
|
5860
|
+
var DEFAULT_ALLOWED_PROTOCOLS = ["http:", "https:"];
|
|
5861
|
+
function denied(id, error) {
|
|
5862
|
+
return { type: "link.open.result", id, status: "denied", error };
|
|
5863
|
+
}
|
|
5864
|
+
function parseLinkUrl(id, rawUrl) {
|
|
5865
|
+
try {
|
|
5866
|
+
return new URL(rawUrl);
|
|
5867
|
+
} catch {
|
|
5868
|
+
return denied(id, "invalid-url");
|
|
5869
|
+
}
|
|
5870
|
+
}
|
|
5871
|
+
function isProtocolAllowed(url, allowedProtocols) {
|
|
5872
|
+
return allowedProtocols.includes(url.protocol);
|
|
5873
|
+
}
|
|
5874
|
+
async function handleOpen(options, windowId, message, send) {
|
|
5875
|
+
const parsed = parseLinkUrl(message.id, message.url);
|
|
5876
|
+
if ("type" in parsed) {
|
|
5877
|
+
send(parsed);
|
|
5878
|
+
return;
|
|
5879
|
+
}
|
|
5880
|
+
const allowedProtocols = options.allowedProtocols ?? DEFAULT_ALLOWED_PROTOCOLS;
|
|
5881
|
+
if (!isProtocolAllowed(parsed, allowedProtocols)) {
|
|
5882
|
+
send(denied(message.id, "unsupported-scheme"));
|
|
5883
|
+
return;
|
|
5884
|
+
}
|
|
5885
|
+
if (!options.open) {
|
|
5886
|
+
send(denied(message.id, "blocked-by-policy"));
|
|
5887
|
+
return;
|
|
5888
|
+
}
|
|
5889
|
+
try {
|
|
5890
|
+
const result = await options.open({ windowId, url: parsed, options: message.options });
|
|
5891
|
+
send({
|
|
5892
|
+
type: "link.open.result",
|
|
5893
|
+
id: message.id,
|
|
5894
|
+
status: result.status,
|
|
5895
|
+
...result.status === "denied" ? { error: "blocked-by-policy" } : {}
|
|
5896
|
+
});
|
|
5897
|
+
} catch {
|
|
5898
|
+
send(denied(message.id, "blocked-by-policy"));
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5901
|
+
function createLinkService(options = {}) {
|
|
5902
|
+
const descriptor = {
|
|
5903
|
+
name: "link",
|
|
5904
|
+
version: LINK_SERVICE_VERSION,
|
|
5905
|
+
description: "NAP-LINK reference handler for shell-mediated link opening"
|
|
5906
|
+
};
|
|
5907
|
+
return {
|
|
5908
|
+
descriptor,
|
|
5909
|
+
handleMessage(windowId, message, send) {
|
|
5910
|
+
if (message.type === "link.open") {
|
|
5911
|
+
void handleOpen(options, windowId, message, send);
|
|
5912
|
+
return;
|
|
5913
|
+
}
|
|
5914
|
+
const id = message.id ?? "";
|
|
5915
|
+
send({
|
|
5916
|
+
type: `${message.type}.error`,
|
|
5917
|
+
id,
|
|
5918
|
+
error: `Unknown link method: ${message.type}`
|
|
5919
|
+
});
|
|
5920
|
+
},
|
|
5921
|
+
onWindowDestroyed(_windowId) {
|
|
5922
|
+
}
|
|
5923
|
+
};
|
|
5924
|
+
}
|
|
5925
|
+
var LISTS_SERVICE_VERSION = "1.0.0";
|
|
5926
|
+
var LISTS_DESCRIPTOR = {
|
|
5927
|
+
name: "lists",
|
|
5928
|
+
version: LISTS_SERVICE_VERSION,
|
|
5929
|
+
description: "NAP-LISTS reference handler for shell-mediated NIP-51 list mutations"
|
|
5930
|
+
};
|
|
5931
|
+
function errorMessage(err, fallback) {
|
|
5932
|
+
if (err instanceof Error) return err.message;
|
|
5933
|
+
if (typeof err === "string") return err;
|
|
5934
|
+
return fallback;
|
|
5935
|
+
}
|
|
5936
|
+
function settle(call, send, okFalse, onValue) {
|
|
5937
|
+
let pending;
|
|
5938
|
+
try {
|
|
5939
|
+
pending = Promise.resolve(call());
|
|
5940
|
+
} catch (err) {
|
|
5941
|
+
send(okFalse(errorMessage(err, "lists request failed")));
|
|
5942
|
+
return;
|
|
5943
|
+
}
|
|
5944
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage(err, "lists request failed"))));
|
|
5945
|
+
}
|
|
5946
|
+
function unsupportedMutation(resultType, id) {
|
|
5947
|
+
return {
|
|
5948
|
+
type: resultType,
|
|
5949
|
+
id,
|
|
5950
|
+
ok: false,
|
|
5951
|
+
error: "unsupported",
|
|
5952
|
+
reason: `${resultType.replace(".result", "")} unavailable`,
|
|
5953
|
+
supported: []
|
|
5954
|
+
};
|
|
5955
|
+
}
|
|
5956
|
+
function settleMutation(hook, message, context, send, resultType) {
|
|
5957
|
+
if (!hook) {
|
|
5958
|
+
send(unsupportedMutation(resultType, message.id));
|
|
5959
|
+
return;
|
|
5960
|
+
}
|
|
5961
|
+
settle(
|
|
5962
|
+
() => hook(message.list, message.items, message.options, context),
|
|
5963
|
+
send,
|
|
5964
|
+
(error) => ({ type: resultType, id: message.id, ok: false, error: "list-unavailable", reason: error }),
|
|
5965
|
+
(result) => ({ type: resultType, id: message.id, ...result })
|
|
5966
|
+
);
|
|
5967
|
+
}
|
|
5968
|
+
function createListsService(options = {}) {
|
|
5969
|
+
return {
|
|
5970
|
+
descriptor: LISTS_DESCRIPTOR,
|
|
5971
|
+
handleMessage(windowId, message, send) {
|
|
5972
|
+
const id = message.id ?? "";
|
|
5973
|
+
const context = { windowId };
|
|
5974
|
+
if (message.type === "lists.supported") {
|
|
5975
|
+
if (!options.supported) {
|
|
5976
|
+
send({ type: "lists.supported.result", id, lists: [] });
|
|
5977
|
+
return;
|
|
5978
|
+
}
|
|
5979
|
+
settle(
|
|
5980
|
+
() => options.supported(context),
|
|
5981
|
+
send,
|
|
5982
|
+
(error) => ({ type: "lists.supported.result", id, error }),
|
|
5983
|
+
(lists) => ({ type: "lists.supported.result", id, lists: [...lists] })
|
|
5984
|
+
);
|
|
5985
|
+
return;
|
|
5986
|
+
}
|
|
5987
|
+
if (message.type === "lists.add") {
|
|
5988
|
+
settleMutation(options.add, message, context, send, "lists.add.result");
|
|
5989
|
+
return;
|
|
5990
|
+
}
|
|
5991
|
+
if (message.type === "lists.remove") {
|
|
5992
|
+
settleMutation(options.remove, message, context, send, "lists.remove.result");
|
|
5993
|
+
return;
|
|
5994
|
+
}
|
|
5995
|
+
send({
|
|
5996
|
+
type: `${message.type}.error`,
|
|
5997
|
+
id,
|
|
5998
|
+
error: `Unknown lists method: ${message.type}`
|
|
5999
|
+
});
|
|
6000
|
+
},
|
|
6001
|
+
onWindowDestroyed(_windowId) {
|
|
6002
|
+
}
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
6005
|
+
var SERIAL_SERVICE_VERSION = "1.0.0";
|
|
6006
|
+
var SERIAL_DESCRIPTOR = {
|
|
6007
|
+
name: "serial",
|
|
6008
|
+
version: SERIAL_SERVICE_VERSION,
|
|
6009
|
+
description: "NAP-SERIAL reference handler for shell-mediated serial sessions"
|
|
6010
|
+
};
|
|
6011
|
+
function errorMessage2(err, fallback) {
|
|
6012
|
+
if (err instanceof Error) return err.message;
|
|
6013
|
+
if (typeof err === "string") return err;
|
|
6014
|
+
return fallback;
|
|
6015
|
+
}
|
|
6016
|
+
function settle2(call, send, okFalse, onValue) {
|
|
6017
|
+
let pending;
|
|
6018
|
+
try {
|
|
6019
|
+
pending = Promise.resolve(call());
|
|
6020
|
+
} catch (err) {
|
|
6021
|
+
send(okFalse(errorMessage2(err, "serial request failed")));
|
|
6022
|
+
return;
|
|
6023
|
+
}
|
|
6024
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage2(err, "serial request failed"))));
|
|
6025
|
+
}
|
|
6026
|
+
function unsupported(resultType, id) {
|
|
6027
|
+
return {
|
|
6028
|
+
type: resultType,
|
|
6029
|
+
id,
|
|
6030
|
+
error: `${resultType.replace(".result", "")} unavailable`
|
|
6031
|
+
};
|
|
6032
|
+
}
|
|
6033
|
+
function createSerialService(options = {}) {
|
|
6034
|
+
return {
|
|
6035
|
+
descriptor: SERIAL_DESCRIPTOR,
|
|
6036
|
+
handleMessage(windowId, message, send) {
|
|
6037
|
+
const id = message.id ?? "";
|
|
6038
|
+
const context = { windowId };
|
|
6039
|
+
if (message.type === "serial.open") {
|
|
6040
|
+
if (!options.open) {
|
|
6041
|
+
send(unsupported("serial.open.result", id));
|
|
6042
|
+
return;
|
|
6043
|
+
}
|
|
6044
|
+
const serialMessage = message;
|
|
6045
|
+
settle2(
|
|
6046
|
+
() => options.open(serialMessage.request, context),
|
|
6047
|
+
send,
|
|
6048
|
+
(error) => ({ type: "serial.open.result", id, error }),
|
|
6049
|
+
(result) => ({ type: "serial.open.result", id, session: result.session })
|
|
6050
|
+
);
|
|
6051
|
+
return;
|
|
6052
|
+
}
|
|
6053
|
+
if (message.type === "serial.write") {
|
|
6054
|
+
if (!options.write) {
|
|
6055
|
+
send(unsupported("serial.write.result", id));
|
|
6056
|
+
return;
|
|
6057
|
+
}
|
|
6058
|
+
const serialMessage = message;
|
|
6059
|
+
settle2(
|
|
6060
|
+
() => options.write(serialMessage.sessionId, serialMessage.data, context),
|
|
6061
|
+
send,
|
|
6062
|
+
(error) => ({ type: "serial.write.result", id, error }),
|
|
6063
|
+
() => ({ type: "serial.write.result", id })
|
|
6064
|
+
);
|
|
6065
|
+
return;
|
|
6066
|
+
}
|
|
6067
|
+
if (message.type === "serial.close") {
|
|
6068
|
+
if (!options.close) {
|
|
6069
|
+
send(unsupported("serial.close.result", id));
|
|
6070
|
+
return;
|
|
6071
|
+
}
|
|
6072
|
+
const serialMessage = message;
|
|
6073
|
+
settle2(
|
|
6074
|
+
() => options.close(serialMessage.sessionId, serialMessage.reason, context),
|
|
6075
|
+
send,
|
|
6076
|
+
(error) => ({ type: "serial.close.result", id, error }),
|
|
6077
|
+
() => ({ type: "serial.close.result", id })
|
|
6078
|
+
);
|
|
6079
|
+
return;
|
|
6080
|
+
}
|
|
6081
|
+
send({
|
|
6082
|
+
type: `${message.type}.error`,
|
|
6083
|
+
id,
|
|
6084
|
+
error: `Unknown serial method: ${message.type}`
|
|
6085
|
+
});
|
|
6086
|
+
},
|
|
6087
|
+
onWindowDestroyed(windowId) {
|
|
6088
|
+
options.destroyWindow?.(windowId);
|
|
6089
|
+
}
|
|
6090
|
+
};
|
|
6091
|
+
}
|
|
6092
|
+
var BLE_SERVICE_VERSION = "1.0.0";
|
|
6093
|
+
var BLE_DESCRIPTOR = {
|
|
6094
|
+
name: "ble",
|
|
6095
|
+
version: BLE_SERVICE_VERSION,
|
|
6096
|
+
description: "NAP-BLE reference handler for shell-mediated BLE/GATT sessions"
|
|
6097
|
+
};
|
|
6098
|
+
function errorMessage3(err, fallback) {
|
|
6099
|
+
if (err instanceof Error) return err.message;
|
|
6100
|
+
if (typeof err === "string") return err;
|
|
6101
|
+
return fallback;
|
|
6102
|
+
}
|
|
6103
|
+
function settle3(call, send, okFalse, onValue) {
|
|
6104
|
+
let pending;
|
|
6105
|
+
try {
|
|
6106
|
+
pending = Promise.resolve(call());
|
|
6107
|
+
} catch (err) {
|
|
6108
|
+
send(okFalse(errorMessage3(err, "ble request failed")));
|
|
6109
|
+
return;
|
|
6110
|
+
}
|
|
6111
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage3(err, "ble request failed"))));
|
|
6112
|
+
}
|
|
6113
|
+
function unsupported2(resultType, id) {
|
|
6114
|
+
return {
|
|
6115
|
+
type: resultType,
|
|
6116
|
+
id,
|
|
6117
|
+
error: `${resultType.replace(".result", "")} unavailable`
|
|
6118
|
+
};
|
|
6119
|
+
}
|
|
6120
|
+
function createBleService(options = {}) {
|
|
6121
|
+
return {
|
|
6122
|
+
descriptor: BLE_DESCRIPTOR,
|
|
6123
|
+
handleMessage(windowId, message, send) {
|
|
6124
|
+
const id = message.id ?? "";
|
|
6125
|
+
const context = { windowId };
|
|
6126
|
+
if (message.type === "ble.open") {
|
|
6127
|
+
if (!options.open) {
|
|
6128
|
+
send(unsupported2("ble.open.result", id));
|
|
6129
|
+
return;
|
|
6130
|
+
}
|
|
6131
|
+
const bleMessage = message;
|
|
6132
|
+
settle3(
|
|
6133
|
+
() => options.open(bleMessage.request, context),
|
|
6134
|
+
send,
|
|
6135
|
+
(error) => ({ type: "ble.open.result", id, error }),
|
|
6136
|
+
(result) => ({ type: "ble.open.result", id, session: result.session })
|
|
6137
|
+
);
|
|
6138
|
+
return;
|
|
6139
|
+
}
|
|
6140
|
+
if (message.type === "ble.services") {
|
|
6141
|
+
if (!options.services) {
|
|
6142
|
+
send(unsupported2("ble.services.result", id));
|
|
6143
|
+
return;
|
|
6144
|
+
}
|
|
6145
|
+
const bleMessage = message;
|
|
6146
|
+
settle3(
|
|
6147
|
+
() => options.services(bleMessage.sessionId, context),
|
|
6148
|
+
send,
|
|
6149
|
+
(error) => ({ type: "ble.services.result", id, error }),
|
|
6150
|
+
(services) => ({ type: "ble.services.result", id, services })
|
|
6151
|
+
);
|
|
6152
|
+
return;
|
|
6153
|
+
}
|
|
6154
|
+
if (message.type === "ble.read") {
|
|
6155
|
+
if (!options.read) {
|
|
6156
|
+
send(unsupported2("ble.read.result", id));
|
|
6157
|
+
return;
|
|
6158
|
+
}
|
|
6159
|
+
const bleMessage = message;
|
|
6160
|
+
settle3(
|
|
6161
|
+
() => options.read(bleMessage.sessionId, bleMessage.target, context),
|
|
6162
|
+
send,
|
|
6163
|
+
(error) => ({ type: "ble.read.result", id, error }),
|
|
6164
|
+
(data) => ({ type: "ble.read.result", id, data })
|
|
6165
|
+
);
|
|
6166
|
+
return;
|
|
6167
|
+
}
|
|
6168
|
+
if (message.type === "ble.write") {
|
|
6169
|
+
if (!options.write) {
|
|
6170
|
+
send(unsupported2("ble.write.result", id));
|
|
6171
|
+
return;
|
|
6172
|
+
}
|
|
6173
|
+
const bleMessage = message;
|
|
6174
|
+
settle3(
|
|
6175
|
+
() => options.write(bleMessage.sessionId, bleMessage.target, bleMessage.data, bleMessage.options, context),
|
|
6176
|
+
send,
|
|
6177
|
+
(error) => ({ type: "ble.write.result", id, error }),
|
|
6178
|
+
() => ({ type: "ble.write.result", id })
|
|
6179
|
+
);
|
|
6180
|
+
return;
|
|
6181
|
+
}
|
|
6182
|
+
if (message.type === "ble.subscribe") {
|
|
6183
|
+
if (!options.subscribe) {
|
|
6184
|
+
send(unsupported2("ble.subscribe.result", id));
|
|
6185
|
+
return;
|
|
6186
|
+
}
|
|
6187
|
+
const bleMessage = message;
|
|
6188
|
+
settle3(
|
|
6189
|
+
() => options.subscribe(bleMessage.sessionId, bleMessage.target, context),
|
|
6190
|
+
send,
|
|
6191
|
+
(error) => ({ type: "ble.subscribe.result", id, error }),
|
|
6192
|
+
() => ({ type: "ble.subscribe.result", id })
|
|
6193
|
+
);
|
|
6194
|
+
return;
|
|
6195
|
+
}
|
|
6196
|
+
if (message.type === "ble.unsubscribe") {
|
|
6197
|
+
if (!options.unsubscribe) {
|
|
6198
|
+
send(unsupported2("ble.unsubscribe.result", id));
|
|
6199
|
+
return;
|
|
6200
|
+
}
|
|
6201
|
+
const bleMessage = message;
|
|
6202
|
+
settle3(
|
|
6203
|
+
() => options.unsubscribe(bleMessage.sessionId, bleMessage.target, context),
|
|
6204
|
+
send,
|
|
6205
|
+
(error) => ({ type: "ble.unsubscribe.result", id, error }),
|
|
6206
|
+
() => ({ type: "ble.unsubscribe.result", id })
|
|
6207
|
+
);
|
|
6208
|
+
return;
|
|
6209
|
+
}
|
|
6210
|
+
if (message.type === "ble.close") {
|
|
6211
|
+
if (!options.close) {
|
|
6212
|
+
send(unsupported2("ble.close.result", id));
|
|
6213
|
+
return;
|
|
6214
|
+
}
|
|
6215
|
+
const bleMessage = message;
|
|
6216
|
+
settle3(
|
|
6217
|
+
() => options.close(bleMessage.sessionId, bleMessage.reason, context),
|
|
6218
|
+
send,
|
|
6219
|
+
(error) => ({ type: "ble.close.result", id, error }),
|
|
6220
|
+
() => ({ type: "ble.close.result", id })
|
|
6221
|
+
);
|
|
6222
|
+
return;
|
|
6223
|
+
}
|
|
6224
|
+
send({
|
|
6225
|
+
type: `${message.type}.error`,
|
|
6226
|
+
id,
|
|
6227
|
+
error: `Unknown ble method: ${message.type}`
|
|
6228
|
+
});
|
|
6229
|
+
},
|
|
6230
|
+
onWindowDestroyed(windowId) {
|
|
6231
|
+
options.destroyWindow?.(windowId);
|
|
6232
|
+
}
|
|
6233
|
+
};
|
|
6234
|
+
}
|
|
6235
|
+
var WEBRTC_SERVICE_VERSION = "1.0.0";
|
|
6236
|
+
var WEBRTC_DESCRIPTOR = {
|
|
6237
|
+
name: "webrtc",
|
|
6238
|
+
version: WEBRTC_SERVICE_VERSION,
|
|
6239
|
+
description: "NAP-WEBRTC reference handler for shell-mediated WebRTC sessions"
|
|
6240
|
+
};
|
|
6241
|
+
function errorMessage4(err, fallback) {
|
|
6242
|
+
if (err instanceof Error) return err.message;
|
|
6243
|
+
if (typeof err === "string") return err;
|
|
6244
|
+
return fallback;
|
|
6245
|
+
}
|
|
6246
|
+
function settle4(call, send, okFalse, onValue) {
|
|
6247
|
+
let pending;
|
|
6248
|
+
try {
|
|
6249
|
+
pending = Promise.resolve(call());
|
|
6250
|
+
} catch (err) {
|
|
6251
|
+
send(okFalse(errorMessage4(err, "webrtc request failed")));
|
|
6252
|
+
return;
|
|
6253
|
+
}
|
|
6254
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage4(err, "webrtc request failed"))));
|
|
6255
|
+
}
|
|
6256
|
+
function unsupported3(resultType, id) {
|
|
6257
|
+
return {
|
|
6258
|
+
type: resultType,
|
|
6259
|
+
id,
|
|
6260
|
+
error: `${resultType.replace(".result", "")} unavailable`
|
|
6261
|
+
};
|
|
6262
|
+
}
|
|
6263
|
+
function createContext(windowId, send) {
|
|
6264
|
+
return {
|
|
6265
|
+
windowId,
|
|
6266
|
+
emit(event) {
|
|
6267
|
+
send({ type: "webrtc.event", event });
|
|
6268
|
+
}
|
|
6269
|
+
};
|
|
6270
|
+
}
|
|
6271
|
+
function createWebrtcService(options = {}) {
|
|
6272
|
+
return {
|
|
6273
|
+
descriptor: WEBRTC_DESCRIPTOR,
|
|
6274
|
+
handleMessage(windowId, message, send) {
|
|
6275
|
+
const id = message.id ?? "";
|
|
6276
|
+
const context = createContext(windowId, send);
|
|
6277
|
+
if (message.type === "webrtc.open") {
|
|
6278
|
+
if (!options.open) {
|
|
6279
|
+
send(unsupported3("webrtc.open.result", id));
|
|
6280
|
+
return;
|
|
6281
|
+
}
|
|
6282
|
+
const webrtcMessage = message;
|
|
6283
|
+
settle4(
|
|
6284
|
+
() => options.open(webrtcMessage.request, context),
|
|
6285
|
+
send,
|
|
6286
|
+
(error) => ({ type: "webrtc.open.result", id, error }),
|
|
6287
|
+
(result) => ({ type: "webrtc.open.result", id, session: result.session })
|
|
6288
|
+
);
|
|
6289
|
+
return;
|
|
6290
|
+
}
|
|
6291
|
+
if (message.type === "webrtc.send") {
|
|
6292
|
+
if (!options.send) {
|
|
6293
|
+
send(unsupported3("webrtc.send.result", id));
|
|
6294
|
+
return;
|
|
6295
|
+
}
|
|
6296
|
+
const webrtcMessage = message;
|
|
6297
|
+
settle4(
|
|
6298
|
+
() => options.send(webrtcMessage.sessionId, webrtcMessage.payload, context),
|
|
6299
|
+
send,
|
|
6300
|
+
(error) => ({ type: "webrtc.send.result", id, error }),
|
|
6301
|
+
() => ({ type: "webrtc.send.result", id })
|
|
6302
|
+
);
|
|
6303
|
+
return;
|
|
6304
|
+
}
|
|
6305
|
+
if (message.type === "webrtc.close") {
|
|
6306
|
+
if (!options.close) {
|
|
6307
|
+
send(unsupported3("webrtc.close.result", id));
|
|
6308
|
+
return;
|
|
6309
|
+
}
|
|
6310
|
+
const webrtcMessage = message;
|
|
6311
|
+
settle4(
|
|
6312
|
+
() => options.close(webrtcMessage.sessionId, webrtcMessage.reason, context),
|
|
6313
|
+
send,
|
|
6314
|
+
(error) => ({ type: "webrtc.close.result", id, error }),
|
|
6315
|
+
() => ({ type: "webrtc.close.result", id })
|
|
6316
|
+
);
|
|
6317
|
+
return;
|
|
6318
|
+
}
|
|
6319
|
+
send({
|
|
6320
|
+
type: `${message.type}.error`,
|
|
6321
|
+
id,
|
|
6322
|
+
error: `Unknown webrtc method: ${message.type}`
|
|
6323
|
+
});
|
|
6324
|
+
},
|
|
6325
|
+
onWindowDestroyed(windowId) {
|
|
6326
|
+
options.destroyWindow?.(windowId);
|
|
6327
|
+
}
|
|
6328
|
+
};
|
|
6329
|
+
}
|
|
6330
|
+
var COMMON_SERVICE_VERSION = "1.0.0";
|
|
6331
|
+
var BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
6332
|
+
var COMMON_DESCRIPTOR = {
|
|
6333
|
+
name: "common",
|
|
6334
|
+
version: COMMON_SERVICE_VERSION,
|
|
6335
|
+
description: "NAP-COMMON reference handler for shell-mediated social helpers"
|
|
6336
|
+
};
|
|
6337
|
+
function errorMessage5(err, fallback) {
|
|
6338
|
+
if (err instanceof Error) return err.message;
|
|
6339
|
+
if (typeof err === "string") return err;
|
|
6340
|
+
return fallback;
|
|
6341
|
+
}
|
|
6342
|
+
function encodeNip19(input) {
|
|
6343
|
+
try {
|
|
6344
|
+
switch (input.type) {
|
|
6345
|
+
case "npub":
|
|
6346
|
+
return { ok: true, value: npubEncode(input.hex), nip19Type: input.type };
|
|
6347
|
+
case "note":
|
|
6348
|
+
return { ok: true, value: noteEncode(input.hex), nip19Type: input.type };
|
|
6349
|
+
case "nprofile":
|
|
6350
|
+
return { ok: true, value: nprofileEncode({ pubkey: input.pubkey, relays: input.relays }), nip19Type: input.type };
|
|
6351
|
+
case "nevent":
|
|
6352
|
+
return {
|
|
6353
|
+
ok: true,
|
|
6354
|
+
value: neventEncode({ id: input.eventId, relays: input.relays, author: input.author, kind: input.kind }),
|
|
6355
|
+
nip19Type: input.type
|
|
6356
|
+
};
|
|
6357
|
+
case "naddr":
|
|
6358
|
+
return {
|
|
6359
|
+
ok: true,
|
|
6360
|
+
value: naddrEncode({ identifier: input.identifier, pubkey: input.pubkey, kind: input.kind, relays: input.relays }),
|
|
6361
|
+
nip19Type: input.type
|
|
6362
|
+
};
|
|
6363
|
+
case "nrelay":
|
|
6364
|
+
return { ok: true, value: encodeBytes("nrelay", new TextEncoder().encode(input.relay)), nip19Type: input.type };
|
|
6365
|
+
default:
|
|
6366
|
+
return { ok: false, error: "unsupported NIP-19 type" };
|
|
6367
|
+
}
|
|
6368
|
+
} catch (err) {
|
|
6369
|
+
return { ok: false, error: errorMessage5(err, "NIP-19 encode failed") };
|
|
6370
|
+
}
|
|
6371
|
+
}
|
|
6372
|
+
function decodeNip19Value(value) {
|
|
6373
|
+
try {
|
|
6374
|
+
const decoded = decode(value);
|
|
6375
|
+
switch (decoded.type) {
|
|
6376
|
+
case "npub":
|
|
6377
|
+
case "note":
|
|
6378
|
+
return { ok: true, nip19Type: decoded.type, hex: decoded.data };
|
|
6379
|
+
case "nprofile":
|
|
6380
|
+
return { ok: true, nip19Type: decoded.type, pubkey: decoded.data.pubkey, relays: decoded.data.relays };
|
|
6381
|
+
case "nevent":
|
|
6382
|
+
return {
|
|
6383
|
+
ok: true,
|
|
6384
|
+
nip19Type: decoded.type,
|
|
6385
|
+
eventId: decoded.data.id,
|
|
6386
|
+
relays: decoded.data.relays,
|
|
6387
|
+
author: decoded.data.author,
|
|
6388
|
+
kind: decoded.data.kind
|
|
6389
|
+
};
|
|
6390
|
+
case "naddr":
|
|
6391
|
+
return {
|
|
6392
|
+
ok: true,
|
|
6393
|
+
nip19Type: decoded.type,
|
|
6394
|
+
identifier: decoded.data.identifier,
|
|
6395
|
+
pubkey: decoded.data.pubkey,
|
|
6396
|
+
kind: decoded.data.kind,
|
|
6397
|
+
relays: decoded.data.relays
|
|
6398
|
+
};
|
|
6399
|
+
default:
|
|
6400
|
+
return { ok: false, error: "unsupported NIP-19 type" };
|
|
6401
|
+
}
|
|
6402
|
+
} catch (err) {
|
|
6403
|
+
if (value.startsWith("nrelay1")) return decodeNrelay(value);
|
|
6404
|
+
return { ok: false, error: errorMessage5(err, "NIP-19 decode failed") };
|
|
6405
|
+
}
|
|
6406
|
+
}
|
|
6407
|
+
function decodeNrelay(value) {
|
|
6408
|
+
try {
|
|
6409
|
+
const separator = value.lastIndexOf("1");
|
|
6410
|
+
if (separator <= 0 || separator + 7 > value.length) return { ok: false, error: "invalid nrelay value" };
|
|
6411
|
+
const dataPart = value.slice(separator + 1);
|
|
6412
|
+
const words = [...dataPart].map((char) => {
|
|
6413
|
+
const index = BECH32_CHARSET.indexOf(char);
|
|
6414
|
+
if (index === -1) throw new Error("invalid nrelay character");
|
|
6415
|
+
return index;
|
|
6416
|
+
});
|
|
6417
|
+
const payloadWords = words.slice(0, -6);
|
|
6418
|
+
const bytes = convertBits(payloadWords, 5, 8, false);
|
|
6419
|
+
return { ok: true, nip19Type: "nrelay", relay: new TextDecoder().decode(Uint8Array.from(bytes)) };
|
|
6420
|
+
} catch (err) {
|
|
6421
|
+
return { ok: false, error: errorMessage5(err, "invalid nrelay value") };
|
|
6422
|
+
}
|
|
6423
|
+
}
|
|
6424
|
+
function convertBits(data, fromBits, toBits, pad) {
|
|
6425
|
+
let acc = 0;
|
|
6426
|
+
let bits = 0;
|
|
6427
|
+
const result = [];
|
|
6428
|
+
const maxv = (1 << toBits) - 1;
|
|
6429
|
+
const maxAcc = (1 << fromBits + toBits - 1) - 1;
|
|
6430
|
+
for (const value of data) {
|
|
6431
|
+
if (value < 0 || value >> fromBits !== 0) throw new Error("invalid bech32 data");
|
|
6432
|
+
acc = (acc << fromBits | value) & maxAcc;
|
|
6433
|
+
bits += fromBits;
|
|
6434
|
+
while (bits >= toBits) {
|
|
6435
|
+
bits -= toBits;
|
|
6436
|
+
result.push(acc >> bits & maxv);
|
|
6437
|
+
}
|
|
6438
|
+
}
|
|
6439
|
+
if (pad) {
|
|
6440
|
+
if (bits > 0) result.push(acc << toBits - bits & maxv);
|
|
6441
|
+
} else if (bits >= fromBits || (acc << toBits - bits & maxv) !== 0) {
|
|
6442
|
+
throw new Error("invalid bech32 padding");
|
|
6443
|
+
}
|
|
6444
|
+
return result;
|
|
6445
|
+
}
|
|
6446
|
+
function settle5(call, send, okFalse, onValue) {
|
|
6447
|
+
let pending;
|
|
6448
|
+
try {
|
|
6449
|
+
pending = Promise.resolve(call());
|
|
6450
|
+
} catch (err) {
|
|
6451
|
+
send(okFalse(errorMessage5(err, "common request failed")));
|
|
6452
|
+
return;
|
|
6453
|
+
}
|
|
6454
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage5(err, "common request failed"))));
|
|
6455
|
+
}
|
|
6456
|
+
function createCommonService(options = {}) {
|
|
6457
|
+
return {
|
|
6458
|
+
descriptor: COMMON_DESCRIPTOR,
|
|
6459
|
+
handleMessage(windowId, message, send) {
|
|
6460
|
+
const id = message.id ?? "";
|
|
6461
|
+
const context = { windowId };
|
|
6462
|
+
if (message.type === "common.encodeNip19") {
|
|
6463
|
+
const input = message.input;
|
|
6464
|
+
const result = input ? encodeNip19(input) : { ok: false, error: "invalid input" };
|
|
6465
|
+
send({ type: "common.encodeNip19.result", id, ...result });
|
|
6466
|
+
return;
|
|
6467
|
+
}
|
|
6468
|
+
if (message.type === "common.decodeNip19") {
|
|
6469
|
+
const value = message.value;
|
|
6470
|
+
const result = typeof value === "string" ? decodeNip19Value(value) : { ok: false, error: "invalid value" };
|
|
6471
|
+
send({ type: "common.decodeNip19.result", id, ...result });
|
|
6472
|
+
return;
|
|
6473
|
+
}
|
|
6474
|
+
if (message.type === "common.getProfile") {
|
|
6475
|
+
const target = message.target;
|
|
6476
|
+
if (!options.getProfile) {
|
|
6477
|
+
send({ type: "common.getProfile.result", id, ok: false, pubkey: target ?? "", error: "profile lookup unavailable" });
|
|
6478
|
+
return;
|
|
6479
|
+
}
|
|
6480
|
+
settle5(
|
|
6481
|
+
() => options.getProfile(target, context),
|
|
6482
|
+
send,
|
|
6483
|
+
(error) => ({ type: "common.getProfile.result", id, ok: false, pubkey: target ?? "", error }),
|
|
6484
|
+
(result) => ({ type: "common.getProfile.result", id, ...result })
|
|
6485
|
+
);
|
|
6486
|
+
return;
|
|
6487
|
+
}
|
|
6488
|
+
if (message.type === "common.follows") {
|
|
6489
|
+
if (!options.follows) {
|
|
6490
|
+
send({ type: "common.follows.result", id, ok: false, pubkeys: [], error: "follows lookup unavailable" });
|
|
6491
|
+
return;
|
|
6492
|
+
}
|
|
6493
|
+
settle5(
|
|
6494
|
+
() => options.follows(context),
|
|
6495
|
+
send,
|
|
6496
|
+
(error) => ({ type: "common.follows.result", id, ok: false, pubkeys: [], error }),
|
|
6497
|
+
(result) => ({ type: "common.follows.result", id, ...result })
|
|
6498
|
+
);
|
|
6499
|
+
return;
|
|
6500
|
+
}
|
|
6501
|
+
if (message.type === "common.follow") {
|
|
6502
|
+
const pubkeys = message.pubkeys ?? [];
|
|
6503
|
+
settleAction(options.follow, pubkeys, context, send, "common.follow.result", id, "follow unavailable");
|
|
6504
|
+
return;
|
|
6505
|
+
}
|
|
6506
|
+
if (message.type === "common.unfollow") {
|
|
6507
|
+
const pubkeys = message.pubkeys ?? [];
|
|
6508
|
+
settleAction(options.unfollow, pubkeys, context, send, "common.unfollow.result", id, "unfollow unavailable");
|
|
6509
|
+
return;
|
|
6510
|
+
}
|
|
6511
|
+
if (message.type === "common.react") {
|
|
6512
|
+
const m = message;
|
|
6513
|
+
if (!options.react) {
|
|
6514
|
+
send({ type: "common.react.result", id, ok: false, error: "react unavailable" });
|
|
6515
|
+
return;
|
|
6516
|
+
}
|
|
6517
|
+
settle5(
|
|
6518
|
+
() => options.react(m.targetEventId, m.reaction, m.customEmojiHref, context),
|
|
6519
|
+
send,
|
|
6520
|
+
(error) => ({ type: "common.react.result", id, ok: false, error }),
|
|
6521
|
+
(result) => ({ type: "common.react.result", id, ...result })
|
|
6522
|
+
);
|
|
6523
|
+
return;
|
|
6524
|
+
}
|
|
6525
|
+
if (message.type === "common.report") {
|
|
6526
|
+
const m = message;
|
|
6527
|
+
if (!options.report) {
|
|
6528
|
+
send({ type: "common.report.result", id, ok: false, error: "report unavailable" });
|
|
6529
|
+
return;
|
|
6530
|
+
}
|
|
6531
|
+
settle5(
|
|
6532
|
+
() => options.report(m.target, m.reason, m.text, context),
|
|
6533
|
+
send,
|
|
6534
|
+
(error) => ({ type: "common.report.result", id, ok: false, error }),
|
|
6535
|
+
(result) => ({ type: "common.report.result", id, ...result })
|
|
6536
|
+
);
|
|
6537
|
+
return;
|
|
6538
|
+
}
|
|
6539
|
+
send({
|
|
6540
|
+
type: `${message.type}.error`,
|
|
6541
|
+
id,
|
|
6542
|
+
error: `Unknown common method: ${message.type}`
|
|
6543
|
+
});
|
|
6544
|
+
},
|
|
6545
|
+
onWindowDestroyed(_windowId) {
|
|
6546
|
+
}
|
|
6547
|
+
};
|
|
6548
|
+
}
|
|
6549
|
+
function settleAction(action, pubkeys, context, send, resultType, id, unavailable) {
|
|
6550
|
+
if (!action) {
|
|
6551
|
+
send({ type: resultType, id, ok: false, error: unavailable });
|
|
6552
|
+
return;
|
|
6553
|
+
}
|
|
6554
|
+
settle5(
|
|
6555
|
+
() => action(pubkeys, context),
|
|
6556
|
+
send,
|
|
6557
|
+
(error) => ({ type: resultType, id, ok: false, error }),
|
|
6558
|
+
(result) => ({ type: resultType, id, ...result })
|
|
6559
|
+
);
|
|
6560
|
+
}
|
|
5156
6561
|
|
|
5157
6562
|
// src/simulation.ts
|
|
5158
6563
|
function summarizePajaSimulation(simulation) {
|
|
@@ -5164,8 +6569,185 @@ function summarizePajaSimulation(simulation) {
|
|
|
5164
6569
|
return `${identity} ${relay} ${storage} ${theme} ${disabled}`;
|
|
5165
6570
|
}
|
|
5166
6571
|
|
|
6572
|
+
// src/development-services.ts
|
|
6573
|
+
var DEV_LISTS_EVENT_ID = "3".repeat(64);
|
|
6574
|
+
var DEV_SERIAL_LABEL = "Paja serial";
|
|
6575
|
+
var DEV_BLE_DEVICE_NAME = "Paja BLE";
|
|
6576
|
+
var DEV_BLE_SERVICE_UUID = "battery_service";
|
|
6577
|
+
var DEV_BLE_CHARACTERISTIC_UUID = "battery_level";
|
|
6578
|
+
var DEV_WEBRTC_PEER = "6".repeat(64);
|
|
6579
|
+
var DEV_LISTS_SUPPORT = {
|
|
6580
|
+
kind: 10003,
|
|
6581
|
+
type: "bookmarks",
|
|
6582
|
+
addressable: false,
|
|
6583
|
+
supportedItemTypes: ["event", "url"]
|
|
6584
|
+
};
|
|
6585
|
+
function destroyWindowSessions2(sessions, windowId) {
|
|
6586
|
+
for (const [sessionId, session] of sessions) {
|
|
6587
|
+
if (session.windowId === windowId) sessions.delete(sessionId);
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
function createDevListStore() {
|
|
6591
|
+
const values = /* @__PURE__ */ new Set();
|
|
6592
|
+
const itemKey = (item) => `${item.itemType}:${item.value}`;
|
|
6593
|
+
const isSupported = (list) => "type" in list && list.type === DEV_LISTS_SUPPORT.type || "kind" in list && list.kind === DEV_LISTS_SUPPORT.kind;
|
|
6594
|
+
return {
|
|
6595
|
+
supported: () => [DEV_LISTS_SUPPORT],
|
|
6596
|
+
add(list, items) {
|
|
6597
|
+
if (!isSupported(list)) return { ok: false, error: "unsupported-list", reason: "unsupported list", supported: [DEV_LISTS_SUPPORT] };
|
|
6598
|
+
let added = 0;
|
|
6599
|
+
let skipped = 0;
|
|
6600
|
+
for (const item of items) {
|
|
6601
|
+
const key = itemKey(item);
|
|
6602
|
+
if (values.has(key)) skipped += 1;
|
|
6603
|
+
else {
|
|
6604
|
+
values.add(key);
|
|
6605
|
+
added += 1;
|
|
6606
|
+
}
|
|
6607
|
+
}
|
|
6608
|
+
return { ok: true, eventId: DEV_LISTS_EVENT_ID, added, skipped };
|
|
6609
|
+
},
|
|
6610
|
+
remove(list, items) {
|
|
6611
|
+
if (!isSupported(list)) return { ok: false, error: "unsupported-list", reason: "unsupported list", supported: [DEV_LISTS_SUPPORT] };
|
|
6612
|
+
let removed = 0;
|
|
6613
|
+
let skipped = 0;
|
|
6614
|
+
for (const item of items) {
|
|
6615
|
+
if (values.delete(itemKey(item))) removed += 1;
|
|
6616
|
+
else skipped += 1;
|
|
6617
|
+
}
|
|
6618
|
+
return { ok: true, eventId: DEV_LISTS_EVENT_ID, removed, skipped };
|
|
6619
|
+
}
|
|
6620
|
+
};
|
|
6621
|
+
}
|
|
6622
|
+
function createDevSerialController() {
|
|
6623
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
6624
|
+
let nextSession = 1;
|
|
6625
|
+
return {
|
|
6626
|
+
open(_request, context) {
|
|
6627
|
+
const id = `paja-serial-${nextSession++}`;
|
|
6628
|
+
sessions.set(id, { windowId: context.windowId, writes: [] });
|
|
6629
|
+
return {
|
|
6630
|
+
session: {
|
|
6631
|
+
id,
|
|
6632
|
+
state: "open",
|
|
6633
|
+
info: { displayName: DEV_SERIAL_LABEL }
|
|
6634
|
+
}
|
|
6635
|
+
};
|
|
6636
|
+
},
|
|
6637
|
+
write(sessionId, data) {
|
|
6638
|
+
const session = sessions.get(sessionId);
|
|
6639
|
+
if (!session) throw new Error("serial session not found");
|
|
6640
|
+
session.writes.push([...data]);
|
|
6641
|
+
},
|
|
6642
|
+
close(sessionId) {
|
|
6643
|
+
if (!sessions.delete(sessionId)) throw new Error("serial session not found");
|
|
6644
|
+
},
|
|
6645
|
+
destroyWindow(windowId) {
|
|
6646
|
+
destroyWindowSessions2(sessions, windowId);
|
|
6647
|
+
}
|
|
6648
|
+
};
|
|
6649
|
+
}
|
|
6650
|
+
function createDevBleController() {
|
|
6651
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
6652
|
+
let nextSession = 1;
|
|
6653
|
+
const service = {
|
|
6654
|
+
uuid: DEV_BLE_SERVICE_UUID,
|
|
6655
|
+
characteristics: [{
|
|
6656
|
+
uuid: DEV_BLE_CHARACTERISTIC_UUID,
|
|
6657
|
+
properties: { read: true, write: true, notify: true }
|
|
6658
|
+
}]
|
|
6659
|
+
};
|
|
6660
|
+
const targetKey = (target) => `${String(target.service)}:${String(target.characteristic)}:${String(target.descriptor ?? "")}`;
|
|
6661
|
+
const getSession = (sessionId) => {
|
|
6662
|
+
const session = sessions.get(sessionId);
|
|
6663
|
+
if (!session) throw new Error("ble session not found");
|
|
6664
|
+
return session;
|
|
6665
|
+
};
|
|
6666
|
+
return {
|
|
6667
|
+
open(_request, context) {
|
|
6668
|
+
const id = `paja-ble-${nextSession++}`;
|
|
6669
|
+
sessions.set(id, { windowId: context.windowId, writes: [], subscriptions: /* @__PURE__ */ new Set() });
|
|
6670
|
+
return {
|
|
6671
|
+
session: {
|
|
6672
|
+
id,
|
|
6673
|
+
state: "open",
|
|
6674
|
+
device: {
|
|
6675
|
+
id: "paja-ble-device",
|
|
6676
|
+
name: DEV_BLE_DEVICE_NAME,
|
|
6677
|
+
services: [DEV_BLE_SERVICE_UUID]
|
|
6678
|
+
}
|
|
6679
|
+
}
|
|
6680
|
+
};
|
|
6681
|
+
},
|
|
6682
|
+
services(sessionId) {
|
|
6683
|
+
getSession(sessionId);
|
|
6684
|
+
return [service];
|
|
6685
|
+
},
|
|
6686
|
+
read(sessionId, _target) {
|
|
6687
|
+
getSession(sessionId);
|
|
6688
|
+
return [87];
|
|
6689
|
+
},
|
|
6690
|
+
write(sessionId, _target, data, _options) {
|
|
6691
|
+
getSession(sessionId).writes.push([...data]);
|
|
6692
|
+
},
|
|
6693
|
+
subscribe(sessionId, target) {
|
|
6694
|
+
getSession(sessionId).subscriptions.add(targetKey(target));
|
|
6695
|
+
},
|
|
6696
|
+
unsubscribe(sessionId, target) {
|
|
6697
|
+
getSession(sessionId).subscriptions.delete(targetKey(target));
|
|
6698
|
+
},
|
|
6699
|
+
close(sessionId) {
|
|
6700
|
+
if (!sessions.delete(sessionId)) throw new Error("ble session not found");
|
|
6701
|
+
},
|
|
6702
|
+
destroyWindow(windowId) {
|
|
6703
|
+
destroyWindowSessions2(sessions, windowId);
|
|
6704
|
+
}
|
|
6705
|
+
};
|
|
6706
|
+
}
|
|
6707
|
+
function createDevWebrtcController() {
|
|
6708
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
6709
|
+
let nextSession = 1;
|
|
6710
|
+
const getSession = (sessionId) => {
|
|
6711
|
+
const session = sessions.get(sessionId);
|
|
6712
|
+
if (!session) throw new Error("webrtc session not found");
|
|
6713
|
+
return session;
|
|
6714
|
+
};
|
|
6715
|
+
return {
|
|
6716
|
+
open(request, context) {
|
|
6717
|
+
const id = `paja-webrtc-${nextSession++}`;
|
|
6718
|
+
const channel = request.channel ?? "default";
|
|
6719
|
+
sessions.set(id, { windowId: context.windowId, payloads: [] });
|
|
6720
|
+
context.emit({ type: "state", sessionId: id, state: "open" });
|
|
6721
|
+
context.emit({ type: "peer", sessionId: id, pubkey: DEV_WEBRTC_PEER, state: "joined" });
|
|
6722
|
+
return {
|
|
6723
|
+
session: {
|
|
6724
|
+
id,
|
|
6725
|
+
scope: request.scope,
|
|
6726
|
+
channel,
|
|
6727
|
+
...request.protocol ? { protocol: request.protocol } : {},
|
|
6728
|
+
state: "open"
|
|
6729
|
+
}
|
|
6730
|
+
};
|
|
6731
|
+
},
|
|
6732
|
+
send(sessionId, payload, context) {
|
|
6733
|
+
getSession(sessionId).payloads.push(payload);
|
|
6734
|
+
context.emit({ type: "message", sessionId, from: DEV_WEBRTC_PEER, payload });
|
|
6735
|
+
},
|
|
6736
|
+
close(sessionId, reason, context) {
|
|
6737
|
+
getSession(sessionId);
|
|
6738
|
+
sessions.delete(sessionId);
|
|
6739
|
+
context.emit({ type: "closed", sessionId, ...reason ? { reason } : {} });
|
|
6740
|
+
},
|
|
6741
|
+
destroyWindow(windowId) {
|
|
6742
|
+
destroyWindowSessions2(sessions, windowId);
|
|
6743
|
+
}
|
|
6744
|
+
};
|
|
6745
|
+
}
|
|
6746
|
+
|
|
5167
6747
|
// src/browser-host.ts
|
|
5168
6748
|
var DEV_INTENT_ARCHETYPE = "paja-target";
|
|
6749
|
+
var DEV_COMMON_PUBKEY = "1".repeat(64);
|
|
6750
|
+
var DEV_COMMON_EVENT_ID = "2".repeat(64);
|
|
5169
6751
|
var DEV_CVM_SERVER = {
|
|
5170
6752
|
pubkey: "0".repeat(64),
|
|
5171
6753
|
name: "Kehto Paja ContextVM",
|
|
@@ -5518,6 +7100,43 @@ function createDevServices(pool, getSimulation, onThemeService) {
|
|
|
5518
7100
|
}
|
|
5519
7101
|
});
|
|
5520
7102
|
}
|
|
7103
|
+
if (getSimulation().capabilities.domains.link) {
|
|
7104
|
+
services.link = createLinkService({
|
|
7105
|
+
open: ({ url }) => ({ status: url.protocol === "https:" || url.protocol === "http:" ? "opened" : "denied" })
|
|
7106
|
+
});
|
|
7107
|
+
}
|
|
7108
|
+
if (getSimulation().capabilities.domains.common) {
|
|
7109
|
+
services.common = createCommonService({
|
|
7110
|
+
getProfile: (target) => ({
|
|
7111
|
+
ok: true,
|
|
7112
|
+
pubkey: target || getSimulation().identity.pubkey || DEV_COMMON_PUBKEY,
|
|
7113
|
+
profile: { name: "paja", displayName: "Kehto Paja" },
|
|
7114
|
+
relays: getRelayUrls(getSimulation())
|
|
7115
|
+
}),
|
|
7116
|
+
follows: () => ({ ok: true, pubkeys: [getSimulation().identity.pubkey || DEV_COMMON_PUBKEY] }),
|
|
7117
|
+
follow: () => ({ ok: true, eventId: DEV_COMMON_EVENT_ID }),
|
|
7118
|
+
unfollow: () => ({ ok: true, eventId: DEV_COMMON_EVENT_ID }),
|
|
7119
|
+
react: () => ({ ok: true, eventId: DEV_COMMON_EVENT_ID }),
|
|
7120
|
+
report: () => ({ ok: true, eventId: DEV_COMMON_EVENT_ID })
|
|
7121
|
+
});
|
|
7122
|
+
}
|
|
7123
|
+
if (getSimulation().capabilities.domains.lists) {
|
|
7124
|
+
const listStore = createDevListStore();
|
|
7125
|
+
services.lists = createListsService({
|
|
7126
|
+
supported: listStore.supported,
|
|
7127
|
+
add: listStore.add,
|
|
7128
|
+
remove: listStore.remove
|
|
7129
|
+
});
|
|
7130
|
+
}
|
|
7131
|
+
if (getSimulation().capabilities.domains.serial) {
|
|
7132
|
+
services.serial = createSerialService(createDevSerialController());
|
|
7133
|
+
}
|
|
7134
|
+
if (getSimulation().capabilities.domains.ble) {
|
|
7135
|
+
services.ble = createBleService(createDevBleController());
|
|
7136
|
+
}
|
|
7137
|
+
if (getSimulation().capabilities.domains.webrtc) {
|
|
7138
|
+
services.webrtc = createWebrtcService(createDevWebrtcController());
|
|
7139
|
+
}
|
|
5521
7140
|
return services;
|
|
5522
7141
|
}
|
|
5523
7142
|
function createPajaAdapter(config, getSimulation, onThemeService) {
|
|
@@ -5549,6 +7168,12 @@ function createPajaAdapter(config, getSimulation, onThemeService) {
|
|
|
5549
7168
|
workerRelay: { getWorkerRelay: () => createWorkerRelay(workerRelayEvents) },
|
|
5550
7169
|
upload: getSimulation().upload.mode === "memory" ? { getUploader: () => ({ rails: [getSimulation().upload.rail] }) } : void 0,
|
|
5551
7170
|
intent: { isAvailable: () => getSimulation().intent.enabled },
|
|
7171
|
+
link: { isAvailable: () => getSimulation().capabilities.domains.link },
|
|
7172
|
+
common: { isAvailable: () => getSimulation().capabilities.domains.common },
|
|
7173
|
+
lists: { isAvailable: () => getSimulation().capabilities.domains.lists },
|
|
7174
|
+
serial: { isAvailable: () => getSimulation().capabilities.domains.serial },
|
|
7175
|
+
ble: { isAvailable: () => getSimulation().capabilities.domains.ble },
|
|
7176
|
+
webrtc: { isAvailable: () => getSimulation().capabilities.domains.webrtc },
|
|
5552
7177
|
crypto: {
|
|
5553
7178
|
verifyEvent: async () => true
|
|
5554
7179
|
},
|
|
@@ -5570,11 +7195,7 @@ function registerFrameForGeneration(bridge, frame, config, generation) {
|
|
|
5570
7195
|
}
|
|
5571
7196
|
function navigateFrame(bridge, frame, config, generation) {
|
|
5572
7197
|
const windowId = registerFrameForGeneration(bridge, frame, config, generation);
|
|
5573
|
-
frame.src =
|
|
5574
|
-
window.setTimeout(() => {
|
|
5575
|
-
registerFrameForGeneration(bridge, frame, config, generation);
|
|
5576
|
-
frame.src = config.target.url;
|
|
5577
|
-
}, 0);
|
|
7198
|
+
frame.src = config.target.url;
|
|
5578
7199
|
return windowId;
|
|
5579
7200
|
}
|
|
5580
7201
|
function installPajaHost() {
|
|
@@ -5671,4 +7292,12 @@ try {
|
|
|
5671
7292
|
if (statusEl) statusEl.textContent = "error";
|
|
5672
7293
|
console.error(error);
|
|
5673
7294
|
}
|
|
7295
|
+
/*! Bundled license information:
|
|
7296
|
+
|
|
7297
|
+
@noble/hashes/utils.js:
|
|
7298
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
7299
|
+
|
|
7300
|
+
@scure/base/index.js:
|
|
7301
|
+
(*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
7302
|
+
*/
|
|
5674
7303
|
//# sourceMappingURL=browser-host.js.map
|