@kehto/services 0.11.1 → 0.12.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/README.md +74 -2
- package/dist/index.d.ts +228 -11
- package/dist/index.js +883 -34
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1650,19 +1650,35 @@ function untrackRequest(state, requestId) {
|
|
|
1650
1650
|
state.perWindow.get(entry.windowId)?.delete(requestId);
|
|
1651
1651
|
}
|
|
1652
1652
|
}
|
|
1653
|
-
function sendResourceError(send, requestId, code, message) {
|
|
1653
|
+
function sendResourceError(send, requestId, code, message, error = toResourceError(code), type = "resource.bytes.error") {
|
|
1654
1654
|
send({
|
|
1655
|
-
type
|
|
1655
|
+
type,
|
|
1656
|
+
id: requestId,
|
|
1656
1657
|
requestId,
|
|
1658
|
+
error,
|
|
1657
1659
|
code,
|
|
1658
1660
|
message
|
|
1659
1661
|
});
|
|
1660
1662
|
}
|
|
1661
|
-
function
|
|
1663
|
+
function sendBytesManyError(send, requestId, code, message, error) {
|
|
1664
|
+
sendResourceError(send, requestId, code, message, error, "resource.bytesMany.error");
|
|
1665
|
+
}
|
|
1666
|
+
function toResourceError(code) {
|
|
1667
|
+
switch (code) {
|
|
1668
|
+
case "denied":
|
|
1669
|
+
return "blocked-by-policy";
|
|
1670
|
+
case "invalid-url":
|
|
1671
|
+
return "invalid-request";
|
|
1672
|
+
case "canceled":
|
|
1673
|
+
return "timeout";
|
|
1674
|
+
case "network-error":
|
|
1675
|
+
return "network-error";
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
function parseResourceUrl(url) {
|
|
1662
1679
|
try {
|
|
1663
1680
|
return new URL(url);
|
|
1664
1681
|
} catch {
|
|
1665
|
-
sendResourceError(send, requestId, "invalid-url", `invalid URL: ${url}`);
|
|
1666
1682
|
return null;
|
|
1667
1683
|
}
|
|
1668
1684
|
}
|
|
@@ -1673,45 +1689,138 @@ function collectResponseHeaders(response) {
|
|
|
1673
1689
|
});
|
|
1674
1690
|
return headers;
|
|
1675
1691
|
}
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
if (
|
|
1692
|
+
function responseMime(response) {
|
|
1693
|
+
return response.headers.get("content-type") || "application/octet-stream";
|
|
1694
|
+
}
|
|
1695
|
+
function responseBlob(buffer, mime) {
|
|
1696
|
+
return new Blob([buffer], { type: mime });
|
|
1697
|
+
}
|
|
1698
|
+
function requestIdFromMessage(message) {
|
|
1699
|
+
if (typeof message.id === "string" && message.id.length > 0) return message.id;
|
|
1700
|
+
if (typeof message.requestId === "string" && message.requestId.length > 0) return message.requestId;
|
|
1701
|
+
return null;
|
|
1702
|
+
}
|
|
1703
|
+
function resourceInvalidRequest(url, message) {
|
|
1704
|
+
return {
|
|
1705
|
+
ok: false,
|
|
1706
|
+
url,
|
|
1707
|
+
error: "invalid-request",
|
|
1708
|
+
code: "invalid-url",
|
|
1709
|
+
message
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
async function fetchResourceItem(options, identity, url, init, signal) {
|
|
1713
|
+
const parsedUrl = parseResourceUrl(url);
|
|
1714
|
+
if (!parsedUrl) return resourceInvalidRequest(url, `invalid URL: ${url}`);
|
|
1685
1715
|
const origin = parsedUrl.origin;
|
|
1686
1716
|
const grants = options.getConnectGrants(identity.dTag, identity.aggregateHash);
|
|
1687
1717
|
if (!options.isOriginGranted(origin, grants)) {
|
|
1688
|
-
|
|
1689
|
-
|
|
1718
|
+
return {
|
|
1719
|
+
ok: false,
|
|
1720
|
+
url,
|
|
1721
|
+
error: "blocked-by-policy",
|
|
1722
|
+
code: "denied",
|
|
1723
|
+
message: `origin ${origin} not granted`
|
|
1724
|
+
};
|
|
1690
1725
|
}
|
|
1691
|
-
const controller = new AbortController();
|
|
1692
|
-
trackRequest(state, requestId, windowId, controller);
|
|
1693
1726
|
try {
|
|
1694
1727
|
const response = await options.fetch(url, {
|
|
1695
1728
|
method: init?.method,
|
|
1696
1729
|
headers: init?.headers ? { ...init.headers } : void 0,
|
|
1697
|
-
signal
|
|
1730
|
+
signal
|
|
1698
1731
|
});
|
|
1699
1732
|
const buffer = await response.arrayBuffer();
|
|
1733
|
+
const headers = collectResponseHeaders(response);
|
|
1734
|
+
const mime = responseMime(response);
|
|
1735
|
+
return {
|
|
1736
|
+
ok: true,
|
|
1737
|
+
url,
|
|
1738
|
+
blob: responseBlob(buffer, mime),
|
|
1739
|
+
mime,
|
|
1740
|
+
status: response.status,
|
|
1741
|
+
headers,
|
|
1742
|
+
bodyBase64: arrayBufferToBase64(buffer)
|
|
1743
|
+
};
|
|
1744
|
+
} catch (err) {
|
|
1745
|
+
const isAbort = signal.aborted || err instanceof Error && (err.name === "AbortError" || err.name === "DOMException");
|
|
1746
|
+
return {
|
|
1747
|
+
ok: false,
|
|
1748
|
+
url,
|
|
1749
|
+
error: isAbort ? "timeout" : "network-error",
|
|
1750
|
+
code: isAbort ? "canceled" : "network-error",
|
|
1751
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
async function handleBytes(options, state, windowId, msg, send) {
|
|
1756
|
+
const { requestId, url, init } = msg;
|
|
1757
|
+
const identity = options.resolveIdentity(windowId);
|
|
1758
|
+
if (!identity) {
|
|
1759
|
+
sendResourceError(send, requestId, "denied", "napplet identity not resolvable", "blocked-by-policy");
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1762
|
+
const controller = new AbortController();
|
|
1763
|
+
trackRequest(state, requestId, windowId, controller);
|
|
1764
|
+
try {
|
|
1765
|
+
const item = await fetchResourceItem(options, identity, url, init, controller.signal);
|
|
1766
|
+
if (!item.ok) {
|
|
1767
|
+
sendResourceError(send, requestId, item.code, item.message, item.error);
|
|
1768
|
+
return;
|
|
1769
|
+
}
|
|
1700
1770
|
send({
|
|
1701
1771
|
type: "resource.bytes.result",
|
|
1772
|
+
id: requestId,
|
|
1702
1773
|
requestId,
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1774
|
+
blob: item.blob,
|
|
1775
|
+
mime: item.mime,
|
|
1776
|
+
status: item.status,
|
|
1777
|
+
headers: item.headers,
|
|
1778
|
+
bodyBase64: item.bodyBase64
|
|
1706
1779
|
});
|
|
1707
|
-
}
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1780
|
+
} finally {
|
|
1781
|
+
untrackRequest(state, requestId);
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
async function handleBytesMany(options, state, windowId, msg, send) {
|
|
1785
|
+
const { requestId, urls, init } = msg;
|
|
1786
|
+
if (!Array.isArray(urls) || urls.length === 0 || urls.some((url) => typeof url !== "string")) {
|
|
1787
|
+
sendBytesManyError(send, requestId, "invalid-url", "resource.bytesMany requires a non-empty urls array", "invalid-request");
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
const identity = options.resolveIdentity(windowId);
|
|
1791
|
+
if (!identity) {
|
|
1792
|
+
sendBytesManyError(send, requestId, "denied", "napplet identity not resolvable", "blocked-by-policy");
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
const controller = new AbortController();
|
|
1796
|
+
trackRequest(state, requestId, windowId, controller);
|
|
1797
|
+
try {
|
|
1798
|
+
const items = [];
|
|
1799
|
+
for (const url of urls) {
|
|
1800
|
+
const item = await fetchResourceItem(options, identity, url, init, controller.signal);
|
|
1801
|
+
if (item.ok) {
|
|
1802
|
+
items.push({
|
|
1803
|
+
url: item.url,
|
|
1804
|
+
ok: true,
|
|
1805
|
+
blob: item.blob,
|
|
1806
|
+
mime: item.mime
|
|
1807
|
+
});
|
|
1808
|
+
} else {
|
|
1809
|
+
items.push({
|
|
1810
|
+
url: item.url,
|
|
1811
|
+
ok: false,
|
|
1812
|
+
error: item.error,
|
|
1813
|
+
code: item.code,
|
|
1814
|
+
message: item.message
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
send({
|
|
1819
|
+
type: "resource.bytesMany.result",
|
|
1820
|
+
id: requestId,
|
|
1711
1821
|
requestId,
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
);
|
|
1822
|
+
items
|
|
1823
|
+
});
|
|
1715
1824
|
} finally {
|
|
1716
1825
|
untrackRequest(state, requestId);
|
|
1717
1826
|
}
|
|
@@ -1751,13 +1860,24 @@ function createResourceService(options) {
|
|
|
1751
1860
|
switch (message.type) {
|
|
1752
1861
|
case "resource.bytes": {
|
|
1753
1862
|
const m = message;
|
|
1754
|
-
|
|
1863
|
+
const requestId = requestIdFromMessage(m);
|
|
1864
|
+
if (!requestId || typeof m.url !== "string") return;
|
|
1865
|
+
handleBytes(options, state, windowId, { requestId, url: m.url, init: m.init }, send).catch(() => {
|
|
1866
|
+
});
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
case "resource.bytesMany": {
|
|
1870
|
+
const m = message;
|
|
1871
|
+
const requestId = requestIdFromMessage(m);
|
|
1872
|
+
if (!requestId) return;
|
|
1873
|
+
handleBytesMany(options, state, windowId, { requestId, urls: m.urls ?? [], init: m.init }, send).catch(() => {
|
|
1755
1874
|
});
|
|
1756
1875
|
return;
|
|
1757
1876
|
}
|
|
1758
1877
|
case "resource.cancel": {
|
|
1759
1878
|
const m = message;
|
|
1760
|
-
|
|
1879
|
+
const requestId = requestIdFromMessage(m);
|
|
1880
|
+
if (requestId) handleCancel(state, requestId);
|
|
1761
1881
|
return;
|
|
1762
1882
|
}
|
|
1763
1883
|
default:
|
|
@@ -2490,7 +2610,7 @@ function createIntentService(options) {
|
|
|
2490
2610
|
send({ type: "intent.changed", availability });
|
|
2491
2611
|
}
|
|
2492
2612
|
});
|
|
2493
|
-
function
|
|
2613
|
+
function settle6(call, send, resultType, id, onValue) {
|
|
2494
2614
|
let pending;
|
|
2495
2615
|
try {
|
|
2496
2616
|
pending = Promise.resolve(call());
|
|
@@ -2508,7 +2628,7 @@ function createIntentService(options) {
|
|
|
2508
2628
|
send({ type: "intent.invoke.result", id, error: "invalid request" });
|
|
2509
2629
|
return;
|
|
2510
2630
|
}
|
|
2511
|
-
|
|
2631
|
+
settle6(
|
|
2512
2632
|
() => resolver.invoke(request, { windowId }),
|
|
2513
2633
|
send,
|
|
2514
2634
|
"intent.invoke.result",
|
|
@@ -2524,7 +2644,7 @@ function createIntentService(options) {
|
|
|
2524
2644
|
return;
|
|
2525
2645
|
}
|
|
2526
2646
|
const archetype = m.archetype;
|
|
2527
|
-
|
|
2647
|
+
settle6(
|
|
2528
2648
|
() => resolver.available(archetype),
|
|
2529
2649
|
send,
|
|
2530
2650
|
"intent.available.result",
|
|
@@ -2535,7 +2655,7 @@ function createIntentService(options) {
|
|
|
2535
2655
|
function handleHandlers(msg, send) {
|
|
2536
2656
|
const m = msg;
|
|
2537
2657
|
const id = m.id ?? "";
|
|
2538
|
-
|
|
2658
|
+
settle6(
|
|
2539
2659
|
() => resolver.handlers(),
|
|
2540
2660
|
send,
|
|
2541
2661
|
"intent.handlers.result",
|
|
@@ -2810,11 +2930,736 @@ function toErrorMessage5(err) {
|
|
|
2810
2930
|
if (typeof err === "string") return err;
|
|
2811
2931
|
return "cvm request failed";
|
|
2812
2932
|
}
|
|
2933
|
+
|
|
2934
|
+
// src/link-service.ts
|
|
2935
|
+
var LINK_SERVICE_VERSION = "1.0.0";
|
|
2936
|
+
var DEFAULT_ALLOWED_PROTOCOLS = ["http:", "https:"];
|
|
2937
|
+
function denied(id, error) {
|
|
2938
|
+
return { type: "link.open.result", id, status: "denied", error };
|
|
2939
|
+
}
|
|
2940
|
+
function parseLinkUrl(id, rawUrl) {
|
|
2941
|
+
try {
|
|
2942
|
+
return new URL(rawUrl);
|
|
2943
|
+
} catch {
|
|
2944
|
+
return denied(id, "invalid-url");
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
function isProtocolAllowed(url, allowedProtocols) {
|
|
2948
|
+
return allowedProtocols.includes(url.protocol);
|
|
2949
|
+
}
|
|
2950
|
+
async function handleOpen(options, windowId, message, send) {
|
|
2951
|
+
const parsed = parseLinkUrl(message.id, message.url);
|
|
2952
|
+
if ("type" in parsed) {
|
|
2953
|
+
send(parsed);
|
|
2954
|
+
return;
|
|
2955
|
+
}
|
|
2956
|
+
const allowedProtocols = options.allowedProtocols ?? DEFAULT_ALLOWED_PROTOCOLS;
|
|
2957
|
+
if (!isProtocolAllowed(parsed, allowedProtocols)) {
|
|
2958
|
+
send(denied(message.id, "unsupported-scheme"));
|
|
2959
|
+
return;
|
|
2960
|
+
}
|
|
2961
|
+
if (!options.open) {
|
|
2962
|
+
send(denied(message.id, "blocked-by-policy"));
|
|
2963
|
+
return;
|
|
2964
|
+
}
|
|
2965
|
+
try {
|
|
2966
|
+
const result = await options.open({ windowId, url: parsed, options: message.options });
|
|
2967
|
+
send({
|
|
2968
|
+
type: "link.open.result",
|
|
2969
|
+
id: message.id,
|
|
2970
|
+
status: result.status,
|
|
2971
|
+
...result.status === "denied" ? { error: "blocked-by-policy" } : {}
|
|
2972
|
+
});
|
|
2973
|
+
} catch {
|
|
2974
|
+
send(denied(message.id, "blocked-by-policy"));
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
function createLinkService(options = {}) {
|
|
2978
|
+
const descriptor = {
|
|
2979
|
+
name: "link",
|
|
2980
|
+
version: LINK_SERVICE_VERSION,
|
|
2981
|
+
description: "NAP-LINK reference handler for shell-mediated link opening"
|
|
2982
|
+
};
|
|
2983
|
+
return {
|
|
2984
|
+
descriptor,
|
|
2985
|
+
handleMessage(windowId, message, send) {
|
|
2986
|
+
if (message.type === "link.open") {
|
|
2987
|
+
void handleOpen(options, windowId, message, send);
|
|
2988
|
+
return;
|
|
2989
|
+
}
|
|
2990
|
+
const id = message.id ?? "";
|
|
2991
|
+
send({
|
|
2992
|
+
type: `${message.type}.error`,
|
|
2993
|
+
id,
|
|
2994
|
+
error: `Unknown link method: ${message.type}`
|
|
2995
|
+
});
|
|
2996
|
+
},
|
|
2997
|
+
onWindowDestroyed(_windowId) {
|
|
2998
|
+
}
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
// src/lists-service.ts
|
|
3003
|
+
var LISTS_SERVICE_VERSION = "1.0.0";
|
|
3004
|
+
var LISTS_DESCRIPTOR = {
|
|
3005
|
+
name: "lists",
|
|
3006
|
+
version: LISTS_SERVICE_VERSION,
|
|
3007
|
+
description: "NAP-LISTS reference handler for shell-mediated NIP-51 list mutations"
|
|
3008
|
+
};
|
|
3009
|
+
function errorMessage(err, fallback) {
|
|
3010
|
+
if (err instanceof Error) return err.message;
|
|
3011
|
+
if (typeof err === "string") return err;
|
|
3012
|
+
return fallback;
|
|
3013
|
+
}
|
|
3014
|
+
function settle(call, send, okFalse, onValue) {
|
|
3015
|
+
let pending;
|
|
3016
|
+
try {
|
|
3017
|
+
pending = Promise.resolve(call());
|
|
3018
|
+
} catch (err) {
|
|
3019
|
+
send(okFalse(errorMessage(err, "lists request failed")));
|
|
3020
|
+
return;
|
|
3021
|
+
}
|
|
3022
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage(err, "lists request failed"))));
|
|
3023
|
+
}
|
|
3024
|
+
function unsupportedMutation(resultType, id) {
|
|
3025
|
+
return {
|
|
3026
|
+
type: resultType,
|
|
3027
|
+
id,
|
|
3028
|
+
ok: false,
|
|
3029
|
+
error: "unsupported",
|
|
3030
|
+
reason: `${resultType.replace(".result", "")} unavailable`,
|
|
3031
|
+
supported: []
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
3034
|
+
function settleMutation(hook, message, context, send, resultType) {
|
|
3035
|
+
if (!hook) {
|
|
3036
|
+
send(unsupportedMutation(resultType, message.id));
|
|
3037
|
+
return;
|
|
3038
|
+
}
|
|
3039
|
+
settle(
|
|
3040
|
+
() => hook(message.list, message.items, message.options, context),
|
|
3041
|
+
send,
|
|
3042
|
+
(error) => ({ type: resultType, id: message.id, ok: false, error: "list-unavailable", reason: error }),
|
|
3043
|
+
(result) => ({ type: resultType, id: message.id, ...result })
|
|
3044
|
+
);
|
|
3045
|
+
}
|
|
3046
|
+
function createListsService(options = {}) {
|
|
3047
|
+
return {
|
|
3048
|
+
descriptor: LISTS_DESCRIPTOR,
|
|
3049
|
+
handleMessage(windowId, message, send) {
|
|
3050
|
+
const id = message.id ?? "";
|
|
3051
|
+
const context = { windowId };
|
|
3052
|
+
if (message.type === "lists.supported") {
|
|
3053
|
+
if (!options.supported) {
|
|
3054
|
+
send({ type: "lists.supported.result", id, lists: [] });
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
settle(
|
|
3058
|
+
() => options.supported(context),
|
|
3059
|
+
send,
|
|
3060
|
+
(error) => ({ type: "lists.supported.result", id, error }),
|
|
3061
|
+
(lists) => ({ type: "lists.supported.result", id, lists: [...lists] })
|
|
3062
|
+
);
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
if (message.type === "lists.add") {
|
|
3066
|
+
settleMutation(options.add, message, context, send, "lists.add.result");
|
|
3067
|
+
return;
|
|
3068
|
+
}
|
|
3069
|
+
if (message.type === "lists.remove") {
|
|
3070
|
+
settleMutation(options.remove, message, context, send, "lists.remove.result");
|
|
3071
|
+
return;
|
|
3072
|
+
}
|
|
3073
|
+
send({
|
|
3074
|
+
type: `${message.type}.error`,
|
|
3075
|
+
id,
|
|
3076
|
+
error: `Unknown lists method: ${message.type}`
|
|
3077
|
+
});
|
|
3078
|
+
},
|
|
3079
|
+
onWindowDestroyed(_windowId) {
|
|
3080
|
+
}
|
|
3081
|
+
};
|
|
3082
|
+
}
|
|
3083
|
+
|
|
3084
|
+
// src/serial-service.ts
|
|
3085
|
+
var SERIAL_SERVICE_VERSION = "1.0.0";
|
|
3086
|
+
var SERIAL_DESCRIPTOR = {
|
|
3087
|
+
name: "serial",
|
|
3088
|
+
version: SERIAL_SERVICE_VERSION,
|
|
3089
|
+
description: "NAP-SERIAL reference handler for shell-mediated serial sessions"
|
|
3090
|
+
};
|
|
3091
|
+
function errorMessage2(err, fallback) {
|
|
3092
|
+
if (err instanceof Error) return err.message;
|
|
3093
|
+
if (typeof err === "string") return err;
|
|
3094
|
+
return fallback;
|
|
3095
|
+
}
|
|
3096
|
+
function settle2(call, send, okFalse, onValue) {
|
|
3097
|
+
let pending;
|
|
3098
|
+
try {
|
|
3099
|
+
pending = Promise.resolve(call());
|
|
3100
|
+
} catch (err) {
|
|
3101
|
+
send(okFalse(errorMessage2(err, "serial request failed")));
|
|
3102
|
+
return;
|
|
3103
|
+
}
|
|
3104
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage2(err, "serial request failed"))));
|
|
3105
|
+
}
|
|
3106
|
+
function unsupported(resultType, id) {
|
|
3107
|
+
return {
|
|
3108
|
+
type: resultType,
|
|
3109
|
+
id,
|
|
3110
|
+
error: `${resultType.replace(".result", "")} unavailable`
|
|
3111
|
+
};
|
|
3112
|
+
}
|
|
3113
|
+
function createSerialService(options = {}) {
|
|
3114
|
+
return {
|
|
3115
|
+
descriptor: SERIAL_DESCRIPTOR,
|
|
3116
|
+
handleMessage(windowId, message, send) {
|
|
3117
|
+
const id = message.id ?? "";
|
|
3118
|
+
const context = { windowId };
|
|
3119
|
+
if (message.type === "serial.open") {
|
|
3120
|
+
if (!options.open) {
|
|
3121
|
+
send(unsupported("serial.open.result", id));
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
const serialMessage = message;
|
|
3125
|
+
settle2(
|
|
3126
|
+
() => options.open(serialMessage.request, context),
|
|
3127
|
+
send,
|
|
3128
|
+
(error) => ({ type: "serial.open.result", id, error }),
|
|
3129
|
+
(result) => ({ type: "serial.open.result", id, session: result.session })
|
|
3130
|
+
);
|
|
3131
|
+
return;
|
|
3132
|
+
}
|
|
3133
|
+
if (message.type === "serial.write") {
|
|
3134
|
+
if (!options.write) {
|
|
3135
|
+
send(unsupported("serial.write.result", id));
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
const serialMessage = message;
|
|
3139
|
+
settle2(
|
|
3140
|
+
() => options.write(serialMessage.sessionId, serialMessage.data, context),
|
|
3141
|
+
send,
|
|
3142
|
+
(error) => ({ type: "serial.write.result", id, error }),
|
|
3143
|
+
() => ({ type: "serial.write.result", id })
|
|
3144
|
+
);
|
|
3145
|
+
return;
|
|
3146
|
+
}
|
|
3147
|
+
if (message.type === "serial.close") {
|
|
3148
|
+
if (!options.close) {
|
|
3149
|
+
send(unsupported("serial.close.result", id));
|
|
3150
|
+
return;
|
|
3151
|
+
}
|
|
3152
|
+
const serialMessage = message;
|
|
3153
|
+
settle2(
|
|
3154
|
+
() => options.close(serialMessage.sessionId, serialMessage.reason, context),
|
|
3155
|
+
send,
|
|
3156
|
+
(error) => ({ type: "serial.close.result", id, error }),
|
|
3157
|
+
() => ({ type: "serial.close.result", id })
|
|
3158
|
+
);
|
|
3159
|
+
return;
|
|
3160
|
+
}
|
|
3161
|
+
send({
|
|
3162
|
+
type: `${message.type}.error`,
|
|
3163
|
+
id,
|
|
3164
|
+
error: `Unknown serial method: ${message.type}`
|
|
3165
|
+
});
|
|
3166
|
+
},
|
|
3167
|
+
onWindowDestroyed(windowId) {
|
|
3168
|
+
options.destroyWindow?.(windowId);
|
|
3169
|
+
}
|
|
3170
|
+
};
|
|
3171
|
+
}
|
|
3172
|
+
|
|
3173
|
+
// src/ble-service.ts
|
|
3174
|
+
var BLE_SERVICE_VERSION = "1.0.0";
|
|
3175
|
+
var BLE_DESCRIPTOR = {
|
|
3176
|
+
name: "ble",
|
|
3177
|
+
version: BLE_SERVICE_VERSION,
|
|
3178
|
+
description: "NAP-BLE reference handler for shell-mediated BLE/GATT sessions"
|
|
3179
|
+
};
|
|
3180
|
+
function errorMessage3(err, fallback) {
|
|
3181
|
+
if (err instanceof Error) return err.message;
|
|
3182
|
+
if (typeof err === "string") return err;
|
|
3183
|
+
return fallback;
|
|
3184
|
+
}
|
|
3185
|
+
function settle3(call, send, okFalse, onValue) {
|
|
3186
|
+
let pending;
|
|
3187
|
+
try {
|
|
3188
|
+
pending = Promise.resolve(call());
|
|
3189
|
+
} catch (err) {
|
|
3190
|
+
send(okFalse(errorMessage3(err, "ble request failed")));
|
|
3191
|
+
return;
|
|
3192
|
+
}
|
|
3193
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage3(err, "ble request failed"))));
|
|
3194
|
+
}
|
|
3195
|
+
function unsupported2(resultType, id) {
|
|
3196
|
+
return {
|
|
3197
|
+
type: resultType,
|
|
3198
|
+
id,
|
|
3199
|
+
error: `${resultType.replace(".result", "")} unavailable`
|
|
3200
|
+
};
|
|
3201
|
+
}
|
|
3202
|
+
function createBleService(options = {}) {
|
|
3203
|
+
return {
|
|
3204
|
+
descriptor: BLE_DESCRIPTOR,
|
|
3205
|
+
handleMessage(windowId, message, send) {
|
|
3206
|
+
const id = message.id ?? "";
|
|
3207
|
+
const context = { windowId };
|
|
3208
|
+
if (message.type === "ble.open") {
|
|
3209
|
+
if (!options.open) {
|
|
3210
|
+
send(unsupported2("ble.open.result", id));
|
|
3211
|
+
return;
|
|
3212
|
+
}
|
|
3213
|
+
const bleMessage = message;
|
|
3214
|
+
settle3(
|
|
3215
|
+
() => options.open(bleMessage.request, context),
|
|
3216
|
+
send,
|
|
3217
|
+
(error) => ({ type: "ble.open.result", id, error }),
|
|
3218
|
+
(result) => ({ type: "ble.open.result", id, session: result.session })
|
|
3219
|
+
);
|
|
3220
|
+
return;
|
|
3221
|
+
}
|
|
3222
|
+
if (message.type === "ble.services") {
|
|
3223
|
+
if (!options.services) {
|
|
3224
|
+
send(unsupported2("ble.services.result", id));
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
3227
|
+
const bleMessage = message;
|
|
3228
|
+
settle3(
|
|
3229
|
+
() => options.services(bleMessage.sessionId, context),
|
|
3230
|
+
send,
|
|
3231
|
+
(error) => ({ type: "ble.services.result", id, error }),
|
|
3232
|
+
(services) => ({ type: "ble.services.result", id, services })
|
|
3233
|
+
);
|
|
3234
|
+
return;
|
|
3235
|
+
}
|
|
3236
|
+
if (message.type === "ble.read") {
|
|
3237
|
+
if (!options.read) {
|
|
3238
|
+
send(unsupported2("ble.read.result", id));
|
|
3239
|
+
return;
|
|
3240
|
+
}
|
|
3241
|
+
const bleMessage = message;
|
|
3242
|
+
settle3(
|
|
3243
|
+
() => options.read(bleMessage.sessionId, bleMessage.target, context),
|
|
3244
|
+
send,
|
|
3245
|
+
(error) => ({ type: "ble.read.result", id, error }),
|
|
3246
|
+
(data) => ({ type: "ble.read.result", id, data })
|
|
3247
|
+
);
|
|
3248
|
+
return;
|
|
3249
|
+
}
|
|
3250
|
+
if (message.type === "ble.write") {
|
|
3251
|
+
if (!options.write) {
|
|
3252
|
+
send(unsupported2("ble.write.result", id));
|
|
3253
|
+
return;
|
|
3254
|
+
}
|
|
3255
|
+
const bleMessage = message;
|
|
3256
|
+
settle3(
|
|
3257
|
+
() => options.write(bleMessage.sessionId, bleMessage.target, bleMessage.data, bleMessage.options, context),
|
|
3258
|
+
send,
|
|
3259
|
+
(error) => ({ type: "ble.write.result", id, error }),
|
|
3260
|
+
() => ({ type: "ble.write.result", id })
|
|
3261
|
+
);
|
|
3262
|
+
return;
|
|
3263
|
+
}
|
|
3264
|
+
if (message.type === "ble.subscribe") {
|
|
3265
|
+
if (!options.subscribe) {
|
|
3266
|
+
send(unsupported2("ble.subscribe.result", id));
|
|
3267
|
+
return;
|
|
3268
|
+
}
|
|
3269
|
+
const bleMessage = message;
|
|
3270
|
+
settle3(
|
|
3271
|
+
() => options.subscribe(bleMessage.sessionId, bleMessage.target, context),
|
|
3272
|
+
send,
|
|
3273
|
+
(error) => ({ type: "ble.subscribe.result", id, error }),
|
|
3274
|
+
() => ({ type: "ble.subscribe.result", id })
|
|
3275
|
+
);
|
|
3276
|
+
return;
|
|
3277
|
+
}
|
|
3278
|
+
if (message.type === "ble.unsubscribe") {
|
|
3279
|
+
if (!options.unsubscribe) {
|
|
3280
|
+
send(unsupported2("ble.unsubscribe.result", id));
|
|
3281
|
+
return;
|
|
3282
|
+
}
|
|
3283
|
+
const bleMessage = message;
|
|
3284
|
+
settle3(
|
|
3285
|
+
() => options.unsubscribe(bleMessage.sessionId, bleMessage.target, context),
|
|
3286
|
+
send,
|
|
3287
|
+
(error) => ({ type: "ble.unsubscribe.result", id, error }),
|
|
3288
|
+
() => ({ type: "ble.unsubscribe.result", id })
|
|
3289
|
+
);
|
|
3290
|
+
return;
|
|
3291
|
+
}
|
|
3292
|
+
if (message.type === "ble.close") {
|
|
3293
|
+
if (!options.close) {
|
|
3294
|
+
send(unsupported2("ble.close.result", id));
|
|
3295
|
+
return;
|
|
3296
|
+
}
|
|
3297
|
+
const bleMessage = message;
|
|
3298
|
+
settle3(
|
|
3299
|
+
() => options.close(bleMessage.sessionId, bleMessage.reason, context),
|
|
3300
|
+
send,
|
|
3301
|
+
(error) => ({ type: "ble.close.result", id, error }),
|
|
3302
|
+
() => ({ type: "ble.close.result", id })
|
|
3303
|
+
);
|
|
3304
|
+
return;
|
|
3305
|
+
}
|
|
3306
|
+
send({
|
|
3307
|
+
type: `${message.type}.error`,
|
|
3308
|
+
id,
|
|
3309
|
+
error: `Unknown ble method: ${message.type}`
|
|
3310
|
+
});
|
|
3311
|
+
},
|
|
3312
|
+
onWindowDestroyed(windowId) {
|
|
3313
|
+
options.destroyWindow?.(windowId);
|
|
3314
|
+
}
|
|
3315
|
+
};
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
// src/webrtc-service.ts
|
|
3319
|
+
var WEBRTC_SERVICE_VERSION = "1.0.0";
|
|
3320
|
+
var WEBRTC_DESCRIPTOR = {
|
|
3321
|
+
name: "webrtc",
|
|
3322
|
+
version: WEBRTC_SERVICE_VERSION,
|
|
3323
|
+
description: "NAP-WEBRTC reference handler for shell-mediated WebRTC sessions"
|
|
3324
|
+
};
|
|
3325
|
+
function errorMessage4(err, fallback) {
|
|
3326
|
+
if (err instanceof Error) return err.message;
|
|
3327
|
+
if (typeof err === "string") return err;
|
|
3328
|
+
return fallback;
|
|
3329
|
+
}
|
|
3330
|
+
function settle4(call, send, okFalse, onValue) {
|
|
3331
|
+
let pending;
|
|
3332
|
+
try {
|
|
3333
|
+
pending = Promise.resolve(call());
|
|
3334
|
+
} catch (err) {
|
|
3335
|
+
send(okFalse(errorMessage4(err, "webrtc request failed")));
|
|
3336
|
+
return;
|
|
3337
|
+
}
|
|
3338
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage4(err, "webrtc request failed"))));
|
|
3339
|
+
}
|
|
3340
|
+
function unsupported3(resultType, id) {
|
|
3341
|
+
return {
|
|
3342
|
+
type: resultType,
|
|
3343
|
+
id,
|
|
3344
|
+
error: `${resultType.replace(".result", "")} unavailable`
|
|
3345
|
+
};
|
|
3346
|
+
}
|
|
3347
|
+
function createContext(windowId, send) {
|
|
3348
|
+
return {
|
|
3349
|
+
windowId,
|
|
3350
|
+
emit(event) {
|
|
3351
|
+
send({ type: "webrtc.event", event });
|
|
3352
|
+
}
|
|
3353
|
+
};
|
|
3354
|
+
}
|
|
3355
|
+
function createWebrtcService(options = {}) {
|
|
3356
|
+
return {
|
|
3357
|
+
descriptor: WEBRTC_DESCRIPTOR,
|
|
3358
|
+
handleMessage(windowId, message, send) {
|
|
3359
|
+
const id = message.id ?? "";
|
|
3360
|
+
const context = createContext(windowId, send);
|
|
3361
|
+
if (message.type === "webrtc.open") {
|
|
3362
|
+
if (!options.open) {
|
|
3363
|
+
send(unsupported3("webrtc.open.result", id));
|
|
3364
|
+
return;
|
|
3365
|
+
}
|
|
3366
|
+
const webrtcMessage = message;
|
|
3367
|
+
settle4(
|
|
3368
|
+
() => options.open(webrtcMessage.request, context),
|
|
3369
|
+
send,
|
|
3370
|
+
(error) => ({ type: "webrtc.open.result", id, error }),
|
|
3371
|
+
(result) => ({ type: "webrtc.open.result", id, session: result.session })
|
|
3372
|
+
);
|
|
3373
|
+
return;
|
|
3374
|
+
}
|
|
3375
|
+
if (message.type === "webrtc.send") {
|
|
3376
|
+
if (!options.send) {
|
|
3377
|
+
send(unsupported3("webrtc.send.result", id));
|
|
3378
|
+
return;
|
|
3379
|
+
}
|
|
3380
|
+
const webrtcMessage = message;
|
|
3381
|
+
settle4(
|
|
3382
|
+
() => options.send(webrtcMessage.sessionId, webrtcMessage.payload, context),
|
|
3383
|
+
send,
|
|
3384
|
+
(error) => ({ type: "webrtc.send.result", id, error }),
|
|
3385
|
+
() => ({ type: "webrtc.send.result", id })
|
|
3386
|
+
);
|
|
3387
|
+
return;
|
|
3388
|
+
}
|
|
3389
|
+
if (message.type === "webrtc.close") {
|
|
3390
|
+
if (!options.close) {
|
|
3391
|
+
send(unsupported3("webrtc.close.result", id));
|
|
3392
|
+
return;
|
|
3393
|
+
}
|
|
3394
|
+
const webrtcMessage = message;
|
|
3395
|
+
settle4(
|
|
3396
|
+
() => options.close(webrtcMessage.sessionId, webrtcMessage.reason, context),
|
|
3397
|
+
send,
|
|
3398
|
+
(error) => ({ type: "webrtc.close.result", id, error }),
|
|
3399
|
+
() => ({ type: "webrtc.close.result", id })
|
|
3400
|
+
);
|
|
3401
|
+
return;
|
|
3402
|
+
}
|
|
3403
|
+
send({
|
|
3404
|
+
type: `${message.type}.error`,
|
|
3405
|
+
id,
|
|
3406
|
+
error: `Unknown webrtc method: ${message.type}`
|
|
3407
|
+
});
|
|
3408
|
+
},
|
|
3409
|
+
onWindowDestroyed(windowId) {
|
|
3410
|
+
options.destroyWindow?.(windowId);
|
|
3411
|
+
}
|
|
3412
|
+
};
|
|
3413
|
+
}
|
|
3414
|
+
|
|
3415
|
+
// src/common-service.ts
|
|
3416
|
+
import {
|
|
3417
|
+
decode,
|
|
3418
|
+
encodeBytes,
|
|
3419
|
+
naddrEncode,
|
|
3420
|
+
neventEncode,
|
|
3421
|
+
noteEncode,
|
|
3422
|
+
nprofileEncode,
|
|
3423
|
+
npubEncode
|
|
3424
|
+
} from "nostr-tools/nip19";
|
|
3425
|
+
var COMMON_SERVICE_VERSION = "1.0.0";
|
|
3426
|
+
var BECH32_CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
3427
|
+
var COMMON_DESCRIPTOR = {
|
|
3428
|
+
name: "common",
|
|
3429
|
+
version: COMMON_SERVICE_VERSION,
|
|
3430
|
+
description: "NAP-COMMON reference handler for shell-mediated social helpers"
|
|
3431
|
+
};
|
|
3432
|
+
function errorMessage5(err, fallback) {
|
|
3433
|
+
if (err instanceof Error) return err.message;
|
|
3434
|
+
if (typeof err === "string") return err;
|
|
3435
|
+
return fallback;
|
|
3436
|
+
}
|
|
3437
|
+
function encodeNip19(input) {
|
|
3438
|
+
try {
|
|
3439
|
+
switch (input.type) {
|
|
3440
|
+
case "npub":
|
|
3441
|
+
return { ok: true, value: npubEncode(input.hex), nip19Type: input.type };
|
|
3442
|
+
case "note":
|
|
3443
|
+
return { ok: true, value: noteEncode(input.hex), nip19Type: input.type };
|
|
3444
|
+
case "nprofile":
|
|
3445
|
+
return { ok: true, value: nprofileEncode({ pubkey: input.pubkey, relays: input.relays }), nip19Type: input.type };
|
|
3446
|
+
case "nevent":
|
|
3447
|
+
return {
|
|
3448
|
+
ok: true,
|
|
3449
|
+
value: neventEncode({ id: input.eventId, relays: input.relays, author: input.author, kind: input.kind }),
|
|
3450
|
+
nip19Type: input.type
|
|
3451
|
+
};
|
|
3452
|
+
case "naddr":
|
|
3453
|
+
return {
|
|
3454
|
+
ok: true,
|
|
3455
|
+
value: naddrEncode({ identifier: input.identifier, pubkey: input.pubkey, kind: input.kind, relays: input.relays }),
|
|
3456
|
+
nip19Type: input.type
|
|
3457
|
+
};
|
|
3458
|
+
case "nrelay":
|
|
3459
|
+
return { ok: true, value: encodeBytes("nrelay", new TextEncoder().encode(input.relay)), nip19Type: input.type };
|
|
3460
|
+
default:
|
|
3461
|
+
return { ok: false, error: "unsupported NIP-19 type" };
|
|
3462
|
+
}
|
|
3463
|
+
} catch (err) {
|
|
3464
|
+
return { ok: false, error: errorMessage5(err, "NIP-19 encode failed") };
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
function decodeNip19Value(value) {
|
|
3468
|
+
try {
|
|
3469
|
+
const decoded = decode(value);
|
|
3470
|
+
switch (decoded.type) {
|
|
3471
|
+
case "npub":
|
|
3472
|
+
case "note":
|
|
3473
|
+
return { ok: true, nip19Type: decoded.type, hex: decoded.data };
|
|
3474
|
+
case "nprofile":
|
|
3475
|
+
return { ok: true, nip19Type: decoded.type, pubkey: decoded.data.pubkey, relays: decoded.data.relays };
|
|
3476
|
+
case "nevent":
|
|
3477
|
+
return {
|
|
3478
|
+
ok: true,
|
|
3479
|
+
nip19Type: decoded.type,
|
|
3480
|
+
eventId: decoded.data.id,
|
|
3481
|
+
relays: decoded.data.relays,
|
|
3482
|
+
author: decoded.data.author,
|
|
3483
|
+
kind: decoded.data.kind
|
|
3484
|
+
};
|
|
3485
|
+
case "naddr":
|
|
3486
|
+
return {
|
|
3487
|
+
ok: true,
|
|
3488
|
+
nip19Type: decoded.type,
|
|
3489
|
+
identifier: decoded.data.identifier,
|
|
3490
|
+
pubkey: decoded.data.pubkey,
|
|
3491
|
+
kind: decoded.data.kind,
|
|
3492
|
+
relays: decoded.data.relays
|
|
3493
|
+
};
|
|
3494
|
+
default:
|
|
3495
|
+
return { ok: false, error: "unsupported NIP-19 type" };
|
|
3496
|
+
}
|
|
3497
|
+
} catch (err) {
|
|
3498
|
+
if (value.startsWith("nrelay1")) return decodeNrelay(value);
|
|
3499
|
+
return { ok: false, error: errorMessage5(err, "NIP-19 decode failed") };
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
function decodeNrelay(value) {
|
|
3503
|
+
try {
|
|
3504
|
+
const separator = value.lastIndexOf("1");
|
|
3505
|
+
if (separator <= 0 || separator + 7 > value.length) return { ok: false, error: "invalid nrelay value" };
|
|
3506
|
+
const dataPart = value.slice(separator + 1);
|
|
3507
|
+
const words = [...dataPart].map((char) => {
|
|
3508
|
+
const index = BECH32_CHARSET.indexOf(char);
|
|
3509
|
+
if (index === -1) throw new Error("invalid nrelay character");
|
|
3510
|
+
return index;
|
|
3511
|
+
});
|
|
3512
|
+
const payloadWords = words.slice(0, -6);
|
|
3513
|
+
const bytes = convertBits(payloadWords, 5, 8, false);
|
|
3514
|
+
return { ok: true, nip19Type: "nrelay", relay: new TextDecoder().decode(Uint8Array.from(bytes)) };
|
|
3515
|
+
} catch (err) {
|
|
3516
|
+
return { ok: false, error: errorMessage5(err, "invalid nrelay value") };
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
function convertBits(data, fromBits, toBits, pad) {
|
|
3520
|
+
let acc = 0;
|
|
3521
|
+
let bits = 0;
|
|
3522
|
+
const result = [];
|
|
3523
|
+
const maxv = (1 << toBits) - 1;
|
|
3524
|
+
const maxAcc = (1 << fromBits + toBits - 1) - 1;
|
|
3525
|
+
for (const value of data) {
|
|
3526
|
+
if (value < 0 || value >> fromBits !== 0) throw new Error("invalid bech32 data");
|
|
3527
|
+
acc = (acc << fromBits | value) & maxAcc;
|
|
3528
|
+
bits += fromBits;
|
|
3529
|
+
while (bits >= toBits) {
|
|
3530
|
+
bits -= toBits;
|
|
3531
|
+
result.push(acc >> bits & maxv);
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
if (pad) {
|
|
3535
|
+
if (bits > 0) result.push(acc << toBits - bits & maxv);
|
|
3536
|
+
} else if (bits >= fromBits || (acc << toBits - bits & maxv) !== 0) {
|
|
3537
|
+
throw new Error("invalid bech32 padding");
|
|
3538
|
+
}
|
|
3539
|
+
return result;
|
|
3540
|
+
}
|
|
3541
|
+
function settle5(call, send, okFalse, onValue) {
|
|
3542
|
+
let pending;
|
|
3543
|
+
try {
|
|
3544
|
+
pending = Promise.resolve(call());
|
|
3545
|
+
} catch (err) {
|
|
3546
|
+
send(okFalse(errorMessage5(err, "common request failed")));
|
|
3547
|
+
return;
|
|
3548
|
+
}
|
|
3549
|
+
pending.then((value) => send(onValue(value))).catch((err) => send(okFalse(errorMessage5(err, "common request failed"))));
|
|
3550
|
+
}
|
|
3551
|
+
function createCommonService(options = {}) {
|
|
3552
|
+
return {
|
|
3553
|
+
descriptor: COMMON_DESCRIPTOR,
|
|
3554
|
+
handleMessage(windowId, message, send) {
|
|
3555
|
+
const id = message.id ?? "";
|
|
3556
|
+
const context = { windowId };
|
|
3557
|
+
if (message.type === "common.encodeNip19") {
|
|
3558
|
+
const input = message.input;
|
|
3559
|
+
const result = input ? encodeNip19(input) : { ok: false, error: "invalid input" };
|
|
3560
|
+
send({ type: "common.encodeNip19.result", id, ...result });
|
|
3561
|
+
return;
|
|
3562
|
+
}
|
|
3563
|
+
if (message.type === "common.decodeNip19") {
|
|
3564
|
+
const value = message.value;
|
|
3565
|
+
const result = typeof value === "string" ? decodeNip19Value(value) : { ok: false, error: "invalid value" };
|
|
3566
|
+
send({ type: "common.decodeNip19.result", id, ...result });
|
|
3567
|
+
return;
|
|
3568
|
+
}
|
|
3569
|
+
if (message.type === "common.getProfile") {
|
|
3570
|
+
const target = message.target;
|
|
3571
|
+
if (!options.getProfile) {
|
|
3572
|
+
send({ type: "common.getProfile.result", id, ok: false, pubkey: target ?? "", error: "profile lookup unavailable" });
|
|
3573
|
+
return;
|
|
3574
|
+
}
|
|
3575
|
+
settle5(
|
|
3576
|
+
() => options.getProfile(target, context),
|
|
3577
|
+
send,
|
|
3578
|
+
(error) => ({ type: "common.getProfile.result", id, ok: false, pubkey: target ?? "", error }),
|
|
3579
|
+
(result) => ({ type: "common.getProfile.result", id, ...result })
|
|
3580
|
+
);
|
|
3581
|
+
return;
|
|
3582
|
+
}
|
|
3583
|
+
if (message.type === "common.follows") {
|
|
3584
|
+
if (!options.follows) {
|
|
3585
|
+
send({ type: "common.follows.result", id, ok: false, pubkeys: [], error: "follows lookup unavailable" });
|
|
3586
|
+
return;
|
|
3587
|
+
}
|
|
3588
|
+
settle5(
|
|
3589
|
+
() => options.follows(context),
|
|
3590
|
+
send,
|
|
3591
|
+
(error) => ({ type: "common.follows.result", id, ok: false, pubkeys: [], error }),
|
|
3592
|
+
(result) => ({ type: "common.follows.result", id, ...result })
|
|
3593
|
+
);
|
|
3594
|
+
return;
|
|
3595
|
+
}
|
|
3596
|
+
if (message.type === "common.follow") {
|
|
3597
|
+
const pubkeys = message.pubkeys ?? [];
|
|
3598
|
+
settleAction(options.follow, pubkeys, context, send, "common.follow.result", id, "follow unavailable");
|
|
3599
|
+
return;
|
|
3600
|
+
}
|
|
3601
|
+
if (message.type === "common.unfollow") {
|
|
3602
|
+
const pubkeys = message.pubkeys ?? [];
|
|
3603
|
+
settleAction(options.unfollow, pubkeys, context, send, "common.unfollow.result", id, "unfollow unavailable");
|
|
3604
|
+
return;
|
|
3605
|
+
}
|
|
3606
|
+
if (message.type === "common.react") {
|
|
3607
|
+
const m = message;
|
|
3608
|
+
if (!options.react) {
|
|
3609
|
+
send({ type: "common.react.result", id, ok: false, error: "react unavailable" });
|
|
3610
|
+
return;
|
|
3611
|
+
}
|
|
3612
|
+
settle5(
|
|
3613
|
+
() => options.react(m.targetEventId, m.reaction, m.customEmojiHref, context),
|
|
3614
|
+
send,
|
|
3615
|
+
(error) => ({ type: "common.react.result", id, ok: false, error }),
|
|
3616
|
+
(result) => ({ type: "common.react.result", id, ...result })
|
|
3617
|
+
);
|
|
3618
|
+
return;
|
|
3619
|
+
}
|
|
3620
|
+
if (message.type === "common.report") {
|
|
3621
|
+
const m = message;
|
|
3622
|
+
if (!options.report) {
|
|
3623
|
+
send({ type: "common.report.result", id, ok: false, error: "report unavailable" });
|
|
3624
|
+
return;
|
|
3625
|
+
}
|
|
3626
|
+
settle5(
|
|
3627
|
+
() => options.report(m.target, m.reason, m.text, context),
|
|
3628
|
+
send,
|
|
3629
|
+
(error) => ({ type: "common.report.result", id, ok: false, error }),
|
|
3630
|
+
(result) => ({ type: "common.report.result", id, ...result })
|
|
3631
|
+
);
|
|
3632
|
+
return;
|
|
3633
|
+
}
|
|
3634
|
+
send({
|
|
3635
|
+
type: `${message.type}.error`,
|
|
3636
|
+
id,
|
|
3637
|
+
error: `Unknown common method: ${message.type}`
|
|
3638
|
+
});
|
|
3639
|
+
},
|
|
3640
|
+
onWindowDestroyed(_windowId) {
|
|
3641
|
+
}
|
|
3642
|
+
};
|
|
3643
|
+
}
|
|
3644
|
+
function settleAction(action, pubkeys, context, send, resultType, id, unavailable) {
|
|
3645
|
+
if (!action) {
|
|
3646
|
+
send({ type: resultType, id, ok: false, error: unavailable });
|
|
3647
|
+
return;
|
|
3648
|
+
}
|
|
3649
|
+
settle5(
|
|
3650
|
+
() => action(pubkeys, context),
|
|
3651
|
+
send,
|
|
3652
|
+
(error) => ({ type: resultType, id, ok: false, error }),
|
|
3653
|
+
(result) => ({ type: resultType, id, ...result })
|
|
3654
|
+
);
|
|
3655
|
+
}
|
|
2813
3656
|
export {
|
|
2814
3657
|
createAudioService,
|
|
3658
|
+
createBleService,
|
|
2815
3659
|
createBrowserMediaBridge,
|
|
2816
3660
|
createCacheService,
|
|
2817
3661
|
createCatalogIntentResolver,
|
|
3662
|
+
createCommonService,
|
|
2818
3663
|
createConfigService,
|
|
2819
3664
|
createCoordinatedRelay,
|
|
2820
3665
|
createCvmService,
|
|
@@ -2822,6 +3667,8 @@ export {
|
|
|
2822
3667
|
createIdentityService,
|
|
2823
3668
|
createIntentService,
|
|
2824
3669
|
createKeysService,
|
|
3670
|
+
createLinkService,
|
|
3671
|
+
createListsService,
|
|
2825
3672
|
createMediaService,
|
|
2826
3673
|
createNotificationService,
|
|
2827
3674
|
createNotifyService,
|
|
@@ -2829,8 +3676,10 @@ export {
|
|
|
2829
3676
|
createRelayPoolOutboxRouter,
|
|
2830
3677
|
createRelayPoolService,
|
|
2831
3678
|
createResourceService,
|
|
3679
|
+
createSerialService,
|
|
2832
3680
|
createThemeService,
|
|
2833
3681
|
createUploadService,
|
|
3682
|
+
createWebrtcService,
|
|
2834
3683
|
manifestToIntentCatalogEntry
|
|
2835
3684
|
};
|
|
2836
3685
|
//# sourceMappingURL=index.js.map
|