@kehto/services 0.11.0 → 0.12.0

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/index.js CHANGED
@@ -231,6 +231,184 @@ function createNotificationService(options) {
231
231
 
232
232
  // src/identity-service.ts
233
233
  var IDENTITY_SERVICE_VERSION = "1.0.0";
234
+ function sendProviderError(send, result, fallback, err) {
235
+ send({
236
+ ...result,
237
+ error: err?.message ?? fallback
238
+ });
239
+ }
240
+ async function getCurrentPubkey(options) {
241
+ const currentSigner = options.getSigner();
242
+ if (!currentSigner?.getPublicKey) return "";
243
+ try {
244
+ return await currentSigner.getPublicKey() ?? "";
245
+ } catch {
246
+ return "";
247
+ }
248
+ }
249
+ function sendOptionalProviderResult(options, send, fallbackResult, errorFallback, buildResult) {
250
+ if (!buildResult) {
251
+ send(fallbackResult);
252
+ return;
253
+ }
254
+ Promise.resolve(getCurrentPubkey(options)).then((pubkey) => buildResult(pubkey)).then((result) => send(result)).catch((err) => sendProviderError(send, fallbackResult, errorFallback, err));
255
+ }
256
+ function sendIdentityError(send, id, typeBase, error) {
257
+ send({ type: `${typeBase}.error`, id, error });
258
+ }
259
+ function sendSignerError(send, id, typeBase, fallback, err) {
260
+ sendIdentityError(send, id, typeBase, err?.message ?? fallback);
261
+ }
262
+ function handleGetPublicKey(options, id, send) {
263
+ const signer = options.getSigner();
264
+ if (!signer) {
265
+ const result = {
266
+ type: "identity.getPublicKey.result",
267
+ id,
268
+ pubkey: ""
269
+ };
270
+ send(result);
271
+ return;
272
+ }
273
+ Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
274
+ const result = {
275
+ type: "identity.getPublicKey.result",
276
+ id,
277
+ pubkey: pubkey ?? ""
278
+ };
279
+ send(result);
280
+ }).catch((err) => sendSignerError(send, id, "identity.getPublicKey", "getPublicKey failed", err));
281
+ }
282
+ function handleGetRelays(options, id, send) {
283
+ const signer = options.getSigner();
284
+ if (!signer) {
285
+ sendIdentityError(send, id, "identity.getRelays", "no signer configured");
286
+ return;
287
+ }
288
+ Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
289
+ const result = {
290
+ type: "identity.getRelays.result",
291
+ id,
292
+ relays
293
+ };
294
+ send(result);
295
+ }).catch((err) => sendSignerError(send, id, "identity.getRelays", "getRelays failed", err));
296
+ }
297
+ function handleReadProvider(options, id, message, send) {
298
+ switch (message.type) {
299
+ case "identity.getProfile":
300
+ sendOptionalProviderResult(
301
+ options,
302
+ send,
303
+ { type: "identity.getProfile.result", id, profile: null },
304
+ "getProfile failed",
305
+ options.getProfile ? async (pubkey) => ({
306
+ type: "identity.getProfile.result",
307
+ id,
308
+ profile: await options.getProfile(pubkey, message)
309
+ }) : void 0
310
+ );
311
+ return true;
312
+ case "identity.getFollows":
313
+ sendOptionalProviderResult(
314
+ options,
315
+ send,
316
+ { type: "identity.getFollows.result", id, pubkeys: [] },
317
+ "getFollows failed",
318
+ options.getFollows ? async (pubkey) => ({
319
+ type: "identity.getFollows.result",
320
+ id,
321
+ pubkeys: await options.getFollows(pubkey, message)
322
+ }) : void 0
323
+ );
324
+ return true;
325
+ case "identity.getList":
326
+ handleGetList(options, id, message, send);
327
+ return true;
328
+ case "identity.getZaps":
329
+ sendOptionalProviderResult(
330
+ options,
331
+ send,
332
+ { type: "identity.getZaps.result", id, zaps: [] },
333
+ "getZaps failed",
334
+ options.getZaps ? async (pubkey) => ({
335
+ type: "identity.getZaps.result",
336
+ id,
337
+ zaps: await options.getZaps(pubkey, message)
338
+ }) : void 0
339
+ );
340
+ return true;
341
+ case "identity.getMutes":
342
+ sendOptionalProviderResult(
343
+ options,
344
+ send,
345
+ { type: "identity.getMutes.result", id, pubkeys: [] },
346
+ "getMutes failed",
347
+ options.getMutes ? async (pubkey) => ({
348
+ type: "identity.getMutes.result",
349
+ id,
350
+ pubkeys: await options.getMutes(pubkey, message)
351
+ }) : void 0
352
+ );
353
+ return true;
354
+ case "identity.getBlocked":
355
+ sendOptionalProviderResult(
356
+ options,
357
+ send,
358
+ { type: "identity.getBlocked.result", id, pubkeys: [] },
359
+ "getBlocked failed",
360
+ options.getBlocked ? async (pubkey) => ({
361
+ type: "identity.getBlocked.result",
362
+ id,
363
+ pubkeys: await options.getBlocked(pubkey, message)
364
+ }) : void 0
365
+ );
366
+ return true;
367
+ case "identity.getBadges":
368
+ sendOptionalProviderResult(
369
+ options,
370
+ send,
371
+ { type: "identity.getBadges.result", id, badges: [] },
372
+ "getBadges failed",
373
+ options.getBadges ? async (pubkey) => ({
374
+ type: "identity.getBadges.result",
375
+ id,
376
+ badges: await options.getBadges(pubkey, message)
377
+ }) : void 0
378
+ );
379
+ return true;
380
+ default:
381
+ return false;
382
+ }
383
+ }
384
+ function handleGetList(options, id, message, send) {
385
+ sendOptionalProviderResult(
386
+ options,
387
+ send,
388
+ { type: "identity.getList.result", id, entries: [] },
389
+ "getList failed",
390
+ options.getList ? async (pubkey) => ({
391
+ type: "identity.getList.result",
392
+ id,
393
+ entries: await options.getList(message.listType, pubkey, message)
394
+ }) : void 0
395
+ );
396
+ }
397
+ function handleIdentityServiceMessage(options, message, send) {
398
+ const id = message.id ?? "";
399
+ switch (message.type) {
400
+ case "identity.getPublicKey":
401
+ handleGetPublicKey(options, id, send);
402
+ return;
403
+ case "identity.getRelays":
404
+ handleGetRelays(options, id, send);
405
+ return;
406
+ default:
407
+ if (!handleReadProvider(options, id, message, send)) {
408
+ sendIdentityError(send, id, message.type, `Unknown identity method: ${message.type}`);
409
+ }
410
+ }
411
+ }
234
412
  function createIdentityService(options) {
235
413
  return {
236
414
  descriptor: {
@@ -239,116 +417,7 @@ function createIdentityService(options) {
239
417
  description: "NIP-5D identity NAP reference handler (9 read-only identity queries)"
240
418
  },
241
419
  handleMessage(_windowId, message, send) {
242
- const id = message.id ?? "";
243
- function sendError(typeBase, error) {
244
- send({ type: `${typeBase}.error`, id, error });
245
- }
246
- function sendSignerError(typeBase, fallback, err) {
247
- sendError(typeBase, err?.message ?? fallback);
248
- }
249
- const signer = options.getSigner();
250
- switch (message.type) {
251
- case "identity.getPublicKey": {
252
- if (!signer) {
253
- const result = {
254
- type: "identity.getPublicKey.result",
255
- id,
256
- pubkey: ""
257
- };
258
- send(result);
259
- return;
260
- }
261
- Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
262
- const result = {
263
- type: "identity.getPublicKey.result",
264
- id,
265
- pubkey: pubkey ?? ""
266
- };
267
- send(result);
268
- }).catch((err) => sendSignerError("identity.getPublicKey", "getPublicKey failed", err));
269
- return;
270
- }
271
- case "identity.getRelays": {
272
- if (!signer) {
273
- sendError("identity.getRelays", "no signer configured");
274
- return;
275
- }
276
- Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
277
- const result = {
278
- type: "identity.getRelays.result",
279
- id,
280
- relays
281
- };
282
- send(result);
283
- }).catch((err) => sendSignerError("identity.getRelays", "getRelays failed", err));
284
- return;
285
- }
286
- case "identity.getProfile": {
287
- const result = {
288
- type: "identity.getProfile.result",
289
- id,
290
- profile: null
291
- };
292
- send(result);
293
- return;
294
- }
295
- case "identity.getFollows": {
296
- const result = {
297
- type: "identity.getFollows.result",
298
- id,
299
- pubkeys: []
300
- };
301
- send(result);
302
- return;
303
- }
304
- case "identity.getList": {
305
- const result = {
306
- type: "identity.getList.result",
307
- id,
308
- entries: []
309
- };
310
- send(result);
311
- return;
312
- }
313
- case "identity.getZaps": {
314
- const result = {
315
- type: "identity.getZaps.result",
316
- id,
317
- zaps: []
318
- };
319
- send(result);
320
- return;
321
- }
322
- case "identity.getMutes": {
323
- const result = {
324
- type: "identity.getMutes.result",
325
- id,
326
- pubkeys: []
327
- };
328
- send(result);
329
- return;
330
- }
331
- case "identity.getBlocked": {
332
- const result = {
333
- type: "identity.getBlocked.result",
334
- id,
335
- pubkeys: []
336
- };
337
- send(result);
338
- return;
339
- }
340
- case "identity.getBadges": {
341
- const result = {
342
- type: "identity.getBadges.result",
343
- id,
344
- badges: []
345
- };
346
- send(result);
347
- return;
348
- }
349
- default:
350
- sendError(message.type, `Unknown identity method: ${message.type}`);
351
- }
420
+ handleIdentityServiceMessage(options, message, send);
352
421
  },
