@kehto/services 0.14.1 → 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 +8 -14
- package/dist/index.js +38 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ServiceHandler, Signer } from '@kehto/runtime';
|
|
1
|
+
import { ServiceHandler, Signer, RelayEventResult } from '@kehto/runtime';
|
|
2
2
|
import { IdentityGetProfileMessage, IdentityGetProfileResultMessage, IdentityGetFollowsMessage, IdentityGetFollowsResultMessage, IdentityGetListMessage, IdentityGetListResultMessage, IdentityGetZapsMessage, IdentityGetZapsResultMessage, IdentityGetMutesMessage, IdentityGetMutesResultMessage, IdentityGetBlockedMessage, IdentityGetBlockedResultMessage, IdentityGetBadgesMessage, IdentityGetBadgesResultMessage } from '@napplet/nap/identity/types';
|
|
3
3
|
import { NostrFilter, NostrEvent, EventTemplate, LinkOpenOptions, LinkOpenResult, ListSupport, ListRef, ListItem, ListOptions, ListMutationResult, SerialOpenRequest, SerialOpenResult, BleEvent, BleOpenRequest, BleOpenResult, BleService, BleAttribute, BleWriteOptions, WebrtcEvent, WebrtcOpenRequest, WebrtcOpenResult, CommonProfileTarget, CommonProfileResult, CommonFollowsResult, CommonActionResult, CommonReaction, CommonReportTarget, CommonReportReason } from '@napplet/core';
|
|
4
4
|
import { MediaMetadata, MediaAction } from '@napplet/nap/media/types';
|
|
@@ -1635,7 +1635,7 @@ declare function createResourceService(options: ResourceServiceOptions): Resourc
|
|
|
1635
1635
|
* Inbound: outbox.getEvent, outbox.query, outbox.subscribe, outbox.close,
|
|
1636
1636
|
* outbox.publish, outbox.resolveRelays
|
|
1637
1637
|
* Outbound: outbox.getEvent.result, outbox.query.result, outbox.event,
|
|
1638
|
-
* outbox.
|
|
1638
|
+
* outbox.closed, outbox.publish.result,
|
|
1639
1639
|
* outbox.resolveRelays.result
|
|
1640
1640
|
*
|
|
1641
1641
|
* The shell owns relay discovery, routing, fallback, deduplication, signature
|
|
@@ -1720,10 +1720,8 @@ interface OutboxRelayPlan {
|
|
|
1720
1720
|
}
|
|
1721
1721
|
/** Outcome of a single-event outbox lookup. */
|
|
1722
1722
|
interface OutboxEventResult {
|
|
1723
|
-
/** The signature-validated event matching the requested event id, when found. */
|
|
1724
|
-
|
|
1725
|
-
/** Relay URLs where the shell observed the event. */
|
|
1726
|
-
relays: string[];
|
|
1723
|
+
/** The signature-validated event result matching the requested event id, when found. */
|
|
1724
|
+
result?: RelayEventResult;
|
|
1727
1725
|
/** True when some relay lists or connections failed and the lookup was partial. */
|
|
1728
1726
|
incomplete?: boolean;
|
|
1729
1727
|
/** Error reason when the lookup could not complete or did not find the event. */
|
|
@@ -1731,10 +1729,8 @@ interface OutboxEventResult {
|
|
|
1731
1729
|
}
|
|
1732
1730
|
/** Outcome of an outbox query, as returned by the {@link OutboxRouter}. */
|
|
1733
1731
|
interface OutboxResult {
|
|
1734
|
-
/** Deduplicated, signature-validated
|
|
1735
|
-
events:
|
|
1736
|
-
/** Map of event id -> relay URLs where the shell observed the event. */
|
|
1737
|
-
relays: Record<string, string[]>;
|
|
1732
|
+
/** Deduplicated, signature-validated event results. */
|
|
1733
|
+
events: RelayEventResult[];
|
|
1738
1734
|
/** True when some relay lists or connections failed and results are partial. */
|
|
1739
1735
|
incomplete?: boolean;
|
|
1740
1736
|
/** Error reason when the query could not complete. */
|
|
@@ -1755,10 +1751,8 @@ interface OutboxPublishResult {
|
|
|
1755
1751
|
}
|
|
1756
1752
|
/** Sink an {@link OutboxRouter} streams subscription lifecycle through. */
|
|
1757
1753
|
interface OutboxSubscriptionSink {
|
|
1758
|
-
/** Deliver a matching event
|
|
1759
|
-
event(
|
|
1760
|
-
/** Signal end-of-stored-events. */
|
|
1761
|
-
eose(): void;
|
|
1754
|
+
/** Deliver a matching event result. */
|
|
1755
|
+
event(result: RelayEventResult): void;
|
|
1762
1756
|
/** Signal that the subscription was closed upstream; `reason` is optional. */
|
|
1763
1757
|
closed(reason?: string): void;
|
|
1764
1758
|
}
|
package/dist/index.js
CHANGED
|
@@ -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(() => {
|
|
@@ -647,6 +649,7 @@ function isPlainObject(value) {
|
|
|
647
649
|
}
|
|
648
650
|
|
|
649
651
|
// src/coordinated-relay.ts
|
|
652
|
+
import { createRelayEventResult as createRelayEventResult2, createRelayEventResultWithHints as createRelayEventResultWithHints2 } from "@kehto/runtime";
|
|
650
653
|
var DEFAULT_EOSE_TIMEOUT_MS = 15e3;
|
|
651
654
|
function createCoordinatedRelay(options) {
|
|
652
655
|
const timeoutMs = options.eoseTimeoutMs ?? DEFAULT_EOSE_TIMEOUT_MS;
|
|
@@ -669,10 +672,13 @@ function createCoordinatedRelay(options) {
|
|
|
669
672
|
handleMessage(windowId, message, send) {
|
|
670
673
|
const relayMessage = message;
|
|
671
674
|
if (message.type === "relay.subscribe") {
|
|
672
|
-
let deliver2 = function(event) {
|
|
675
|
+
let deliver2 = function(event, relayHints) {
|
|
673
676
|
if (tracked.seenIds.has(event.id)) return;
|
|
674
677
|
tracked.seenIds.add(event.id);
|
|
675
|
-
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
|
+
}
|
|
676
682
|
};
|
|
677
683
|
var deliver = deliver2;
|
|
678
684
|
const subId = relayMessage.subId;
|
|
@@ -728,7 +734,7 @@ function createCoordinatedRelay(options) {
|
|
|
728
734
|
maybeSendEose(subKey, subId, send);
|
|
729
735
|
return;
|
|
730
736
|
}
|
|
731
|
-
deliver2(item);
|
|
737
|
+
deliver2(item, relayUrls2);
|
|
732
738
|
if (cacheAvailable) {
|
|
733
739
|
try {
|
|
734
740
|
options.cache.store(item);
|
|
@@ -2045,12 +2051,10 @@ function buildEventQuery(eventId, eventOptions) {
|
|
|
2045
2051
|
return { filter, queryOptions };
|
|
2046
2052
|
}
|
|
2047
2053
|
function eventResultFromQuery(eventId, result2) {
|
|
2048
|
-
const
|
|
2049
|
-
const eventResult = {
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
if (event) eventResult.event = event;
|
|
2053
|
-
if (!event) eventResult.error = result2.error ?? "not found";
|
|
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";
|
|
2054
2058
|
else if (result2.error !== void 0) eventResult.error = result2.error;
|
|
2055
2059
|
if (result2.incomplete !== void 0) eventResult.incomplete = result2.incomplete;
|
|
2056
2060
|
return eventResult;
|
|
@@ -2060,15 +2064,14 @@ function fallbackGetEvent(router, eventId, eventOptions) {
|
|
|
2060
2064
|
return router.query([filter], queryOptions).then((result2) => eventResultFromQuery(eventId, result2));
|
|
2061
2065
|
}
|
|
2062
2066
|
function sendEventResult(id, eventId, result2, send) {
|
|
2063
|
-
if (result2.
|
|
2064
|
-
send({ type: "outbox.getEvent.result", id,
|
|
2067
|
+
if (result2.result && result2.result.event.id !== eventId) {
|
|
2068
|
+
send({ type: "outbox.getEvent.result", id, error: "not found" });
|
|
2065
2069
|
return;
|
|
2066
2070
|
}
|
|
2067
2071
|
send({
|
|
2068
2072
|
type: "outbox.getEvent.result",
|
|
2069
2073
|
id,
|
|
2070
|
-
...result2.
|
|
2071
|
-
relays: result2.relays,
|
|
2074
|
+
...result2.result === void 0 ? {} : { result: result2.result },
|
|
2072
2075
|
...result2.incomplete === void 0 ? {} : { incomplete: result2.incomplete },
|
|
2073
2076
|
...result2.error === void 0 ? {} : { error: result2.error }
|
|
2074
2077
|
});
|
|
@@ -2077,12 +2080,12 @@ function handleGetEvent(router, msg, send) {
|
|
|
2077
2080
|
const m = msg;
|
|
2078
2081
|
const id = m.id ?? "";
|
|
2079
2082
|
if (typeof m.eventId !== "string" || m.eventId.length === 0) {
|
|
2080
|
-
send({ type: "outbox.getEvent.result", id,
|
|
2083
|
+
send({ type: "outbox.getEvent.result", id, error: "invalid filter" });
|
|
2081
2084
|
return;
|
|
2082
2085
|
}
|
|
2083
2086
|
const getEvent = router.getEvent ?? ((eventId, eventOptions) => fallbackGetEvent(router, eventId, eventOptions));
|
|
2084
2087
|
void getEvent(m.eventId, m.options).then((result2) => sendEventResult(id, m.eventId, result2, send)).catch(
|
|
2085
|
-
(err2) => send({ type: "outbox.getEvent.result", id,
|
|
2088
|
+
(err2) => send({ type: "outbox.getEvent.result", id, error: toErrorMessage(err2) })
|
|
2086
2089
|
);
|
|
2087
2090
|
}
|
|
2088
2091
|
function createOutboxService(options) {
|
|
@@ -2096,7 +2099,7 @@ function createOutboxService(options) {
|
|
|
2096
2099
|
const id = m.id ?? "";
|
|
2097
2100
|
const filters = normalizeFilters(m.filters);
|
|
2098
2101
|
if (!filters) {
|
|
2099
|
-
send({ type: "outbox.query.result", id, events: [],
|
|
2102
|
+
send({ type: "outbox.query.result", id, events: [], error: "invalid filter" });
|
|
2100
2103
|
return;
|
|
2101
2104
|
}
|
|
2102
2105
|
void router.query(filters, m.options).then(
|
|
@@ -2104,12 +2107,11 @@ function createOutboxService(options) {
|
|
|
2104
2107
|
type: "outbox.query.result",
|
|
2105
2108
|
id,
|
|
2106
2109
|
events: result2.events,
|
|
2107
|
-
relays: result2.relays,
|
|
2108
2110
|
...result2.incomplete === void 0 ? {} : { incomplete: result2.incomplete },
|
|
2109
2111
|
...result2.error === void 0 ? {} : { error: result2.error }
|
|
2110
2112
|
})
|
|
2111
2113
|
).catch(
|
|
2112
|
-
(err2) => send({ type: "outbox.query.result", id, events: [],
|
|
2114
|
+
(err2) => send({ type: "outbox.query.result", id, events: [], error: toErrorMessage(err2) })
|
|
2113
2115
|
);
|
|
2114
2116
|
}
|
|
2115
2117
|
function handleSubscribe(windowId, msg, send) {
|
|
@@ -2125,8 +2127,7 @@ function createOutboxService(options) {
|
|
|
2125
2127
|
return;
|
|
2126
2128
|
}
|
|
2127
2129
|
const sink = {
|
|
2128
|
-
event: (
|
|
2129
|
-
eose: () => send({ type: "outbox.eose", subId }),
|
|
2130
|
+
event: (result2) => send({ type: "outbox.event", subId, result: result2 }),
|
|
2130
2131
|
closed: (reason) => {
|
|
2131
2132
|
subscriptions.delete(subKey);
|
|
2132
2133
|
send({ type: "outbox.closed", subId, ...reason === void 0 ? {} : { reason } });
|
|
@@ -2219,6 +2220,7 @@ function toErrorMessage(err2) {
|
|
|
2219
2220
|
}
|
|
2220
2221
|
|
|
2221
2222
|
// src/relay-pool-outbox-router.ts
|
|
2223
|
+
import { createRelayEventResultWithHints as createRelayEventResultWithHints3 } from "@kehto/runtime";
|
|
2222
2224
|
var DEFAULT_QUERY_TIMEOUT_MS = 4e3;
|
|
2223
2225
|
function defaultRelayAllowed(url) {
|
|
2224
2226
|
return typeof url === "string" && (url.startsWith("wss://") || url.startsWith("ws://"));
|
|
@@ -2292,10 +2294,10 @@ function admitEvent(ctx, collector, event) {
|
|
|
2292
2294
|
);
|
|
2293
2295
|
}
|
|
2294
2296
|
function buildCollectResult(collector, timedOut) {
|
|
2295
|
-
const events = [...collector.seen.values()]
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
return { events,
|
|
2297
|
+
const events = [...collector.seen.values()].map(
|
|
2298
|
+
(event) => createRelayEventResultWithHints3(event, [...collector.relayMap.get(event.id) ?? []])
|
|
2299
|
+
);
|
|
2300
|
+
return { events, incomplete: timedOut };
|
|
2299
2301
|
}
|
|
2300
2302
|
function collectFromRelays(ctx, filters, relayUrls2, timeoutMs) {
|
|
2301
2303
|
return new Promise((resolve) => {
|
|
@@ -2340,28 +2342,28 @@ function relayPoolSubscribe(ctx, filters, relayUrl, cb) {
|
|
|
2340
2342
|
}
|
|
2341
2343
|
async function queryImpl(ctx, filters, options) {
|
|
2342
2344
|
if (!ctx.relayPool.isAvailable()) {
|
|
2343
|
-
return { events: [],
|
|
2345
|
+
return { events: [], incomplete: true, error: "relay list unavailable" };
|
|
2344
2346
|
}
|
|
2345
2347
|
const strategy = options?.strategy ?? "auto";
|
|
2346
2348
|
const authors = deriveAuthors(filters, options?.authors);
|
|
2347
2349
|
const plan = await resolvePlan(ctx, authors, "read", strategy, options?.relays);
|
|
2348
2350
|
if (plan.relays.length === 0) {
|
|
2349
|
-
return { events: [],
|
|
2351
|
+
return { events: [], incomplete: true, error: "relay list unavailable" };
|
|
2350
2352
|
}
|
|
2351
2353
|
const timeoutMs = options?.timeoutMs ?? ctx.defaultTimeoutMs;
|
|
2352
2354
|
const collected = await collectFromRelays(ctx, filters, plan.relays, timeoutMs);
|
|
2353
2355
|
const incomplete = collected.incomplete || (plan.missingAuthors?.length ?? 0) > 0;
|
|
2354
2356
|
let events = collected.events;
|
|
2355
2357
|
if (options?.limit !== void 0 && events.length > options.limit) {
|
|
2356
|
-
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);
|
|
2357
2359
|
}
|
|
2358
|
-
const result2 = { events
|
|
2360
|
+
const result2 = { events };
|
|
2359
2361
|
if (incomplete) result2.incomplete = true;
|
|
2360
2362
|
return result2;
|
|
2361
2363
|
}
|
|
2362
2364
|
async function getEventImpl(ctx, eventId, options) {
|
|
2363
2365
|
if (typeof eventId !== "string" || eventId.length === 0) {
|
|
2364
|
-
return {
|
|
2366
|
+
return { error: "invalid filter" };
|
|
2365
2367
|
}
|
|
2366
2368
|
const filter = { ids: [eventId] };
|
|
2367
2369
|
const queryOptions = { limit: 1 };
|
|
@@ -2373,12 +2375,10 @@ async function getEventImpl(ctx, eventId, options) {
|
|
|
2373
2375
|
if (options?.strategy !== void 0) queryOptions.strategy = options.strategy;
|
|
2374
2376
|
if (options?.timeoutMs !== void 0) queryOptions.timeoutMs = options.timeoutMs;
|
|
2375
2377
|
const queryResult = await queryImpl(ctx, [filter], queryOptions);
|
|
2376
|
-
const
|
|
2377
|
-
const result2 = {
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
if (event) result2.event = event;
|
|
2381
|
-
if (!event) result2.error = queryResult.error ?? "not found";
|
|
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
2382
|
else if (queryResult.error !== void 0) result2.error = queryResult.error;
|
|
2383
2383
|
if (queryResult.incomplete !== void 0) result2.incomplete = queryResult.incomplete;
|
|
2384
2384
|
return result2;
|
|
@@ -2399,7 +2399,6 @@ function attachLiveRelay(ctx, sub, filters, relayUrl, live, sink) {
|
|
|
2399
2399
|
sub.eoseCount += 1;
|
|
2400
2400
|
if (!sub.eoseSent && sub.eoseCount >= sub.relayCount) {
|
|
2401
2401
|
sub.eoseSent = true;
|
|
2402
|
-
sink.eose();
|
|
2403
2402
|
if (!live) {
|
|
2404
2403
|
sub.closed = true;
|
|
2405
2404
|
closeLiveSub(sub);
|
|
@@ -2412,7 +2411,7 @@ function attachLiveRelay(ctx, sub, filters, relayUrl, live, sink) {
|
|
|
2412
2411
|
void ctx.verify(item).then((ok) => {
|
|
2413
2412
|
if (!ok || sub.closed || sub.seen.has(item.id)) return;
|
|
2414
2413
|
sub.seen.add(item.id);
|
|
2415
|
-
sink.event(item, relayUrl);
|
|
2414
|
+
sink.event(createRelayEventResultWithHints3(item, [relayUrl]));
|
|
2416
2415
|
});
|
|
2417
2416
|
}));
|
|
2418
2417
|
}
|