@kehto/services 0.13.2 → 0.15.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.d.ts +49 -15
- package/dist/index.js +208 -122
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -231,9 +231,9 @@ function createNotificationService(options) {
|
|
|
231
231
|
|
|
232
232
|
// src/identity-service.ts
|
|
233
233
|
var IDENTITY_SERVICE_VERSION = "1.0.0";
|
|
234
|
-
function sendProviderError(send,
|
|
234
|
+
function sendProviderError(send, result2, fallback, err2) {
|
|
235
235
|
send({
|
|
236
|
-
...
|
|
236
|
+
...result2,
|
|
237
237
|
error: err2?.message ?? fallback
|
|
238
238
|
});
|
|
239
239
|
}
|
|
@@ -251,7 +251,7 @@ function sendOptionalProviderResult(options, send, fallbackResult, errorFallback
|
|
|
251
251
|
send(fallbackResult);
|
|
252
252
|
return;
|
|
253
253
|
}
|
|
254
|
-
Promise.resolve(getCurrentPubkey(options)).then((pubkey) => buildResult(pubkey)).then((
|
|
254
|
+
Promise.resolve(getCurrentPubkey(options)).then((pubkey) => buildResult(pubkey)).then((result2) => send(result2)).catch((err2) => sendProviderError(send, fallbackResult, errorFallback, err2));
|
|
255
255
|
}
|
|
256
256
|
function sendIdentityError(send, id, typeBase, error) {
|
|
257
257
|
send({ type: `${typeBase}.error`, id, error });
|
|
@@ -262,21 +262,21 @@ function sendSignerError(send, id, typeBase, fallback, err2) {
|
|
|
262
262
|
function handleGetPublicKey(options, id, send) {
|
|
263
263
|
const signer = options.getSigner();
|
|
264
264
|
if (!signer) {
|
|
265
|
-
const
|
|
265
|
+
const result2 = {
|
|
266
266
|
type: "identity.getPublicKey.result",
|
|
267
267
|
id,
|
|
268
268
|
pubkey: ""
|
|
269
269
|
};
|
|
270
|
-
send(
|
|
270
|
+
send(result2);
|
|
271
271
|
return;
|
|
272
272
|
}
|
|
273
273
|
Promise.resolve(signer.getPublicKey?.()).then((pubkey) => {
|
|
274
|
-
const
|
|
274
|
+
const result2 = {
|
|
275
275
|
type: "identity.getPublicKey.result",
|
|
276
276
|
id,
|
|
277
277
|
pubkey: pubkey ?? ""
|
|
278
278
|
};
|
|
279
|
-
send(
|
|
279
|
+
send(result2);
|
|
280
280
|
}).catch((err2) => sendSignerError(send, id, "identity.getPublicKey", "getPublicKey failed", err2));
|
|
281
281
|
}
|
|
282
282
|
function handleGetRelays(options, id, send) {
|
|
@@ -286,12 +286,12 @@ function handleGetRelays(options, id, send) {
|
|
|
286
286
|
return;
|
|
287
287
|
}
|
|
288
288
|
Promise.resolve(signer.getRelays?.() ?? {}).then((relays) => {
|
|
289
|
-
const
|
|
289
|
+
const result2 = {
|
|
290
290
|
type: "identity.getRelays.result",
|
|
291
291
|
id,
|
|
292
292
|
relays
|
|
293
293
|
};
|
|
294
|
-
send(
|
|
294
|
+
send(result2);
|
|
295
295
|
}).catch((err2) => sendSignerError(send, id, "identity.getRelays", "getRelays failed", err2));
|
|
296
296
|
}
|
|
297
297
|
function handleReadProvider(options, id, message, send) {
|
|
@@ -426,6 +426,7 @@ function createIdentityService(options) {
|
|
|
426
426
|
}
|
|
427
427
|
|
|
428
428
|
// src/relay-pool-service.ts
|
|
429
|
+
import { createRelayEventResultWithHints } from "@kehto/runtime";
|
|
429
430
|
var EOSE_FALLBACK_MS = 15e3;
|
|
430
431
|
function createRelayPoolService(options) {
|
|
431
432
|
const tracked = /* @__PURE__ */ new Map();
|
|
@@ -470,7 +471,7 @@ function createRelayPoolService(options) {
|
|
|
470
471
|
}
|
|
471
472
|
return;
|
|
472
473
|
}
|
|
473
|
-
send({ type: "relay.event", subId,
|
|
474
|
+
send({ type: "relay.event", subId, result: createRelayEventResultWithHints(item, relayUrls2) });
|
|
474
475
|
}, relayUrls2);
|
|
475
476
|
tracked.set(subKey, { handle, eoseTimer });
|
|
476
477
|
return;
|
|
@@ -516,6 +517,7 @@ function createRelayPoolService(options) {
|
|
|
516
517
|
}
|
|
517
518
|
|
|
518
519
|
// src/cache-service.ts
|
|
520
|
+
import { createRelayEventResult } from "@kehto/runtime";
|
|
519
521
|
function createCacheService(options) {
|
|
520
522
|
return {
|
|
521
523
|
descriptor: {
|
|
@@ -535,7 +537,7 @@ function createCacheService(options) {
|
|
|
535
537
|
}
|
|
536
538
|
options.query(filters).then((events) => {
|
|
537
539
|
for (const event of events) {
|
|
538
|
-
send({ type: "relay.event", subId, event });
|
|
540
|
+
send({ type: "relay.event", subId, result: createRelayEventResult(event) });
|
|
539
541
|
}
|
|
540
542
|
send({ type: "relay.eose", subId });
|
|
541
543
|
}).catch(() => {
|
|
@@ -560,7 +562,94 @@ function createCacheService(options) {
|
|
|
560
562
|
};
|
|
561
563
|
}
|
|
562
564
|
|
|
565
|
+
// src/count-service.ts
|
|
566
|
+
var DEFAULT_MAX_FILTERS = 16;
|
|
567
|
+
function createCountService(options) {
|
|
568
|
+
return {
|
|
569
|
+
descriptor: {
|
|
570
|
+
name: "count",
|
|
571
|
+
version: "1.0.0",
|
|
572
|
+
description: "Runtime-mediated NIP-01 filter counts"
|
|
573
|
+
},
|
|
574
|
+
handleMessage(windowId, message, send) {
|
|
575
|
+
if (message.type !== "count.query") return;
|
|
576
|
+
const countMessage = message;
|
|
577
|
+
const id = typeof countMessage.id === "string" ? countMessage.id : "";
|
|
578
|
+
const filters = countMessage.filters;
|
|
579
|
+
if (!isValidFilterArray(filters)) {
|
|
580
|
+
send(result(id, { ok: false, error: "invalid-filter", reason: "count.query requires a non-empty filters array" }));
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
const maxFilters = options.maxFilters ?? DEFAULT_MAX_FILTERS;
|
|
584
|
+
if (filters.length > maxFilters) {
|
|
585
|
+
send(result(id, { ok: false, error: "too-expensive", reason: `count.query accepts at most ${maxFilters} filters` }));
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
for (let i = 0; i < filters.length; i++) {
|
|
589
|
+
const supported = options.isFilterSupported?.(filters[i], i) ?? true;
|
|
590
|
+
if (supported !== true) {
|
|
591
|
+
send(result(id, {
|
|
592
|
+
ok: false,
|
|
593
|
+
error: "unsupported-filter",
|
|
594
|
+
reason: typeof supported === "string" ? supported : `filter ${i} is not supported by this count backend`
|
|
595
|
+
}));
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
const request = {
|
|
600
|
+
filters,
|
|
601
|
+
windowId,
|
|
602
|
+
...isPlainObject(countMessage.options) ? { options: countMessage.options } : {}
|
|
603
|
+
};
|
|
604
|
+
Promise.resolve(options.count(request)).then((countResult) => {
|
|
605
|
+
send(result(id, normalizeCountResult(countResult)));
|
|
606
|
+
}).catch((error) => {
|
|
607
|
+
send(result(id, {
|
|
608
|
+
ok: false,
|
|
609
|
+
error: "count-unavailable",
|
|
610
|
+
reason: error instanceof Error ? error.message : "count backend failed"
|
|
611
|
+
}));
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
function result(id, value) {
|
|
617
|
+
return {
|
|
618
|
+
type: "count.query.result",
|
|
619
|
+
id,
|
|
620
|
+
ok: value.ok,
|
|
621
|
+
...typeof value.count === "number" ? { count: value.count } : {},
|
|
622
|
+
...typeof value.approximate === "boolean" ? { approximate: value.approximate } : {},
|
|
623
|
+
...typeof value.hll === "string" ? { hll: value.hll } : {},
|
|
624
|
+
...Array.isArray(value.relays) ? { relays: value.relays.filter((relay) => typeof relay === "string") } : {},
|
|
625
|
+
...typeof value.error === "string" ? { error: value.error } : {},
|
|
626
|
+
...typeof value.reason === "string" ? { reason: value.reason } : {}
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
function normalizeCountResult(value) {
|
|
630
|
+
if (typeof value === "number") {
|
|
631
|
+
return Number.isFinite(value) && value >= 0 ? { ok: true, count: Math.floor(value), approximate: false } : { ok: false, error: "count-unavailable", reason: "count backend returned an invalid count" };
|
|
632
|
+
}
|
|
633
|
+
const count = typeof value.count === "number" && Number.isFinite(value.count) && value.count >= 0 ? Math.floor(value.count) : void 0;
|
|
634
|
+
return {
|
|
635
|
+
ok: value.ok === true,
|
|
636
|
+
...count !== void 0 ? { count } : {},
|
|
637
|
+
...typeof value.approximate === "boolean" ? { approximate: value.approximate } : {},
|
|
638
|
+
...typeof value.hll === "string" ? { hll: value.hll } : {},
|
|
639
|
+
...Array.isArray(value.relays) ? { relays: value.relays } : {},
|
|
640
|
+
...typeof value.error === "string" ? { error: value.error } : {},
|
|
641
|
+
...typeof value.reason === "string" ? { reason: value.reason } : {}
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function isValidFilterArray(value) {
|
|
645
|
+
return Array.isArray(value) && value.length > 0 && value.every((filter) => isPlainObject(filter));
|
|
646
|
+
}
|
|
647
|
+
function isPlainObject(value) {
|
|
648
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
649
|
+
}
|
|
650
|
+
|
|
563
651
|
// src/coordinated-relay.ts
|
|
652
|
+
import { createRelayEventResult as createRelayEventResult2, createRelayEventResultWithHints as createRelayEventResultWithHints2 } from "@kehto/runtime";
|
|
564
653
|
var DEFAULT_EOSE_TIMEOUT_MS = 15e3;
|
|
565
654
|
function createCoordinatedRelay(options) {
|
|
566
655
|
const timeoutMs = options.eoseTimeoutMs ?? DEFAULT_EOSE_TIMEOUT_MS;
|
|
@@ -583,10 +672,13 @@ function createCoordinatedRelay(options) {
|
|
|
583
672
|
handleMessage(windowId, message, send) {
|
|
584
673
|
const relayMessage = message;
|
|
585
674
|
if (message.type === "relay.subscribe") {
|
|
586
|
-
let deliver2 = function(event) {
|
|
675
|
+
let deliver2 = function(event, relayHints) {
|
|
587
676
|
if (tracked.seenIds.has(event.id)) return;
|
|
588
677
|
tracked.seenIds.add(event.id);
|
|
589
|
-
if (subs.has(subKey))
|
|
678
|
+
if (subs.has(subKey)) {
|
|
679
|
+
const result2 = relayHints ? createRelayEventResultWithHints2(event, relayHints) : createRelayEventResult2(event);
|
|
680
|
+
send({ type: "relay.event", subId, result: result2 });
|
|
681
|
+
}
|
|
590
682
|
};
|
|
591
683
|
var deliver = deliver2;
|
|
592
684
|
const subId = relayMessage.subId;
|
|
@@ -642,7 +734,7 @@ function createCoordinatedRelay(options) {
|
|
|
642
734
|
maybeSendEose(subKey, subId, send);
|
|
643
735
|
return;
|
|
644
736
|
}
|
|
645
|
-
deliver2(item);
|
|
737
|
+
deliver2(item, relayUrls2);
|
|
646
738
|
if (cacheAvailable) {
|
|
647
739
|
try {
|
|
648
740
|
options.cache.store(item);
|
|
@@ -807,13 +899,13 @@ function createKeysService(options = {}) {
|
|
|
807
899
|
return;
|
|
808
900
|
}
|
|
809
901
|
}
|
|
810
|
-
const
|
|
902
|
+
const result2 = {
|
|
811
903
|
type: "keys.registerAction.result",
|
|
812
904
|
id: m.id,
|
|
813
905
|
actionId: m.action.id,
|
|
814
906
|
...m.action.defaultKey ? { binding: m.action.defaultKey } : {}
|
|
815
907
|
};
|
|
816
|
-
send(
|
|
908
|
+
send(result2);
|
|
817
909
|
return;
|
|
818
910
|
}
|
|
819
911
|
case "keys.unregisterAction": {
|
|
@@ -954,13 +1046,13 @@ function createKeysService(options = {}) {
|
|
|
954
1046
|
return;
|
|
955
1047
|
}
|
|
956
1048
|
}
|
|
957
|
-
const
|
|
1049
|
+
const result2 = {
|
|
958
1050
|
type: "keys.registerAction.result",
|
|
959
1051
|
id: m.id,
|
|
960
1052
|
actionId: m.action.id,
|
|
961
1053
|
...m.action.defaultKey ? { binding: m.action.defaultKey } : {}
|
|
962
1054
|
};
|
|
963
|
-
send(
|
|
1055
|
+
send(result2);
|
|
964
1056
|
return;
|
|
965
1057
|
}
|
|
966
1058
|
case "keys.unregisterAction": {
|
|
@@ -1391,12 +1483,12 @@ function createNotifyService(options = {}) {
|
|
|
1391
1483
|
case "notify.send": {
|
|
1392
1484
|
const m = message;
|
|
1393
1485
|
options.onSend?.(windowId, m);
|
|
1394
|
-
const
|
|
1486
|
+
const result2 = {
|
|
1395
1487
|
type: "notify.send.result",
|
|
1396
1488
|
id: m.id,
|
|
1397
1489
|
notificationId: gen()
|
|
1398
1490
|
};
|
|
1399
|
-
send(
|
|
1491
|
+
send(result2);
|
|
1400
1492
|
return;
|
|
1401
1493
|
}
|
|
1402
1494
|
case "notify.dismiss":
|
|
@@ -1405,12 +1497,12 @@ function createNotifyService(options = {}) {
|
|
|
1405
1497
|
return;
|
|
1406
1498
|
case "notify.permission.request": {
|
|
1407
1499
|
const m = message;
|
|
1408
|
-
const
|
|
1500
|
+
const result2 = {
|
|
1409
1501
|
type: "notify.permission.result",
|
|
1410
1502
|
id: m.id,
|
|
1411
1503
|
granted: defaultGrant
|
|
1412
1504
|
};
|
|
1413
|
-
send(
|
|
1505
|
+
send(result2);
|
|
1414
1506
|
return;
|
|
1415
1507
|
}
|
|
1416
1508
|
default: {
|
|
@@ -1451,12 +1543,12 @@ function createThemeService(options = {}) {
|
|
|
1451
1543
|
handleMessage(_windowId, message, send) {
|
|
1452
1544
|
const id = message.id ?? "";
|
|
1453
1545
|
if (message.type === "theme.get") {
|
|
1454
|
-
const
|
|
1546
|
+
const result2 = {
|
|
1455
1547
|
type: "theme.get.result",
|
|
1456
1548
|
id,
|
|
1457
1549
|
theme: currentTheme
|
|
1458
1550
|
};
|
|
1459
|
-
send(
|
|
1551
|
+
send(result2);
|
|
1460
1552
|
return;
|
|
1461
1553
|
}
|
|
1462
1554
|
send({
|
|
@@ -1580,14 +1672,14 @@ function createConfigService(options) {
|
|
|
1580
1672
|
case "config.registerSchema": {
|
|
1581
1673
|
const m = message;
|
|
1582
1674
|
const validation = options.registerSchema ? options.registerSchema(windowId, m.schema, m.version) : validateCoreSubset(m.schema);
|
|
1583
|
-
const
|
|
1675
|
+
const result2 = validation.ok ? { type: "config.registerSchema.result", id: m.id, ok: true } : {
|
|
1584
1676
|
type: "config.registerSchema.result",
|
|
1585
1677
|
id: m.id,
|
|
1586
1678
|
ok: false,
|
|
1587
1679
|
code: validation.code,
|
|
1588
1680
|
error: validation.error
|
|
1589
1681
|
};
|
|
1590
|
-
send(
|
|
1682
|
+
send(result2);
|
|
1591
1683
|
return;
|
|
1592
1684
|
}
|
|
1593
1685
|
case "config.openSettings": {
|
|
@@ -1958,45 +2050,42 @@ function buildEventQuery(eventId, eventOptions) {
|
|
|
1958
2050
|
if (eventOptions?.timeoutMs !== void 0) queryOptions.timeoutMs = eventOptions.timeoutMs;
|
|
1959
2051
|
return { filter, queryOptions };
|
|
1960
2052
|
}
|
|
1961
|
-
function eventResultFromQuery(eventId,
|
|
1962
|
-
const
|
|
1963
|
-
const eventResult = {
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
if (
|
|
1967
|
-
if (
|
|
1968
|
-
else if (result.error !== void 0) eventResult.error = result.error;
|
|
1969
|
-
if (result.incomplete !== void 0) eventResult.incomplete = result.incomplete;
|
|
2053
|
+
function eventResultFromQuery(eventId, result2) {
|
|
2054
|
+
const relayResult = result2.events.find((candidate) => candidate.event.id === eventId);
|
|
2055
|
+
const eventResult = {};
|
|
2056
|
+
if (relayResult) eventResult.result = relayResult;
|
|
2057
|
+
if (!relayResult) eventResult.error = result2.error ?? "not found";
|
|
2058
|
+
else if (result2.error !== void 0) eventResult.error = result2.error;
|
|
2059
|
+
if (result2.incomplete !== void 0) eventResult.incomplete = result2.incomplete;
|
|
1970
2060
|
return eventResult;
|
|
1971
2061
|
}
|
|
1972
2062
|
function fallbackGetEvent(router, eventId, eventOptions) {
|
|
1973
2063
|
const { filter, queryOptions } = buildEventQuery(eventId, eventOptions);
|
|
1974
|
-
return router.query([filter], queryOptions).then((
|
|
2064
|
+
return router.query([filter], queryOptions).then((result2) => eventResultFromQuery(eventId, result2));
|
|
1975
2065
|
}
|
|
1976
|
-
function sendEventResult(id, eventId,
|
|
1977
|
-
if (result
|
|
1978
|
-
send({ type: "outbox.getEvent.result", id,
|
|
2066
|
+
function sendEventResult(id, eventId, result2, send) {
|
|
2067
|
+
if (result2.result && result2.result.event.id !== eventId) {
|
|
2068
|
+
send({ type: "outbox.getEvent.result", id, error: "not found" });
|
|
1979
2069
|
return;
|
|
1980
2070
|
}
|
|
1981
2071
|
send({
|
|
1982
2072
|
type: "outbox.getEvent.result",
|
|
1983
2073
|
id,
|
|
1984
|
-
...result
|
|
1985
|
-
|
|
1986
|
-
...
|
|
1987
|
-
...result.error === void 0 ? {} : { error: result.error }
|
|
2074
|
+
...result2.result === void 0 ? {} : { result: result2.result },
|
|
2075
|
+
...result2.incomplete === void 0 ? {} : { incomplete: result2.incomplete },
|
|
2076
|
+
...result2.error === void 0 ? {} : { error: result2.error }
|
|
1988
2077
|
});
|
|
1989
2078
|
}
|
|
1990
2079
|
function handleGetEvent(router, msg, send) {
|
|
1991
2080
|
const m = msg;
|
|
1992
2081
|
const id = m.id ?? "";
|
|
1993
2082
|
if (typeof m.eventId !== "string" || m.eventId.length === 0) {
|
|
1994
|
-
send({ type: "outbox.getEvent.result", id,
|
|
2083
|
+
send({ type: "outbox.getEvent.result", id, error: "invalid filter" });
|
|
1995
2084
|
return;
|
|
1996
2085
|
}
|
|
1997
2086
|
const getEvent = router.getEvent ?? ((eventId, eventOptions) => fallbackGetEvent(router, eventId, eventOptions));
|
|
1998
|
-
void getEvent(m.eventId, m.options).then((
|
|
1999
|
-
(err2) => send({ type: "outbox.getEvent.result", id,
|
|
2087
|
+
void getEvent(m.eventId, m.options).then((result2) => sendEventResult(id, m.eventId, result2, send)).catch(
|
|
2088
|
+
(err2) => send({ type: "outbox.getEvent.result", id, error: toErrorMessage(err2) })
|
|
2000
2089
|
);
|
|
2001
2090
|
}
|
|
2002
2091
|
function createOutboxService(options) {
|
|
@@ -2010,20 +2099,19 @@ function createOutboxService(options) {
|
|
|
2010
2099
|
const id = m.id ?? "";
|
|
2011
2100
|
const filters = normalizeFilters(m.filters);
|
|
2012
2101
|
if (!filters) {
|
|
2013
|
-
send({ type: "outbox.query.result", id, events: [],
|
|
2102
|
+
send({ type: "outbox.query.result", id, events: [], error: "invalid filter" });
|
|
2014
2103
|
return;
|
|
2015
2104
|
}
|
|
2016
2105
|
void router.query(filters, m.options).then(
|
|
2017
|
-
(
|
|
2106
|
+
(result2) => send({
|
|
2018
2107
|
type: "outbox.query.result",
|
|
2019
2108
|
id,
|
|
2020
|
-
events:
|
|
2021
|
-
|
|
2022
|
-
...
|
|
2023
|
-
...result.error === void 0 ? {} : { error: result.error }
|
|
2109
|
+
events: result2.events,
|
|
2110
|
+
...result2.incomplete === void 0 ? {} : { incomplete: result2.incomplete },
|
|
2111
|
+
...result2.error === void 0 ? {} : { error: result2.error }
|
|
2024
2112
|
})
|
|
2025
2113
|
).catch(
|
|
2026
|
-
(err2) => send({ type: "outbox.query.result", id, events: [],
|
|
2114
|
+
(err2) => send({ type: "outbox.query.result", id, events: [], error: toErrorMessage(err2) })
|
|
2027
2115
|
);
|
|
2028
2116
|
}
|
|
2029
2117
|
function handleSubscribe(windowId, msg, send) {
|
|
@@ -2039,8 +2127,7 @@ function createOutboxService(options) {
|
|
|
2039
2127
|
return;
|
|
2040
2128
|
}
|
|
2041
2129
|
const sink = {
|
|
2042
|
-
event: (
|
|
2043
|
-
eose: () => send({ type: "outbox.eose", subId }),
|
|
2130
|
+
event: (result2) => send({ type: "outbox.event", subId, result: result2 }),
|
|
2044
2131
|
closed: (reason) => {
|
|
2045
2132
|
subscriptions.delete(subKey);
|
|
2046
2133
|
send({ type: "outbox.closed", subId, ...reason === void 0 ? {} : { reason } });
|
|
@@ -2065,14 +2152,14 @@ function createOutboxService(options) {
|
|
|
2065
2152
|
return;
|
|
2066
2153
|
}
|
|
2067
2154
|
void router.publish(m.event, m.options).then(
|
|
2068
|
-
(
|
|
2155
|
+
(result2) => send({
|
|
2069
2156
|
type: "outbox.publish.result",
|
|
2070
2157
|
id,
|
|
2071
|
-
ok:
|
|
2072
|
-
...
|
|
2073
|
-
...
|
|
2074
|
-
...
|
|
2075
|
-
...
|
|
2158
|
+
ok: result2.ok,
|
|
2159
|
+
...result2.event === void 0 ? {} : { event: result2.event },
|
|
2160
|
+
...result2.eventId === void 0 ? {} : { eventId: result2.eventId },
|
|
2161
|
+
...result2.relays === void 0 ? {} : { relays: result2.relays },
|
|
2162
|
+
...result2.error === void 0 ? {} : { error: result2.error }
|
|
2076
2163
|
})
|
|
2077
2164
|
).catch(
|
|
2078
2165
|
(err2) => send({ type: "outbox.publish.result", id, ok: false, error: toErrorMessage(err2) })
|
|
@@ -2133,6 +2220,7 @@ function toErrorMessage(err2) {
|
|
|
2133
2220
|
}
|
|
2134
2221
|
|
|
2135
2222
|
// src/relay-pool-outbox-router.ts
|
|
2223
|
+
import { createRelayEventResultWithHints as createRelayEventResultWithHints3 } from "@kehto/runtime";
|
|
2136
2224
|
var DEFAULT_QUERY_TIMEOUT_MS = 4e3;
|
|
2137
2225
|
function defaultRelayAllowed(url) {
|
|
2138
2226
|
return typeof url === "string" && (url.startsWith("wss://") || url.startsWith("ws://"));
|
|
@@ -2206,10 +2294,10 @@ function admitEvent(ctx, collector, event) {
|
|
|
2206
2294
|
);
|
|
2207
2295
|
}
|
|
2208
2296
|
function buildCollectResult(collector, timedOut) {
|
|
2209
|
-
const events = [...collector.seen.values()]
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
return { events,
|
|
2297
|
+
const events = [...collector.seen.values()].map(
|
|
2298
|
+
(event) => createRelayEventResultWithHints3(event, [...collector.relayMap.get(event.id) ?? []])
|
|
2299
|
+
);
|
|
2300
|
+
return { events, incomplete: timedOut };
|
|
2213
2301
|
}
|
|
2214
2302
|
function collectFromRelays(ctx, filters, relayUrls2, timeoutMs) {
|
|
2215
2303
|
return new Promise((resolve) => {
|
|
@@ -2254,28 +2342,28 @@ function relayPoolSubscribe(ctx, filters, relayUrl, cb) {
|
|
|
2254
2342
|
}
|
|
2255
2343
|
async function queryImpl(ctx, filters, options) {
|
|
2256
2344
|
if (!ctx.relayPool.isAvailable()) {
|
|
2257
|
-
return { events: [],
|
|
2345
|
+
return { events: [], incomplete: true, error: "relay list unavailable" };
|
|
2258
2346
|
}
|
|
2259
2347
|
const strategy = options?.strategy ?? "auto";
|
|
2260
2348
|
const authors = deriveAuthors(filters, options?.authors);
|
|
2261
2349
|
const plan = await resolvePlan(ctx, authors, "read", strategy, options?.relays);
|
|
2262
2350
|
if (plan.relays.length === 0) {
|
|
2263
|
-
return { events: [],
|
|
2351
|
+
return { events: [], incomplete: true, error: "relay list unavailable" };
|
|
2264
2352
|
}
|
|
2265
2353
|
const timeoutMs = options?.timeoutMs ?? ctx.defaultTimeoutMs;
|
|
2266
2354
|
const collected = await collectFromRelays(ctx, filters, plan.relays, timeoutMs);
|
|
2267
2355
|
const incomplete = collected.incomplete || (plan.missingAuthors?.length ?? 0) > 0;
|
|
2268
2356
|
let events = collected.events;
|
|
2269
2357
|
if (options?.limit !== void 0 && events.length > options.limit) {
|
|
2270
|
-
events = [...events].sort((a, b) => b.created_at - a.created_at).slice(0, options.limit);
|
|
2358
|
+
events = [...events].sort((a, b) => b.event.created_at - a.event.created_at).slice(0, options.limit);
|
|
2271
2359
|
}
|
|
2272
|
-
const
|
|
2273
|
-
if (incomplete)
|
|
2274
|
-
return
|
|
2360
|
+
const result2 = { events };
|
|
2361
|
+
if (incomplete) result2.incomplete = true;
|
|
2362
|
+
return result2;
|
|
2275
2363
|
}
|
|
2276
2364
|
async function getEventImpl(ctx, eventId, options) {
|
|
2277
2365
|
if (typeof eventId !== "string" || eventId.length === 0) {
|
|
2278
|
-
return {
|
|
2366
|
+
return { error: "invalid filter" };
|
|
2279
2367
|
}
|
|
2280
2368
|
const filter = { ids: [eventId] };
|
|
2281
2369
|
const queryOptions = { limit: 1 };
|
|
@@ -2287,15 +2375,13 @@ async function getEventImpl(ctx, eventId, options) {
|
|
|
2287
2375
|
if (options?.strategy !== void 0) queryOptions.strategy = options.strategy;
|
|
2288
2376
|
if (options?.timeoutMs !== void 0) queryOptions.timeoutMs = options.timeoutMs;
|
|
2289
2377
|
const queryResult = await queryImpl(ctx, [filter], queryOptions);
|
|
2290
|
-
const
|
|
2291
|
-
const
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
if (
|
|
2295
|
-
if (
|
|
2296
|
-
|
|
2297
|
-
if (queryResult.incomplete !== void 0) result.incomplete = queryResult.incomplete;
|
|
2298
|
-
return result;
|
|
2378
|
+
const eventResult = queryResult.events.find((candidate) => candidate.event.id === eventId);
|
|
2379
|
+
const result2 = {};
|
|
2380
|
+
if (eventResult) result2.result = eventResult;
|
|
2381
|
+
if (!eventResult) result2.error = queryResult.error ?? "not found";
|
|
2382
|
+
else if (queryResult.error !== void 0) result2.error = queryResult.error;
|
|
2383
|
+
if (queryResult.incomplete !== void 0) result2.incomplete = queryResult.incomplete;
|
|
2384
|
+
return result2;
|
|
2299
2385
|
}
|
|
2300
2386
|
function closeLiveSub(sub) {
|
|
2301
2387
|
for (const handle of sub.handles) {
|
|
@@ -2313,7 +2399,6 @@ function attachLiveRelay(ctx, sub, filters, relayUrl, live, sink) {
|
|
|
2313
2399
|
sub.eoseCount += 1;
|
|
2314
2400
|
if (!sub.eoseSent && sub.eoseCount >= sub.relayCount) {
|
|
2315
2401
|
sub.eoseSent = true;
|
|
2316
|
-
sink.eose();
|
|
2317
2402
|
if (!live) {
|
|
2318
2403
|
sub.closed = true;
|
|
2319
2404
|
closeLiveSub(sub);
|
|
@@ -2326,7 +2411,7 @@ function attachLiveRelay(ctx, sub, filters, relayUrl, live, sink) {
|
|
|
2326
2411
|
void ctx.verify(item).then((ok) => {
|
|
2327
2412
|
if (!ok || sub.closed || sub.seen.has(item.id)) return;
|
|
2328
2413
|
sub.seen.add(item.id);
|
|
2329
|
-
sink.event(item, relayUrl);
|
|
2414
|
+
sink.event(createRelayEventResultWithHints3(item, [relayUrl]));
|
|
2330
2415
|
});
|
|
2331
2416
|
}));
|
|
2332
2417
|
}
|
|
@@ -2384,9 +2469,9 @@ async function publishImpl(ctx, template, options) {
|
|
|
2384
2469
|
return { ok: false, event: signed, eventId: signed.id, error: err2 instanceof Error ? err2.message : "publish failed" };
|
|
2385
2470
|
}
|
|
2386
2471
|
const ok = Object.values(relays).some(Boolean);
|
|
2387
|
-
const
|
|
2388
|
-
if (!ok)
|
|
2389
|
-
return
|
|
2472
|
+
const result2 = { ok, event: signed, eventId: signed.id, relays };
|
|
2473
|
+
if (!ok) result2.error = "publish denied";
|
|
2474
|
+
return result2;
|
|
2390
2475
|
}
|
|
2391
2476
|
function createRelayPoolOutboxRouter(options) {
|
|
2392
2477
|
if (!options || typeof options.relayPool !== "object" || options.relayPool === null) {
|
|
@@ -2496,8 +2581,8 @@ function createUploadService(options) {
|
|
|
2496
2581
|
send({ type: "upload.status.changed", status: stamped });
|
|
2497
2582
|
}
|
|
2498
2583
|
};
|
|
2499
|
-
void uploader.upload(request, ctx).then((
|
|
2500
|
-
const stamped = { ...
|
|
2584
|
+
void uploader.upload(request, ctx).then((result2) => {
|
|
2585
|
+
const stamped = { ...result2, uploadId };
|
|
2501
2586
|
const entry = entries.get(key);
|
|
2502
2587
|
if (entry) entry.status = { ...stamped, updatedAt: now() };
|
|
2503
2588
|
send({ type: "upload.upload.result", id, result: stamped });
|
|
@@ -2634,7 +2719,7 @@ async function uploadNip96(args) {
|
|
|
2634
2719
|
function fromNip94Tags(uploadId, rail, tags, fallbackSize, fallbackSha) {
|
|
2635
2720
|
const get = (name) => tags.find((t) => t[0] === name)?.[1];
|
|
2636
2721
|
const url = get("url");
|
|
2637
|
-
const
|
|
2722
|
+
const result2 = {
|
|
2638
2723
|
ok: Boolean(url),
|
|
2639
2724
|
uploadId,
|
|
2640
2725
|
status: url ? "complete" : "failed",
|
|
@@ -2642,19 +2727,19 @@ function fromNip94Tags(uploadId, rail, tags, fallbackSize, fallbackSha) {
|
|
|
2642
2727
|
sha256: get("x") ?? fallbackSha,
|
|
2643
2728
|
nip94: tags
|
|
2644
2729
|
};
|
|
2645
|
-
if (url)
|
|
2730
|
+
if (url) result2.url = url;
|
|
2646
2731
|
const ox = get("ox");
|
|
2647
|
-
if (ox)
|
|
2732
|
+
if (ox) result2.originalSha256 = ox;
|
|
2648
2733
|
const size = get("size");
|
|
2649
|
-
|
|
2734
|
+
result2.size = size ? Number(size) : fallbackSize;
|
|
2650
2735
|
const m = get("m");
|
|
2651
|
-
if (m)
|
|
2736
|
+
if (m) result2.mimeType = m;
|
|
2652
2737
|
const dim = parseDimensions(get("dim"));
|
|
2653
|
-
if (dim)
|
|
2738
|
+
if (dim) result2.dimensions = dim;
|
|
2654
2739
|
const blurhash = get("blurhash");
|
|
2655
|
-
if (blurhash)
|
|
2656
|
-
if (!url)
|
|
2657
|
-
return
|
|
2740
|
+
if (blurhash) result2.blurhash = blurhash;
|
|
2741
|
+
if (!url) result2.error = "server returned no url";
|
|
2742
|
+
return result2;
|
|
2658
2743
|
}
|
|
2659
2744
|
async function uploadBlossom(args) {
|
|
2660
2745
|
const { request, ctx, server, bytes, sha256, signEvent, fetchFn, nowS } = args;
|
|
@@ -2683,7 +2768,7 @@ async function uploadBlossom(args) {
|
|
|
2683
2768
|
if (!blob.url) {
|
|
2684
2769
|
return failed(ctx.uploadId, "blossom", "server returned no url", sha256);
|
|
2685
2770
|
}
|
|
2686
|
-
const
|
|
2771
|
+
const result2 = {
|
|
2687
2772
|
ok: true,
|
|
2688
2773
|
uploadId: ctx.uploadId,
|
|
2689
2774
|
status: "complete",
|
|
@@ -2692,8 +2777,8 @@ async function uploadBlossom(args) {
|
|
|
2692
2777
|
sha256: blob.sha256 ?? sha256,
|
|
2693
2778
|
size: blob.size ?? bytes.byteLength
|
|
2694
2779
|
};
|
|
2695
|
-
if (blob.type)
|
|
2696
|
-
return
|
|
2780
|
+
if (blob.type) result2.mimeType = blob.type;
|
|
2781
|
+
return result2;
|
|
2697
2782
|
}
|
|
2698
2783
|
function failed(uploadId, rail, error, sha256) {
|
|
2699
2784
|
return { ok: false, uploadId, status: "failed", rail, error, ...sha256 ? { sha256 } : {} };
|
|
@@ -2781,7 +2866,7 @@ function createIntentService(options) {
|
|
|
2781
2866
|
send,
|
|
2782
2867
|
"intent.invoke.result",
|
|
2783
2868
|
id,
|
|
2784
|
-
(
|
|
2869
|
+
(result2) => ({ type: "intent.invoke.result", id, result: result2 })
|
|
2785
2870
|
);
|
|
2786
2871
|
}
|
|
2787
2872
|
function handleAvailable(msg, send) {
|
|
@@ -3111,12 +3196,12 @@ async function handleOpen(options, windowId, message, send) {
|
|
|
3111
3196
|
return;
|
|
3112
3197
|
}
|
|
3113
3198
|
try {
|
|
3114
|
-
const
|
|
3199
|
+
const result2 = await options.open({ windowId, url: parsed, options: message.options });
|
|
3115
3200
|
send({
|
|
3116
3201
|
type: "link.open.result",
|
|
3117
3202
|
id: message.id,
|
|
3118
|
-
status:
|
|
3119
|
-
...
|
|
3203
|
+
status: result2.status,
|
|
3204
|
+
...result2.status === "denied" ? { error: "blocked-by-policy" } : {}
|
|
3120
3205
|
});
|
|
3121
3206
|
} catch {
|
|
3122
3207
|
send(denied(message.id, "blocked-by-policy"));
|
|
@@ -3188,7 +3273,7 @@ function settleMutation(hook, message, context, send, resultType) {
|
|
|
3188
3273
|
() => hook(message.list, message.items, message.options, context),
|
|
3189
3274
|
send,
|
|
3190
3275
|
(error) => ({ type: resultType, id: message.id, ok: false, error: "list-unavailable", reason: error }),
|
|
3191
|
-
(
|
|
3276
|
+
(result2) => ({ type: resultType, id: message.id, ...result2 })
|
|
3192
3277
|
);
|
|
3193
3278
|
}
|
|
3194
3279
|
function createListsService(options = {}) {
|
|
@@ -3274,7 +3359,7 @@ function createSerialService(options = {}) {
|
|
|
3274
3359
|
() => options.open(serialMessage.request, context),
|
|
3275
3360
|
send,
|
|
3276
3361
|
(error) => ({ type: "serial.open.result", id, error }),
|
|
3277
|
-
(
|
|
3362
|
+
(result2) => ({ type: "serial.open.result", id, session: result2.session })
|
|
3278
3363
|
);
|
|
3279
3364
|
return;
|
|
3280
3365
|
}
|
|
@@ -3371,7 +3456,7 @@ function createBleService(options = {}) {
|
|
|
3371
3456
|
() => options.open(bleMessage.request, context),
|
|
3372
3457
|
send,
|
|
3373
3458
|
(error) => ({ type: "ble.open.result", id, error }),
|
|
3374
|
-
(
|
|
3459
|
+
(result2) => ({ type: "ble.open.result", id, session: result2.session })
|
|
3375
3460
|
);
|
|
3376
3461
|
return;
|
|
3377
3462
|
}
|
|
@@ -3524,7 +3609,7 @@ function createWebrtcService(options = {}) {
|
|
|
3524
3609
|
() => options.open(webrtcMessage.request, context),
|
|
3525
3610
|
send,
|
|
3526
3611
|
(error) => ({ type: "webrtc.open.result", id, error }),
|
|
3527
|
-
(
|
|
3612
|
+
(result2) => ({ type: "webrtc.open.result", id, session: result2.session })
|
|
3528
3613
|
);
|
|
3529
3614
|
return;
|
|
3530
3615
|
}
|
|
@@ -3675,7 +3760,7 @@ function decodeNrelay(value) {
|
|
|
3675
3760
|
function convertBits(data, fromBits, toBits, pad) {
|
|
3676
3761
|
let acc = 0;
|
|
3677
3762
|
let bits = 0;
|
|
3678
|
-
const
|
|
3763
|
+
const result2 = [];
|
|
3679
3764
|
const maxv = (1 << toBits) - 1;
|
|
3680
3765
|
const maxAcc = (1 << fromBits + toBits - 1) - 1;
|
|
3681
3766
|
for (const value of data) {
|
|
@@ -3684,15 +3769,15 @@ function convertBits(data, fromBits, toBits, pad) {
|
|
|
3684
3769
|
bits += fromBits;
|
|
3685
3770
|
while (bits >= toBits) {
|
|
3686
3771
|
bits -= toBits;
|
|
3687
|
-
|
|
3772
|
+
result2.push(acc >> bits & maxv);
|
|
3688
3773
|
}
|
|
3689
3774
|
}
|
|
3690
3775
|
if (pad) {
|
|
3691
|
-
if (bits > 0)
|
|
3776
|
+
if (bits > 0) result2.push(acc << toBits - bits & maxv);
|
|
3692
3777
|
} else if (bits >= fromBits || (acc << toBits - bits & maxv) !== 0) {
|
|
3693
3778
|
throw new Error("invalid bech32 padding");
|
|
3694
3779
|
}
|
|
3695
|
-
return
|
|
3780
|
+
return result2;
|
|
3696
3781
|
}
|
|
3697
3782
|
function settle5(call, send, okFalse, onValue) {
|
|
3698
3783
|
let pending;
|
|
@@ -3712,14 +3797,14 @@ function createCommonService(options = {}) {
|
|
|
3712
3797
|
const context = { windowId };
|
|
3713
3798
|
if (message.type === "common.encodeNip19") {
|
|
3714
3799
|
const input = message.input;
|
|
3715
|
-
const
|
|
3716
|
-
send({ type: "common.encodeNip19.result", id, ...
|
|
3800
|
+
const result2 = input ? encodeNip19(input) : { ok: false, error: "invalid input" };
|
|
3801
|
+
send({ type: "common.encodeNip19.result", id, ...result2 });
|
|
3717
3802
|
return;
|
|
3718
3803
|
}
|
|
3719
3804
|
if (message.type === "common.decodeNip19") {
|
|
3720
3805
|
const value = message.value;
|
|
3721
|
-
const
|
|
3722
|
-
send({ type: "common.decodeNip19.result", id, ...
|
|
3806
|
+
const result2 = typeof value === "string" ? decodeNip19Value(value) : { ok: false, error: "invalid value" };
|
|
3807
|
+
send({ type: "common.decodeNip19.result", id, ...result2 });
|
|
3723
3808
|
return;
|
|
3724
3809
|
}
|
|
3725
3810
|
if (message.type === "common.getProfile") {
|
|
@@ -3732,7 +3817,7 @@ function createCommonService(options = {}) {
|
|
|
3732
3817
|
() => options.getProfile(target, context),
|
|
3733
3818
|
send,
|
|
3734
3819
|
(error) => ({ type: "common.getProfile.result", id, ok: false, pubkey: target ?? "", error }),
|
|
3735
|
-
(
|
|
3820
|
+
(result2) => ({ type: "common.getProfile.result", id, ...result2 })
|
|
3736
3821
|
);
|
|
3737
3822
|
return;
|
|
3738
3823
|
}
|
|
@@ -3745,7 +3830,7 @@ function createCommonService(options = {}) {
|
|
|
3745
3830
|
() => options.follows(context),
|
|
3746
3831
|
send,
|
|
3747
3832
|
(error) => ({ type: "common.follows.result", id, ok: false, pubkeys: [], error }),
|
|
3748
|
-
(
|
|
3833
|
+
(result2) => ({ type: "common.follows.result", id, ...result2 })
|
|
3749
3834
|
);
|
|
3750
3835
|
return;
|
|
3751
3836
|
}
|
|
@@ -3769,7 +3854,7 @@ function createCommonService(options = {}) {
|
|
|
3769
3854
|
() => options.react(m.targetEventId, m.reaction, m.customEmojiHref, context),
|
|
3770
3855
|
send,
|
|
3771
3856
|
(error) => ({ type: "common.react.result", id, ok: false, error }),
|
|
3772
|
-
(
|
|
3857
|
+
(result2) => ({ type: "common.react.result", id, ...result2 })
|
|
3773
3858
|
);
|
|
3774
3859
|
return;
|
|
3775
3860
|
}
|
|
@@ -3783,7 +3868,7 @@ function createCommonService(options = {}) {
|
|
|
3783
3868
|
() => options.report(m.target, m.reason, m.text, context),
|
|
3784
3869
|
send,
|
|
3785
3870
|
(error) => ({ type: "common.report.result", id, ok: false, error }),
|
|
3786
|
-
(
|
|
3871
|
+
(result2) => ({ type: "common.report.result", id, ...result2 })
|
|
3787
3872
|
);
|
|
3788
3873
|
return;
|
|
3789
3874
|
}
|
|
@@ -3806,7 +3891,7 @@ function settleAction(action, pubkeys, context, send, resultType, id, unavailabl
|
|
|
3806
3891
|
() => action(pubkeys, context),
|
|
3807
3892
|
send,
|
|
3808
3893
|
(error) => ({ type: resultType, id, ok: false, error }),
|
|
3809
|
-
(
|
|
3894
|
+
(result2) => ({ type: resultType, id, ...result2 })
|
|
3810
3895
|
);
|
|
3811
3896
|
}
|
|
3812
3897
|
|
|
@@ -3861,7 +3946,7 @@ function createDmService(options) {
|
|
|
3861
3946
|
);
|
|
3862
3947
|
return;
|
|
3863
3948
|
case "dm.send":
|
|
3864
|
-
void adapter.send(message).then((
|
|
3949
|
+
void adapter.send(message).then((result2) => send({ type: "dm.send.result", id: requestId, ...result2 })).catch((error) => send({ type: "dm.send.result", id: requestId, error: err(error) }));
|
|
3865
3950
|
return;
|
|
3866
3951
|
case "dm.subscribe": {
|
|
3867
3952
|
let activeSubscriptionId = "";
|
|
@@ -4463,6 +4548,7 @@ export {
|
|
|
4463
4548
|
createCoordinatedRelay,
|
|
4464
4549
|
createCordnDmAdapter,
|
|
4465
4550
|
createCordnRelayCoordinatorClient,
|
|
4551
|
+
createCountService,
|
|
4466
4552
|
createCvmService,
|
|
4467
4553
|
createDmService,
|
|
4468
4554
|
createHttpUploader,
|