@kehto/shell 0.16.4 → 0.16.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +20 -35
- package/dist/index.js +761 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1025,7 +1025,6 @@ function buildShellCapabilities(hooks) {
|
|
|
1025
1025
|
if (hooks.webrtc?.isAvailable()) domains.push("webrtc");
|
|
1026
1026
|
if (hooks.dm) domains.push("dm");
|
|
1027
1027
|
const sandbox = [];
|
|
1028
|
-
domains.push(...sandbox);
|
|
1029
1028
|
const protocols = {};
|
|
1030
1029
|
for (const entry of NAP_INC_PROTOCOLS) {
|
|
1031
1030
|
const [domain, protocol] = entry.split(":");
|
|
@@ -1275,18 +1274,777 @@ function injectNappletNamespacePrelude(html, options) {
|
|
|
1275
1274
|
}
|
|
1276
1275
|
function nappletNamespacePrelude(domains) {
|
|
1277
1276
|
const target = window;
|
|
1277
|
+
const allowed = new Set(domains);
|
|
1278
|
+
const requestTimeoutMs = 3e4;
|
|
1279
|
+
function id() {
|
|
1280
|
+
if (target.crypto?.randomUUID) return target.crypto.randomUUID();
|
|
1281
|
+
return `napplet-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
1282
|
+
}
|
|
1283
|
+
function post(message) {
|
|
1284
|
+
target.parent.postMessage(message, "*");
|
|
1285
|
+
}
|
|
1286
|
+
function listen(listener) {
|
|
1287
|
+
target.addEventListener("message", listener);
|
|
1288
|
+
return () => target.removeEventListener("message", listener);
|
|
1289
|
+
}
|
|
1290
|
+
function isParentMessage(event) {
|
|
1291
|
+
return event.source === target.parent;
|
|
1292
|
+
}
|
|
1293
|
+
function request(message, resultType, map, options = {}) {
|
|
1294
|
+
const requestId = message.id ?? id();
|
|
1295
|
+
const outbound = { ...message, id: requestId };
|
|
1296
|
+
return new Promise((resolve, reject) => {
|
|
1297
|
+
const off = listen((event) => {
|
|
1298
|
+
if (!isParentMessage(event)) return;
|
|
1299
|
+
const incoming = event.data;
|
|
1300
|
+
if (typeof incoming !== "object" || incoming === null) return;
|
|
1301
|
+
const msg = incoming;
|
|
1302
|
+
if (msg.type !== resultType && msg.type !== `${message.type}.error`) return;
|
|
1303
|
+
if (msg.id !== requestId) return;
|
|
1304
|
+
off();
|
|
1305
|
+
clearTimeout(timer);
|
|
1306
|
+
const error = typeof msg.error === "string" ? msg.error : "";
|
|
1307
|
+
if (error && options.rejectOnError !== false) {
|
|
1308
|
+
reject(new Error(error));
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
try {
|
|
1312
|
+
resolve(map(msg));
|
|
1313
|
+
} catch (err) {
|
|
1314
|
+
reject(err);
|
|
1315
|
+
}
|
|
1316
|
+
});
|
|
1317
|
+
const timer = setTimeout(() => {
|
|
1318
|
+
off();
|
|
1319
|
+
reject(new Error(`${message.type} timed out`));
|
|
1320
|
+
}, requestTimeoutMs);
|
|
1321
|
+
post(outbound);
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
function fire(message) {
|
|
1325
|
+
post(message);
|
|
1326
|
+
}
|
|
1327
|
+
function resultOrError(msg) {
|
|
1328
|
+
return msg;
|
|
1329
|
+
}
|
|
1330
|
+
function withoutEnvelope(msg) {
|
|
1331
|
+
const { type: _type, id: _id, ...result } = msg;
|
|
1332
|
+
return result;
|
|
1333
|
+
}
|
|
1334
|
+
function fieldOrThrow(msg, field, fallback) {
|
|
1335
|
+
if (Object.prototype.hasOwnProperty.call(msg, field)) return msg[field];
|
|
1336
|
+
throw new Error(typeof msg.error === "string" ? msg.error : fallback);
|
|
1337
|
+
}
|
|
1338
|
+
function voidResult(msg, fallback) {
|
|
1339
|
+
if (typeof msg.error === "string" && msg.error) throw new Error(msg.error);
|
|
1340
|
+
if (msg.ok === false) throw new Error(fallback);
|
|
1341
|
+
}
|
|
1342
|
+
function subscriptionHandle(close) {
|
|
1343
|
+
let closed = false;
|
|
1344
|
+
return {
|
|
1345
|
+
close() {
|
|
1346
|
+
if (closed) return;
|
|
1347
|
+
closed = true;
|
|
1348
|
+
close();
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
function domainEventHandle(eventType, callback, select = (message) => message.event) {
|
|
1353
|
+
const off = listen((event) => {
|
|
1354
|
+
if (!isParentMessage(event)) return;
|
|
1355
|
+
const msg = event.data;
|
|
1356
|
+
if (typeof msg === "object" && msg !== null && msg.type === eventType) callback(select(msg));
|
|
1357
|
+
});
|
|
1358
|
+
return subscriptionHandle(off);
|
|
1359
|
+
}
|
|
1360
|
+
function makeRelay() {
|
|
1361
|
+
return {
|
|
1362
|
+
subscribe(filters, onEvent, onEose, options) {
|
|
1363
|
+
const subId = id();
|
|
1364
|
+
const off = listen((event) => {
|
|
1365
|
+
if (!isParentMessage(event)) return;
|
|
1366
|
+
const msg = event.data;
|
|
1367
|
+
if (typeof msg !== "object" || msg === null || msg.subId !== subId) return;
|
|
1368
|
+
if (msg.type === "relay.event") onEvent(msg.result);
|
|
1369
|
+
else if (msg.type === "relay.eose") onEose();
|
|
1370
|
+
else if (msg.type === "relay.closed") off();
|
|
1371
|
+
});
|
|
1372
|
+
fire({
|
|
1373
|
+
type: "relay.subscribe",
|
|
1374
|
+
id: id(),
|
|
1375
|
+
subId,
|
|
1376
|
+
filters: Array.isArray(filters) ? filters : [filters],
|
|
1377
|
+
...options?.relay ? { relay: options.relay } : {}
|
|
1378
|
+
});
|
|
1379
|
+
return subscriptionHandle(() => {
|
|
1380
|
+
fire({ type: "relay.close", id: id(), subId });
|
|
1381
|
+
off();
|
|
1382
|
+
});
|
|
1383
|
+
},
|
|
1384
|
+
publish(template) {
|
|
1385
|
+
return request(
|
|
1386
|
+
{ type: "relay.publish", event: template },
|
|
1387
|
+
"relay.publish.result",
|
|
1388
|
+
(msg) => {
|
|
1389
|
+
if (!msg.event) throw new Error("relay.publish.result missing event");
|
|
1390
|
+
return msg.event;
|
|
1391
|
+
}
|
|
1392
|
+
);
|
|
1393
|
+
},
|
|
1394
|
+
publishEncrypted(template, recipient, encryption = "nip44") {
|
|
1395
|
+
return request(
|
|
1396
|
+
{ type: "relay.publishEncrypted", event: template, recipient, encryption },
|
|
1397
|
+
"relay.publishEncrypted.result",
|
|
1398
|
+
(msg) => {
|
|
1399
|
+
if (!msg.event) throw new Error("relay.publishEncrypted.result missing event");
|
|
1400
|
+
return msg.event;
|
|
1401
|
+
}
|
|
1402
|
+
);
|
|
1403
|
+
},
|
|
1404
|
+
query(filters) {
|
|
1405
|
+
return request(
|
|
1406
|
+
{ type: "relay.query", filters: Array.isArray(filters) ? filters : [filters] },
|
|
1407
|
+
"relay.query.result",
|
|
1408
|
+
(msg) => Array.isArray(msg.events) ? msg.events : []
|
|
1409
|
+
);
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
function makeInc() {
|
|
1414
|
+
return {
|
|
1415
|
+
emit(topic, _extraTags, content) {
|
|
1416
|
+
let payload = content;
|
|
1417
|
+
if (typeof content === "string" && content.length > 0) {
|
|
1418
|
+
try {
|
|
1419
|
+
payload = JSON.parse(content);
|
|
1420
|
+
} catch {
|
|
1421
|
+
payload = content;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
fire({ type: "inc.emit", topic, ...payload === void 0 || payload === "" ? {} : { payload } });
|
|
1425
|
+
},
|
|
1426
|
+
on(topic, callback) {
|
|
1427
|
+
const off = listen((event) => {
|
|
1428
|
+
if (!isParentMessage(event)) return;
|
|
1429
|
+
const msg = event.data;
|
|
1430
|
+
if (typeof msg !== "object" || msg === null || msg.type !== "inc.event" || msg.topic !== topic) return;
|
|
1431
|
+
callback(msg.payload ?? {}, {
|
|
1432
|
+
id: "",
|
|
1433
|
+
pubkey: typeof msg.sender === "string" ? msg.sender : "",
|
|
1434
|
+
created_at: Math.floor(Date.now() / 1e3),
|
|
1435
|
+
kind: 0,
|
|
1436
|
+
tags: [["t", topic]],
|
|
1437
|
+
content: typeof msg.payload === "string" ? msg.payload : JSON.stringify(msg.payload ?? {}),
|
|
1438
|
+
sig: ""
|
|
1439
|
+
});
|
|
1440
|
+
});
|
|
1441
|
+
fire({ type: "inc.subscribe", id: id(), topic });
|
|
1442
|
+
return subscriptionHandle(() => {
|
|
1443
|
+
fire({ type: "inc.unsubscribe", topic });
|
|
1444
|
+
off();
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
};
|
|
1448
|
+
}
|
|
1449
|
+
function makeStorage() {
|
|
1450
|
+
const makeScope = (scope) => ({
|
|
1451
|
+
getItem(key) {
|
|
1452
|
+
return request(
|
|
1453
|
+
{ type: "storage.get", key, ...scope ? { scope } : {} },
|
|
1454
|
+
"storage.get.result",
|
|
1455
|
+
(msg) => msg.value ?? null
|
|
1456
|
+
);
|
|
1457
|
+
},
|
|
1458
|
+
setItem(key, value) {
|
|
1459
|
+
return request(
|
|
1460
|
+
{ type: "storage.set", key, value, ...scope ? { scope } : {} },
|
|
1461
|
+
"storage.set.result",
|
|
1462
|
+
() => void 0
|
|
1463
|
+
);
|
|
1464
|
+
},
|
|
1465
|
+
removeItem(key) {
|
|
1466
|
+
return request(
|
|
1467
|
+
{ type: "storage.remove", key, ...scope ? { scope } : {} },
|
|
1468
|
+
"storage.remove.result",
|
|
1469
|
+
() => void 0
|
|
1470
|
+
);
|
|
1471
|
+
},
|
|
1472
|
+
keys() {
|
|
1473
|
+
return request(
|
|
1474
|
+
{ type: "storage.keys", ...scope ? { scope } : {} },
|
|
1475
|
+
"storage.keys.result",
|
|
1476
|
+
(msg) => Array.isArray(msg.keys) ? msg.keys : []
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
return { ...makeScope(), instance: makeScope("instance") };
|
|
1481
|
+
}
|
|
1482
|
+
function makeIdentity() {
|
|
1483
|
+
const read = (type, field, fallback) => request(
|
|
1484
|
+
{ type },
|
|
1485
|
+
`${type}.result`,
|
|
1486
|
+
(msg) => Object.prototype.hasOwnProperty.call(msg, field) ? msg[field] : fallback,
|
|
1487
|
+
{ rejectOnError: type !== "identity.getPublicKey" }
|
|
1488
|
+
);
|
|
1489
|
+
return {
|
|
1490
|
+
getPublicKey: () => read("identity.getPublicKey", "pubkey", ""),
|
|
1491
|
+
onChanged(handler) {
|
|
1492
|
+
const off = listen((event) => {
|
|
1493
|
+
if (!isParentMessage(event)) return;
|
|
1494
|
+
const msg = event.data;
|
|
1495
|
+
if (typeof msg !== "object" || msg === null || msg.type !== "identity.changed") return;
|
|
1496
|
+
if (typeof msg.pubkey === "string") handler(msg.pubkey);
|
|
1497
|
+
});
|
|
1498
|
+
return subscriptionHandle(off);
|
|
1499
|
+
},
|
|
1500
|
+
getRelays: () => read("identity.getRelays", "relays", {}),
|
|
1501
|
+
getProfile: () => read("identity.getProfile", "profile", null),
|
|
1502
|
+
getFollows: () => read("identity.getFollows", "pubkeys", []),
|
|
1503
|
+
getList: (listType) => request(
|
|
1504
|
+
{ type: "identity.getList", listType },
|
|
1505
|
+
"identity.getList.result",
|
|
1506
|
+
(msg) => Array.isArray(msg.entries) ? msg.entries : []
|
|
1507
|
+
),
|
|
1508
|
+
getZaps: () => read("identity.getZaps", "zaps", []),
|
|
1509
|
+
getMutes: () => read("identity.getMutes", "pubkeys", []),
|
|
1510
|
+
getBlocked: () => read("identity.getBlocked", "pubkeys", []),
|
|
1511
|
+
getBadges: () => read("identity.getBadges", "badges", [])
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
function makeTheme() {
|
|
1515
|
+
return {
|
|
1516
|
+
get: () => request({ type: "theme.get" }, "theme.get.result", (msg) => msg.theme),
|
|
1517
|
+
onChanged(handler) {
|
|
1518
|
+
const off = listen((event) => {
|
|
1519
|
+
if (!isParentMessage(event)) return;
|
|
1520
|
+
const msg = event.data;
|
|
1521
|
+
if (typeof msg === "object" && msg !== null && msg.type === "theme.changed") handler(msg.theme);
|
|
1522
|
+
});
|
|
1523
|
+
return subscriptionHandle(off);
|
|
1524
|
+
}
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
function makeKeys() {
|
|
1528
|
+
return {
|
|
1529
|
+
forward: (event = {}) => fire({
|
|
1530
|
+
type: "keys.forward",
|
|
1531
|
+
key: typeof event.key === "string" ? event.key : "",
|
|
1532
|
+
code: typeof event.code === "string" ? event.code : "",
|
|
1533
|
+
ctrl: Boolean(event.ctrl ?? event.ctrlKey),
|
|
1534
|
+
alt: Boolean(event.alt ?? event.altKey),
|
|
1535
|
+
shift: Boolean(event.shift ?? event.shiftKey),
|
|
1536
|
+
meta: Boolean(event.meta ?? event.metaKey)
|
|
1537
|
+
}),
|
|
1538
|
+
registerAction: (action) => request(
|
|
1539
|
+
{ type: "keys.registerAction", action },
|
|
1540
|
+
"keys.registerAction.result",
|
|
1541
|
+
resultOrError
|
|
1542
|
+
),
|
|
1543
|
+
unregisterAction: (actionId) => fire({ type: "keys.unregisterAction", actionId }),
|
|
1544
|
+
onAction(actionId, callback) {
|
|
1545
|
+
const off = listen((event) => {
|
|
1546
|
+
if (!isParentMessage(event)) return;
|
|
1547
|
+
const msg = event.data;
|
|
1548
|
+
if (typeof msg === "object" && msg !== null && msg.type === "keys.action" && msg.actionId === actionId) callback();
|
|
1549
|
+
});
|
|
1550
|
+
return subscriptionHandle(off);
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
function makeMedia() {
|
|
1555
|
+
const on = (type, sessionId, callback) => {
|
|
1556
|
+
const off = listen((event) => {
|
|
1557
|
+
if (!isParentMessage(event)) return;
|
|
1558
|
+
const msg = event.data;
|
|
1559
|
+
if (typeof msg === "object" && msg !== null && msg.type === type && msg.sessionId === sessionId) callback(msg);
|
|
1560
|
+
});
|
|
1561
|
+
return subscriptionHandle(off);
|
|
1562
|
+
};
|
|
1563
|
+
return {
|
|
1564
|
+
createSession: (options) => request(
|
|
1565
|
+
{ type: "media.session.create", ...options && typeof options === "object" ? options : {} },
|
|
1566
|
+
"media.session.create.result",
|
|
1567
|
+
withoutEnvelope,
|
|
1568
|
+
{ rejectOnError: false }
|
|
1569
|
+
),
|
|
1570
|
+
updateSession: (sessionId, metadata) => fire({ type: "media.session.update", sessionId, metadata }),
|
|
1571
|
+
destroySession: (sessionId) => fire({ type: "media.session.destroy", sessionId }),
|
|
1572
|
+
reportState: (sessionId, state) => fire({ type: "media.state", sessionId, ...state && typeof state === "object" ? state : {} }),
|
|
1573
|
+
reportCapabilities: (sessionId, actions) => fire({ type: "media.capabilities", sessionId, actions }),
|
|
1574
|
+
sendCommand: (sessionId, action, value) => fire({ type: "media.command", sessionId, action, ...value === void 0 ? {} : { value } }),
|
|
1575
|
+
onCommand: (sessionId, callback) => on("media.command", sessionId, (msg) => callback(msg.action, msg.value)),
|
|
1576
|
+
onState: (sessionId, callback) => on("media.state", sessionId, (msg) => callback({
|
|
1577
|
+
status: msg.status,
|
|
1578
|
+
position: msg.position,
|
|
1579
|
+
duration: msg.duration,
|
|
1580
|
+
volume: msg.volume
|
|
1581
|
+
})),
|
|
1582
|
+
onCapabilities: (sessionId, callback) => on("media.capabilities", sessionId, (msg) => callback(msg.actions)),
|
|
1583
|
+
onControls: (sessionId, callback) => on("media.controls", sessionId, (msg) => callback(msg.controls))
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
function makeNotify() {
|
|
1587
|
+
const on = (type, callback) => {
|
|
1588
|
+
const off = listen((event) => {
|
|
1589
|
+
if (!isParentMessage(event)) return;
|
|
1590
|
+
const msg = event.data;
|
|
1591
|
+
if (typeof msg === "object" && msg !== null && msg.type === type) callback(msg);
|
|
1592
|
+
});
|
|
1593
|
+
return subscriptionHandle(off);
|
|
1594
|
+
};
|
|
1595
|
+
return {
|
|
1596
|
+
send: (notification) => request(
|
|
1597
|
+
{ type: "notify.send", ...notification },
|
|
1598
|
+
"notify.send.result",
|
|
1599
|
+
(msg) => ({ notificationId: fieldOrThrow(msg, "notificationId", "notify.send.result missing notificationId") })
|
|
1600
|
+
),
|
|
1601
|
+
dismiss: (notificationId) => fire({ type: "notify.dismiss", notificationId }),
|
|
1602
|
+
badge: (count) => fire({ type: "notify.badge", count }),
|
|
1603
|
+
registerChannel: (channel) => fire({ type: "notify.channel.register", ...channel }),
|
|
1604
|
+
requestPermission: (channel) => request(
|
|
1605
|
+
{ type: "notify.permission.request", ...channel ? { channel } : {} },
|
|
1606
|
+
"notify.permission.result",
|
|
1607
|
+
(msg) => ({ granted: msg.granted })
|
|
1608
|
+
),
|
|
1609
|
+
onAction: (callback) => on("notify.action", (msg) => callback(msg.notificationId, msg.actionId)),
|
|
1610
|
+
onClicked: (callback) => on("notify.clicked", (msg) => callback(msg.notificationId)),
|
|
1611
|
+
onDismissed: (callback) => on("notify.dismissed", (msg) => callback(msg.notificationId, msg.reason)),
|
|
1612
|
+
onControls: (callback) => on("notify.controls", (msg) => callback(msg.controls))
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
function makeConfig() {
|
|
1616
|
+
let schema = null;
|
|
1617
|
+
return {
|
|
1618
|
+
registerSchema: (nextSchema, version2) => request(
|
|
1619
|
+
{ type: "config.registerSchema", schema: nextSchema, ...version2 === void 0 ? {} : { version: version2 } },
|
|
1620
|
+
"config.registerSchema.result",
|
|
1621
|
+
(msg) => {
|
|
1622
|
+
if (!msg.error) schema = nextSchema;
|
|
1623
|
+
return void 0;
|
|
1624
|
+
}
|
|
1625
|
+
),
|
|
1626
|
+
get: () => request({ type: "config.get" }, "config.values", (msg) => msg.values ?? {}),
|
|
1627
|
+
subscribe(callback) {
|
|
1628
|
+
const off = listen((event) => {
|
|
1629
|
+
if (!isParentMessage(event)) return;
|
|
1630
|
+
const msg = event.data;
|
|
1631
|
+
if (typeof msg === "object" && msg !== null && msg.type === "config.values") callback(msg.values ?? {});
|
|
1632
|
+
});
|
|
1633
|
+
fire({ type: "config.subscribe" });
|
|
1634
|
+
return subscriptionHandle(() => {
|
|
1635
|
+
fire({ type: "config.unsubscribe" });
|
|
1636
|
+
off();
|
|
1637
|
+
});
|
|
1638
|
+
},
|
|
1639
|
+
openSettings: (options) => fire({ type: "config.openSettings", ...options && typeof options === "object" ? options : {} }),
|
|
1640
|
+
onSchemaError(callback) {
|
|
1641
|
+
const off = listen((event) => {
|
|
1642
|
+
if (!isParentMessage(event)) return;
|
|
1643
|
+
const msg = event.data;
|
|
1644
|
+
if (typeof msg === "object" && msg !== null && msg.type === "config.schemaError") callback(msg);
|
|
1645
|
+
});
|
|
1646
|
+
return off;
|
|
1647
|
+
},
|
|
1648
|
+
get schema() {
|
|
1649
|
+
return schema;
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function makeResource() {
|
|
1654
|
+
const objectUrls = /* @__PURE__ */ new Set();
|
|
1655
|
+
const bytes = (url) => request({ type: "resource.bytes", url }, "resource.bytes.result", (msg) => msg.blob);
|
|
1656
|
+
return {
|
|
1657
|
+
info: () => request({ type: "resource.info" }, "resource.info.result", (msg) => msg.info),
|
|
1658
|
+
bytes,
|
|
1659
|
+
bytesMany: (urls) => request({ type: "resource.bytesMany", urls }, "resource.bytesMany.result", (msg) => Array.isArray(msg.items) ? msg.items : []),
|
|
1660
|
+
bytesAsObjectURL(url) {
|
|
1661
|
+
let objectUrl = "";
|
|
1662
|
+
const handle = {
|
|
1663
|
+
get url() {
|
|
1664
|
+
return objectUrl;
|
|
1665
|
+
},
|
|
1666
|
+
revoke() {
|
|
1667
|
+
if (objectUrl) {
|
|
1668
|
+
URL.revokeObjectURL(objectUrl);
|
|
1669
|
+
objectUrls.delete(objectUrl);
|
|
1670
|
+
objectUrl = "";
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
};
|
|
1674
|
+
void bytes(url).then((blob) => {
|
|
1675
|
+
objectUrl = URL.createObjectURL(blob);
|
|
1676
|
+
objectUrls.add(objectUrl);
|
|
1677
|
+
});
|
|
1678
|
+
return handle;
|
|
1679
|
+
},
|
|
1680
|
+
hydrateResourceCache: () => void 0,
|
|
1681
|
+
revokeAllObjectURLs() {
|
|
1682
|
+
for (const url of objectUrls) URL.revokeObjectURL(url);
|
|
1683
|
+
objectUrls.clear();
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
function makeCvm() {
|
|
1688
|
+
const req = (type, payload, map) => request(
|
|
1689
|
+
{ type, ...payload },
|
|
1690
|
+
`${type}.result`,
|
|
1691
|
+
map
|
|
1692
|
+
);
|
|
1693
|
+
const cvmRequest = (server, message, options) => req(
|
|
1694
|
+
"cvm.request",
|
|
1695
|
+
{ server, message, ...options === void 0 ? {} : { options } },
|
|
1696
|
+
(msg) => fieldOrThrow(msg, "message", "cvm.request.result missing message")
|
|
1697
|
+
);
|
|
1698
|
+
const mcpCall = async (server, method, params, options) => {
|
|
1699
|
+
const reply = await cvmRequest(server, {
|
|
1700
|
+
jsonrpc: "2.0",
|
|
1701
|
+
id: id(),
|
|
1702
|
+
method,
|
|
1703
|
+
...params === void 0 ? {} : { params }
|
|
1704
|
+
}, options);
|
|
1705
|
+
if (reply.error !== void 0) {
|
|
1706
|
+
const error = reply.error;
|
|
1707
|
+
throw new Error(typeof error === "object" && error !== null && typeof error.message === "string" ? `${method}: ${error.message}` : `${method} failed`);
|
|
1708
|
+
}
|
|
1709
|
+
return reply.result;
|
|
1710
|
+
};
|
|
1711
|
+
return {
|
|
1712
|
+
discover: (query) => req("cvm.discover", query === void 0 ? {} : { query }, (msg) => Array.isArray(msg.servers) ? msg.servers : []),
|
|
1713
|
+
request: cvmRequest,
|
|
1714
|
+
listTools: async (server, options) => {
|
|
1715
|
+
const result = await mcpCall(server, "tools/list", void 0, options);
|
|
1716
|
+
return result?.tools ?? [];
|
|
1717
|
+
},
|
|
1718
|
+
callTool: (server, name, args, options) => mcpCall(
|
|
1719
|
+
server,
|
|
1720
|
+
"tools/call",
|
|
1721
|
+
{ name, ...args === void 0 ? {} : { arguments: args } },
|
|
1722
|
+
options
|
|
1723
|
+
),
|
|
1724
|
+
listResources: async (server, options) => {
|
|
1725
|
+
const result = await mcpCall(server, "resources/list", void 0, options);
|
|
1726
|
+
return result?.resources ?? [];
|
|
1727
|
+
},
|
|
1728
|
+
readResource: async (server, uri, options) => {
|
|
1729
|
+
const result = await mcpCall(server, "resources/read", { uri }, options);
|
|
1730
|
+
const first = result?.contents?.[0];
|
|
1731
|
+
if (!first) throw new Error(`resources/read returned no contents for ${uri}`);
|
|
1732
|
+
return first;
|
|
1733
|
+
},
|
|
1734
|
+
close: (server) => req("cvm.close", { server }, (msg) => voidResult(msg, "cvm close failed")),
|
|
1735
|
+
onEvent(callback) {
|
|
1736
|
+
const off = listen((event) => {
|
|
1737
|
+
if (!isParentMessage(event)) return;
|
|
1738
|
+
const msg = event.data;
|
|
1739
|
+
if (typeof msg === "object" && msg !== null && msg.type === "cvm.event" && msg.server !== void 0 && msg.message !== void 0) {
|
|
1740
|
+
callback(msg.server, msg.message);
|
|
1741
|
+
}
|
|
1742
|
+
});
|
|
1743
|
+
return subscriptionHandle(off);
|
|
1744
|
+
}
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
function makeOutbox() {
|
|
1748
|
+
const req = (type, payload, resultType = `${type}.result`) => request(
|
|
1749
|
+
{ type, ...payload },
|
|
1750
|
+
resultType,
|
|
1751
|
+
resultOrError,
|
|
1752
|
+
{ rejectOnError: false }
|
|
1753
|
+
);
|
|
1754
|
+
return {
|
|
1755
|
+
getEvent: (eventId, options) => req("outbox.getEvent", { eventId, ...options ? { options } : {} }),
|
|
1756
|
+
query: (filters, options) => req("outbox.query", { filters: Array.isArray(filters) ? filters : [filters], ...options ? { options } : {} }),
|
|
1757
|
+
subscribe(filters, options) {
|
|
1758
|
+
const subId = id();
|
|
1759
|
+
const handlers = { event: /* @__PURE__ */ new Set(), closed: /* @__PURE__ */ new Set() };
|
|
1760
|
+
const off = listen((event) => {
|
|
1761
|
+
if (!isParentMessage(event)) return;
|
|
1762
|
+
const msg = event.data;
|
|
1763
|
+
if (typeof msg !== "object" || msg === null || msg.subId !== subId) return;
|
|
1764
|
+
if (msg.type === "outbox.event") for (const handler of handlers.event) handler(msg.result);
|
|
1765
|
+
if (msg.type === "outbox.closed") {
|
|
1766
|
+
for (const handler of handlers.closed) handler(msg.reason);
|
|
1767
|
+
off();
|
|
1768
|
+
}
|
|
1769
|
+
});
|
|
1770
|
+
fire({ type: "outbox.subscribe", id: id(), subId, filters: Array.isArray(filters) ? filters : [filters], ...options ? { options } : {} });
|
|
1771
|
+
return {
|
|
1772
|
+
on(event, handler) {
|
|
1773
|
+
handlers[event].add(handler);
|
|
1774
|
+
return { close: () => handlers[event].delete(handler) };
|
|
1775
|
+
},
|
|
1776
|
+
close() {
|
|
1777
|
+
fire({ type: "outbox.close", id: id(), subId });
|
|
1778
|
+
off();
|
|
1779
|
+
handlers.event.clear();
|
|
1780
|
+
handlers.closed.clear();
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
},
|
|
1784
|
+
publish: (event, options) => req("outbox.publish", { event, ...options ? { options } : {} }),
|
|
1785
|
+
resolveRelays: (targetValue) => req("outbox.resolveRelays", { target: targetValue }).then((msg) => msg.plan ?? msg)
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1788
|
+
function makeUpload() {
|
|
1789
|
+
return {
|
|
1790
|
+
info: () => request({ type: "upload.info" }, "upload.info.result", (msg) => fieldOrThrow(msg, "info", "upload info unavailable")),
|
|
1791
|
+
upload: (requestPayload) => request({ type: "upload.upload", request: requestPayload }, "upload.upload.result", (msg) => fieldOrThrow(msg, "result", "upload failed")),
|
|
1792
|
+
status: (uploadId) => request({ type: "upload.status", uploadId }, "upload.status.result", (msg) => fieldOrThrow(msg, "status", "upload status unavailable")),
|
|
1793
|
+
onStatus(callback) {
|
|
1794
|
+
const off = listen((event) => {
|
|
1795
|
+
if (!isParentMessage(event)) return;
|
|
1796
|
+
const msg = event.data;
|
|
1797
|
+
if (typeof msg === "object" && msg !== null && msg.type === "upload.status.changed" && msg.status !== void 0) callback(msg.status);
|
|
1798
|
+
});
|
|
1799
|
+
return subscriptionHandle(off);
|
|
1800
|
+
}
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
function makeIntent() {
|
|
1804
|
+
const invoke = (requestPayload) => request(
|
|
1805
|
+
{ type: "intent.invoke", request: requestPayload },
|
|
1806
|
+
"intent.invoke.result",
|
|
1807
|
+
(msg) => fieldOrThrow(msg, "result", "intent.invoke.result missing result")
|
|
1808
|
+
);
|
|
1809
|
+
return {
|
|
1810
|
+
invoke,
|
|
1811
|
+
open: (archetype, payload, opts) => invoke({
|
|
1812
|
+
archetype,
|
|
1813
|
+
action: "open",
|
|
1814
|
+
payload,
|
|
1815
|
+
...opts && typeof opts === "object" ? opts : {}
|
|
1816
|
+
}),
|
|
1817
|
+
available: (archetype) => request(
|
|
1818
|
+
{ type: "intent.available", archetype },
|
|
1819
|
+
"intent.available.result",
|
|
1820
|
+
(msg) => fieldOrThrow(msg, "availability", "intent.available.result missing availability")
|
|
1821
|
+
),
|
|
1822
|
+
handlers: () => request(
|
|
1823
|
+
{ type: "intent.handlers" },
|
|
1824
|
+
"intent.handlers.result",
|
|
1825
|
+
(msg) => fieldOrThrow(msg, "handlers", "intent.handlers.result missing handlers")
|
|
1826
|
+
),
|
|
1827
|
+
onChanged: (callback) => domainEventHandle(
|
|
1828
|
+
"intent.changed",
|
|
1829
|
+
callback,
|
|
1830
|
+
(msg) => msg.availability
|
|
1831
|
+
)
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
function makeWebrtc() {
|
|
1835
|
+
return {
|
|
1836
|
+
open: (requestPayload) => request(
|
|
1837
|
+
{ type: "webrtc.open", request: requestPayload },
|
|
1838
|
+
"webrtc.open.result",
|
|
1839
|
+
(msg) => ({ session: fieldOrThrow(msg, "session", "webrtc.open.result missing session") })
|
|
1840
|
+
),
|
|
1841
|
+
send: (sessionId, payload) => request(
|
|
1842
|
+
{ type: "webrtc.send", sessionId, payload },
|
|
1843
|
+
"webrtc.send.result",
|
|
1844
|
+
(msg) => voidResult(msg, "webrtc send failed")
|
|
1845
|
+
),
|
|
1846
|
+
close: (sessionId, reason) => request(
|
|
1847
|
+
{ type: "webrtc.close", sessionId, ...reason ? { reason } : {} },
|
|
1848
|
+
"webrtc.close.result",
|
|
1849
|
+
(msg) => voidResult(msg, "webrtc close failed")
|
|
1850
|
+
),
|
|
1851
|
+
onEvent: (callback) => domainEventHandle("webrtc.event", callback)
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
function makeBle() {
|
|
1855
|
+
const req = (action, payload, map) => request(
|
|
1856
|
+
{ type: `ble.${action}`, ...payload },
|
|
1857
|
+
`ble.${action}.result`,
|
|
1858
|
+
map
|
|
1859
|
+
);
|
|
1860
|
+
return {
|
|
1861
|
+
open: (requestPayload) => req("open", { request: requestPayload }, (msg) => ({ session: fieldOrThrow(msg, "session", "ble.open.result missing session") })),
|
|
1862
|
+
services: (sessionId) => req("services", { sessionId }, (msg) => fieldOrThrow(msg, "services", "ble.services.result missing services")),
|
|
1863
|
+
read: (sessionId, targetValue) => req("read", { sessionId, target: targetValue }, (msg) => fieldOrThrow(msg, "data", "ble.read.result missing data")),
|
|
1864
|
+
write: (sessionId, targetValue, data, options) => req(
|
|
1865
|
+
"write",
|
|
1866
|
+
{ sessionId, target: targetValue, data, ...options ? { options } : {} },
|
|
1867
|
+
(msg) => voidResult(msg, "ble write failed")
|
|
1868
|
+
),
|
|
1869
|
+
subscribe: (sessionId, targetValue) => req("subscribe", { sessionId, target: targetValue }, (msg) => voidResult(msg, "ble subscribe failed")),
|
|
1870
|
+
unsubscribe: (sessionId, targetValue) => req("unsubscribe", { sessionId, target: targetValue }, (msg) => voidResult(msg, "ble unsubscribe failed")),
|
|
1871
|
+
close: (sessionId, reason) => req("close", { sessionId, ...reason ? { reason } : {} }, (msg) => voidResult(msg, "ble close failed")),
|
|
1872
|
+
onEvent: (callback) => domainEventHandle("ble.event", callback)
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
function makeSerial() {
|
|
1876
|
+
return {
|
|
1877
|
+
open: (requestPayload) => request(
|
|
1878
|
+
{ type: "serial.open", request: requestPayload },
|
|
1879
|
+
"serial.open.result",
|
|
1880
|
+
(msg) => ({ session: fieldOrThrow(msg, "session", "serial.open.result missing session") })
|
|
1881
|
+
),
|
|
1882
|
+
write: (sessionId, data) => request(
|
|
1883
|
+
{ type: "serial.write", sessionId, data: Array.from(data) },
|
|
1884
|
+
"serial.write.result",
|
|
1885
|
+
(msg) => voidResult(msg, "serial write failed")
|
|
1886
|
+
),
|
|
1887
|
+
close: (sessionId, reason) => request(
|
|
1888
|
+
{ type: "serial.close", sessionId, ...reason === void 0 ? {} : { reason } },
|
|
1889
|
+
"serial.close.result",
|
|
1890
|
+
(msg) => voidResult(msg, "serial close failed")
|
|
1891
|
+
),
|
|
1892
|
+
onEvent: (callback) => domainEventHandle("serial.event", callback)
|
|
1893
|
+
};
|
|
1894
|
+
}
|
|
1895
|
+
function makeLink() {
|
|
1896
|
+
return {
|
|
1897
|
+
open: (url, options) => request(
|
|
1898
|
+
{ type: "link.open", url, ...options ? { options } : {} },
|
|
1899
|
+
"link.open.result",
|
|
1900
|
+
resultOrError,
|
|
1901
|
+
{ rejectOnError: false }
|
|
1902
|
+
)
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
function makeCount() {
|
|
1906
|
+
return {
|
|
1907
|
+
query: (filters, options) => request(
|
|
1908
|
+
{ type: "count.query", filters: Array.isArray(filters) ? filters : [filters], ...options ? { options } : {} },
|
|
1909
|
+
"count.query.result",
|
|
1910
|
+
resultOrError,
|
|
1911
|
+
{ rejectOnError: false }
|
|
1912
|
+
)
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1915
|
+
function makeLists() {
|
|
1916
|
+
const req = (type, payload) => request({ type, ...payload }, `${type}.result`, resultOrError, { rejectOnError: false });
|
|
1917
|
+
return {
|
|
1918
|
+
supported: () => req("lists.supported", {}),
|
|
1919
|
+
add: (list, items, options) => req("lists.add", { list, items, ...options ? { options } : {} }),
|
|
1920
|
+
remove: (list, items, options) => req("lists.remove", { list, items, ...options ? { options } : {} })
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
function makeCommon() {
|
|
1924
|
+
const req = (type, payload) => request({ type, ...payload }, `${type}.result`, withoutEnvelope, { rejectOnError: false });
|
|
1925
|
+
return {
|
|
1926
|
+
encodeNip19: (input) => req("common.encodeNip19", { input }),
|
|
1927
|
+
decodeNip19: (value) => req("common.decodeNip19", { value }),
|
|
1928
|
+
getProfile: (targetValue) => req("common.getProfile", { target: targetValue }),
|
|
1929
|
+
follows: () => req("common.follows", {}),
|
|
1930
|
+
follow: (...pubkeys) => req("common.follow", { pubkeys }),
|
|
1931
|
+
unfollow: (...pubkeys) => req("common.unfollow", { pubkeys }),
|
|
1932
|
+
react: (targetEventId, reaction, customEmojiHref) => req("common.react", {
|
|
1933
|
+
targetEventId,
|
|
1934
|
+
reaction,
|
|
1935
|
+
...customEmojiHref === void 0 ? {} : { customEmojiHref }
|
|
1936
|
+
}),
|
|
1937
|
+
report: (targetValue, reason, text) => req("common.report", {
|
|
1938
|
+
target: targetValue,
|
|
1939
|
+
reason,
|
|
1940
|
+
text
|
|
1941
|
+
})
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
function makeDm() {
|
|
1945
|
+
const req = (type, payload) => request({ type, ...payload }, `${type}.result`, withoutEnvelope, { rejectOnError: false });
|
|
1946
|
+
return {
|
|
1947
|
+
status: () => req("dm.status", {}),
|
|
1948
|
+
conversations: (query) => req("dm.conversations", query ?? {}),
|
|
1949
|
+
messages: (query) => req("dm.messages", query ?? {}),
|
|
1950
|
+
send: (requestPayload) => req("dm.send", requestPayload ?? {}),
|
|
1951
|
+
subscribe: (requestPayload) => req("dm.subscribe", requestPayload ?? {}),
|
|
1952
|
+
unsubscribe: (subscriptionId) => req("dm.unsubscribe", { subscriptionId }),
|
|
1953
|
+
onMessage(callback) {
|
|
1954
|
+
const off = listen((event) => {
|
|
1955
|
+
if (!isParentMessage(event)) return;
|
|
1956
|
+
const msg = event.data;
|
|
1957
|
+
if (typeof msg === "object" && msg !== null && msg.type === "dm.message" && typeof msg.subscriptionId === "string") {
|
|
1958
|
+
callback(msg.message, msg.subscriptionId);
|
|
1959
|
+
}
|
|
1960
|
+
});
|
|
1961
|
+
return subscriptionHandle(off);
|
|
1962
|
+
}
|
|
1963
|
+
};
|
|
1964
|
+
}
|
|
1965
|
+
function makeDomain(domain, existing) {
|
|
1966
|
+
if (existing && typeof existing === "object" && Object.keys(existing).length > 0) return existing;
|
|
1967
|
+
switch (domain) {
|
|
1968
|
+
case "relay":
|
|
1969
|
+
return makeRelay();
|
|
1970
|
+
case "inc":
|
|
1971
|
+
return makeInc();
|
|
1972
|
+
case "storage":
|
|
1973
|
+
return makeStorage();
|
|
1974
|
+
case "keys":
|
|
1975
|
+
return makeKeys();
|
|
1976
|
+
case "media":
|
|
1977
|
+
return makeMedia();
|
|
1978
|
+
case "notify":
|
|
1979
|
+
return makeNotify();
|
|
1980
|
+
case "identity":
|
|
1981
|
+
return makeIdentity();
|
|
1982
|
+
case "theme":
|
|
1983
|
+
return makeTheme();
|
|
1984
|
+
case "config":
|
|
1985
|
+
return makeConfig();
|
|
1986
|
+
case "resource":
|
|
1987
|
+
return makeResource();
|
|
1988
|
+
case "cvm":
|
|
1989
|
+
return makeCvm();
|
|
1990
|
+
case "outbox":
|
|
1991
|
+
return makeOutbox();
|
|
1992
|
+
case "upload":
|
|
1993
|
+
return makeUpload();
|
|
1994
|
+
case "intent":
|
|
1995
|
+
return makeIntent();
|
|
1996
|
+
case "webrtc":
|
|
1997
|
+
return makeWebrtc();
|
|
1998
|
+
case "ble":
|
|
1999
|
+
return makeBle();
|
|
2000
|
+
case "link":
|
|
2001
|
+
return makeLink();
|
|
2002
|
+
case "count":
|
|
2003
|
+
return makeCount();
|
|
2004
|
+
case "lists":
|
|
2005
|
+
return makeLists();
|
|
2006
|
+
case "common":
|
|
2007
|
+
return makeCommon();
|
|
2008
|
+
case "serial":
|
|
2009
|
+
return makeSerial();
|
|
2010
|
+
case "dm":
|
|
2011
|
+
return makeDm();
|
|
2012
|
+
default:
|
|
2013
|
+
return {};
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
function guardNappletNamespace(namespace) {
|
|
2017
|
+
return new Proxy(namespace, {
|
|
2018
|
+
set(obj, prop, value) {
|
|
2019
|
+
if (typeof prop !== "string" || !allowed.has(prop)) return true;
|
|
2020
|
+
obj[prop] = makeDomain(prop, value);
|
|
2021
|
+
return true;
|
|
2022
|
+
},
|
|
2023
|
+
defineProperty(obj, prop, descriptor) {
|
|
2024
|
+
if (typeof prop !== "string" || !allowed.has(prop)) return true;
|
|
2025
|
+
return Reflect.defineProperty(obj, prop, {
|
|
2026
|
+
...descriptor,
|
|
2027
|
+
value: makeDomain(prop, descriptor.value)
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
1278
2032
|
function buildNappletNamespace(value) {
|
|
1279
2033
|
const candidate = typeof value === "object" && value !== null ? value : {};
|
|
1280
2034
|
const next = {};
|
|
1281
2035
|
for (const domain of domains) {
|
|
2036
|
+
if (!allowed.has(domain)) continue;
|
|
1282
2037
|
Object.defineProperty(next, domain, {
|
|
1283
|
-
value:
|
|
2038
|
+
value: makeDomain(
|
|
2039
|
+
domain,
|
|
2040
|
+
Object.prototype.hasOwnProperty.call(candidate, domain) ? candidate[domain] : void 0
|
|
2041
|
+
),
|
|
1284
2042
|
enumerable: true,
|
|
1285
2043
|
configurable: true,
|
|
1286
2044
|
writable: true
|
|
1287
2045
|
});
|
|
1288
2046
|
}
|
|
1289
|
-
return next;
|
|
2047
|
+
return guardNappletNamespace(next);
|
|
1290
2048
|
}
|
|
1291
2049
|
let root = buildNappletNamespace(target.napplet);
|
|
1292
2050
|
Object.defineProperty(target, "napplet", {
|