353
422
  // Identity service has no per-window state to clean up.
354
423
  onWindowDestroyed(_windowId) {
@@ -383,7 +452,8 @@ function createRelayPoolService(options) {
383
452
  send({ type: "relay.eose", subId });
384
453
  return;
385
454
  }
386
- const relayUrls = options.selectRelayTier(filters);
455
+ const relayHint = typeof relayMessage.relay === "string" && relayMessage.relay.length > 0 ? relayMessage.relay : void 0;
456
+ const relayUrls = relayHint ? [relayHint] : options.selectRelayTier(filters);
387
457
  let eoseSent = false;
388
458
  const eoseTimer = setTimeout(() => {
389
459
  if (!eoseSent) {
@@ -563,7 +633,8 @@ function createCoordinatedRelay(options) {
563
633
  maybeSendEose(subKey, subId, send);
564
634
  }
565
635
  }, timeoutMs);
566
- const relayUrls = options.relayPool.selectRelayTier(filters);
636
+ const relayHint = typeof relayMessage.relay === "string" && relayMessage.relay.length > 0 ? relayMessage.relay : void 0;
637
+ const relayUrls = relayHint ? [relayHint] : options.relayPool.selectRelayTier(filters);
567
638
  tracked.relayHandle = options.relayPool.subscribe(filters, (item) => {
568
639
  if (item === "EOSE") {
569
640
  clearTimeout(tracked.eoseTimer);
@@ -1579,19 +1650,35 @@ function untrackRequest(state, requestId) {
1579
1650
  state.perWindow.get(entry.windowId)?.delete(requestId);
1580
1651
  }
1581
1652
  }
1582
- function sendResourceError(send, requestId, code, message) {
1653
+ function sendResourceError(send, requestId, code, message, error = toResourceError(code), type = "resource.bytes.error") {
1583
1654
  send({
1584
- type: "resource.bytes.error",
1655
+ type,
1656
+ id: requestId,
1585
1657
  requestId,
1658
+ error,
1586
1659
  code,
1587
1660
  message
1588
1661
  });
1589
1662
  }
1590
- function parseResourceUrl(send, requestId, url) {
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) {
1591
1679
  try {
1592
1680
  return new URL(url);
1593
1681
  } catch {
1594
- sendResourceError(send, requestId, "invalid-url", `invalid URL: ${url}`);
1595
1682
  return null;
1596
1683
  }
1597
1684
  }
@@ -1602,45 +1689,138 @@ function collectResponseHeaders(response) {
1602
1689
  });
1603
1690
  return headers;
1604
1691
  }
1605
- async function handleBytes(options, state, windowId, msg, send) {
1606
- const { requestId, url, init } = msg;
1607
- const identity = options.resolveIdentity(windowId);
1608
- if (!identity) {
1609
- sendResourceError(send, requestId, "denied", "napplet identity not resolvable");
1610
- return;
1611
- }
1612
- const parsedUrl = parseResourceUrl(send, requestId, url);
1613
- if (!parsedUrl) return;
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}`);
1614
1715
  const origin = parsedUrl.origin;
1615
1716
  const grants = options.getConnectGrants(identity.dTag, identity.aggregateHash);
1616
1717
  if (!options.isOriginGranted(origin, grants)) {
1617
- sendResourceError(send, requestId, "denied", `origin ${origin} not granted`);
1618
- return;
1718
+ return {
1719
+ ok: false,
1720
+ url,
1721
+ error: "blocked-by-policy",
1722
+ code: "denied",
1723
+ message: `origin ${origin} not granted`
1724
+ };
1619
1725
  }
1620
- const controller = new AbortController();
1621
- trackRequest(state, requestId, windowId, controller);
1622
1726
  try {
1623
1727
  const response = await options.fetch(url, {
1624
1728
  method: init?.method,
1625
1729
  headers: init?.headers ? { ...init.headers } : void 0,
1626
- signal: controller.signal
1730
+ signal
1627
1731
  });
1628
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
+ }
1629
1770
  send({
1630
1771
  type: "resource.bytes.result",
1772
+ id: requestId,
1631
1773
  requestId,
1632
- status: response.status,
1633
- headers: collectResponseHeaders(response),
1634
- bodyBase64: arrayBufferToBase64(buffer)
1774
+ blob: item.blob,
1775
+ mime: item.mime,
1776
+ status: item.status,
1777
+ headers: item.headers,
1778
+ bodyBase64: item.bodyBase64
1635
1779
  });
1636
- } catch (err) {
1637
- const isAbort = controller.signal.aborted || err instanceof Error && (err.name === "AbortError" || err.name === "DOMException");
1638
- sendResourceError(
1639
- send,
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,
1640
1821
  requestId,
1641
- isAbort ? "canceled" : "network-error",
1642
- err instanceof Error ? err.message : String(err)
1643
- );
1822
+ items
1823
+ });
1644
1824
  } finally {
1645
1825
  untrackRequest(state, requestId);
1646
1826
  }
@@ -1680,13 +1860,24 @@ function createResourceService(options) {
1680
1860
  switch (message.type) {
1681
1861
  case "resource.bytes": {
1682
1862
  const m = message;
1683
- handleBytes(options, state, windowId, m, send).catch(() => {
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(() => {
1684
1874
  });
1685
1875
  return;
1686
1876
  }
1687
1877
  case "resource.cancel": {
1688
1878
  const m = message;
1689
- handleCancel(state, m.requestId);
1879
+ const requestId = requestIdFromMessage(m);
1880
+ if (requestId) handleCancel(state, requestId);
1690
1881
  return;
1691
1882
  }
1692
1883
  default:
@@ -2419,7 +2610,7 @@ function createIntentService(options) {
2419
2610
  send({ type: "intent.changed", availability });
2420
2611
  }
2421
2612
  });
2422
- function settle(call, send, resultType, id, onValue) {
2613
+ function settle6(call, send, resultType, id, onValue) {
2423
2614
  let pending;
2424
2615
  try {
2425
2616
  pending = Promise.resolve(call());
@@ -2437,7 +2628,7 @@ function createIntentService(options) {
2437
2628
  send({ type: "intent.invoke.result", id, error: "invalid request" });
2438
2629
  return;
2439
2630
  }
2440
- settle(
2631
+ settle6(
2441
2632
  () => resolver.invoke(request, { windowId }),
2442
2633
  send,
2443
2634
  "intent.invoke.result",
@@ -2453,7 +2644,7 @@ function createIntentService(options) {
2453
2644
  return;
2454
2645
  }
2455
2646
  const archetype = m.archetype;
2456
- settle(
2647
+ settle6(
2457
2648
  () => resolver.available(archetype),
2458
2649
  send,
2459
2650
  "intent.available.result",
@@ -2464,7 +2655,7 @@ function createIntentService(options) {
2464
2655
  function handleHandlers(msg, send) {
2465
2656
  const m = msg;
2466
2657
  const id = m.id ?? "";
2467
- settle(
2658
+ settle6(
2468
2659
  () => resolver.handlers(),
2469
2660
  send,
2470
2661
  "intent.handlers.result",
@@ -2739,11 +2930,736 @@ function toErrorMessage5(err) {
2739
2930
  if (typeof err === "string") return err;
2740
2931
  return "cvm request failed";
2741
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
+ }
2742
3656
  export {
2743
3657
  createAudioService,
3658
+ createBleService,
2744
3659
  createBrowserMediaBridge,
2745
3660
  createCacheService,
2746
3661
  createCatalogIntentResolver,
3662
+ createCommonService,
2747
3663
  createConfigService,
2748
3664
  createCoordinatedRelay,
2749
3665
  createCvmService,
@@ -2751,6 +3667,8 @@ export {
2751
3667
  createIdentityService,
2752
3668
  createIntentService,
2753
3669
  createKeysService,
3670
+ createLinkService,
3671
+ createListsService,
2754
3672
  createMediaService,
2755
3673
  createNotificationService,
2756
3674
  createNotifyService,
@@ -2758,8 +3676,10 @@ export {
2758
3676
  createRelayPoolOutboxRouter,
2759
3677
  createRelayPoolService,
2760
3678
  createResourceService,
3679
+ createSerialService,
2761
3680
  createThemeService,
2762
3681
  createUploadService,
3682
+ createWebrtcService,
2763
3683
  manifestToIntentCatalogEntry
2764
3684
  };
2765
3685
  //# sourceMappingURL=index.js.map