@estiva-app/protocol 0.2.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -4,6 +4,72 @@ Every entry answers the wire question explicitly, including when the answer is
4
4
  nothing (ADR 0002 §4b). A change to the bytes an app publishes is a MAJOR — in
5
5
  `0.x`, a MINOR — even when no TypeScript signature moved.
6
6
 
7
+ ## 0.4.0 — 2026-09-01
8
+
9
+ **Wire behaviour: unchanged.** No builder, tag layout, id computation or
10
+ signature input moved. `queryAll` returns the same array it always did — see
11
+ below, that is the property the tests are about.
12
+
13
+ - **`queryAll` runs its filters concurrently**, bounded by the new
14
+ `DEFAULT_QUERY_CONCURRENCY` (8) and overridable per call via
15
+ `QueryAllOptions.concurrency`. `concurrency: 1` is the old serial read
16
+ exactly.
17
+
18
+ Filters handed to one call are independent; only the pages *inside* a filter
19
+ are a cursor walk, and those stay sequential because page N+1's `until` is
20
+ not known until page N has answered. Running the filters in sequence made a
21
+ read cost the sum of every filter's latency. Measured on Ship's `loadAll`
22
+ against production: **33 filters, 66 round trips, median 206 ms, 100% of wall
23
+ clock spent inside `query` one request at a time.** The same read, same relay,
24
+ same credentials, through this build: **9.0 s → 1.68 s, and the fold compares
25
+ equal event for event** — every project and issue address with its status,
26
+ every change id, every conversation id.
27
+
28
+ The concurrency is deliberately not observable in the answer. Results are
29
+ collected per filter and concatenated in filter order, and a failure reports
30
+ the **lowest-indexed** filter's error rather than whichever request lost the
31
+ race — so a broken read names the same filter twice running.
32
+
33
+ - **What this does not buy you: relay budget.** Buzz meters `POST /query`
34
+ against `human_api_calls_per_min` — a fixed 60-second window, default 300,
35
+ applied to every bridge call whatever tier the caller is. One Ship workspace
36
+ read is 66 of those. Concurrency changes when a read spends its requests,
37
+ never how many, so a poller that simply reads more often now spends the same
38
+ allowance sooner. Documented at `DEFAULT_QUERY_CONCURRENCY` because it is the
39
+ first thing a caller will get wrong.
40
+
41
+ Additive, and behaviour under a caller's existing call changes (requests now
42
+ overlap), so a MINOR: ADR 0002 §4b puts the break on MINOR within `0.x`.
43
+
44
+ ## 0.3.0 — 2026-09-01
45
+
46
+ *Backfilled 2026-09-01. This release shipped without an entry, and so did 0.2.0
47
+ below — the file's own rule is that every release answers the wire question, and
48
+ twice it went unanswered. Recorded now from the release commits rather than left
49
+ as a gap.*
50
+
51
+ **Wire behaviour: unchanged.** NIP-19 is an encoding of a pointer, not of an
52
+ event; nothing an app publishes moved.
53
+
54
+ - **`nevent`** — `EventPointer`, `encodeNevent`, `decodeNevent`. An event that
55
+ is not addressable had no reference form at all, so a plain `kind:9` message
56
+ could be resolved by nothing. TLV type 0 carries the event id as 32 raw
57
+ bytes, where `naddr` carries a UTF-8 `d`; that difference is the whole of the
58
+ codec.
59
+
60
+ ## 0.2.0 — 2026-08-28
61
+
62
+ *Backfilled 2026-09-01, from the release commit — see the note under 0.3.0.*
63
+
64
+ **Wire behaviour: unchanged.** A read-path fix; no published bytes moved.
65
+
66
+ - **`RELAY_PAGE_CEILING`, and `queryAll` pages instead of truncating.** Buzz
67
+ clamps a REQ to its advertised NIP-11 `max_limit`, which halved from 10000 to
68
+ 1000, and NIP-01 has no truncation signal — so a caller asking for 2000 got
69
+ 1000 and no indication why. `limit: 2000` was a literal at four call sites
70
+ across two apps and the agent, none of which could know when the relay changed
71
+ it.
72
+
7
73
  ## 0.1.2 — 2026-08-27
8
74
 
9
75
  **Wire behaviour: unchanged.** One constant added. No builder, tag layout, id
package/dist/bridge.d.ts CHANGED
@@ -37,6 +37,48 @@ export interface PublishResult {
37
37
  * is the relay's real ceiling — see its note on why.
38
38
  */
39
39
  export declare const RELAY_PAGE_CEILING = 1000;
40
+ /**
41
+ * How many of a {@link Relay.queryAll} call's filters may be in flight at once.
42
+ *
43
+ * Filters are independent — only paging *within* one is a cursor walk — and
44
+ * running them one after another made a read as slow as the sum of its parts.
45
+ * Measured on Ship's `loadAll` against production: **33 filters, 66 sequential
46
+ * round trips, median 206 ms, 100% of wall clock spent inside `query` one
47
+ * request at a time.** At a concurrency of 8 the same read returned a
48
+ * byte-identical answer in 1.9 s instead of 9.0 s.
49
+ *
50
+ * Bounded rather than unbounded on purpose. A workspace's filter count grows
51
+ * with its Folders, so `Promise.all` over all of them would open a fan-out
52
+ * whose width is set by the *data* — fine at 33, an accidental flood at 500,
53
+ * and the relay is shared. Eight is enough to hide the latency without any
54
+ * caller having to think about it.
55
+ *
56
+ * Pass `concurrency: 1` to restore the strictly serial read.
57
+ *
58
+ * ## This does not buy a caller more relay budget
59
+ *
60
+ * Concurrency changes how fast a read spends its requests, never how many it
61
+ * makes. Buzz meters `POST /query` against `human_api_calls_per_min` — a fixed
62
+ * 60-second window, **default 300, applied to every bridge call whatever tier
63
+ * the caller is** (`enforce_http_admission` in `api/bridge.rs` reads the human
64
+ * limit unconditionally). At 66 requests, one Ship workspace read is 22% of a
65
+ * minute's entire allowance, so no client gets more than ~4.5 of them a minute
66
+ * however it schedules them.
67
+ *
68
+ * A poller therefore has to slow down as its reads get faster, or it simply
69
+ * spends the same budget sooner and starts collecting
70
+ * `rate-limited: quota exceeded`. Making a read cheap is the fix for that;
71
+ * making it parallel is not.
72
+ */
73
+ export declare const DEFAULT_QUERY_CONCURRENCY = 8;
74
+ export interface QueryAllOptions {
75
+ /** Events per request. Defaults to {@link RELAY_PAGE_CEILING}. */
76
+ pageSize?: number;
77
+ /** Give up after this many pages *per filter*, rather than looping forever. */
78
+ maxPages?: number;
79
+ /** Filters in flight at once. Defaults to {@link DEFAULT_QUERY_CONCURRENCY}; 1 is serial. */
80
+ concurrency?: number;
81
+ }
40
82
  export declare function parsePublishResponse(status: number, text: string): PublishResult;
41
83
  export interface QueryResult {
42
84
  ok: boolean;
@@ -131,10 +173,26 @@ export declare class Relay {
131
173
  * value of `until` reaches past them without skipping some, and no correct
132
174
  * answer exists from this API — so it says so instead of returning a
133
175
  * plausible subset.
176
+ *
177
+ * **Filters run concurrently, up to {@link DEFAULT_QUERY_CONCURRENCY}.** They
178
+ * are independent of one another; only the pages inside one are a cursor
179
+ * walk. Doing them in sequence made a read cost the sum of every filter's
180
+ * latency, which is what put Ship's workspace read at nine seconds against a
181
+ * five-second poll — long enough that a write's re-read had usually not
182
+ * finished before the next one began.
183
+ *
184
+ * The concurrency is deliberately **not observable in the answer**: results
185
+ * are collected per filter and concatenated in filter order, so the returned
186
+ * array is identical to the serial one, and a failure reports the
187
+ * lowest-indexed filter's error rather than whichever lost the race.
188
+ */
189
+ queryAll(filters: Record<string, unknown>[], options?: QueryAllOptions): Promise<SignedEvent[]>;
190
+ /**
191
+ * One filter, paged to exhaustion. The sequential half, and it has to be:
192
+ * `until` is a cursor, so page N+1's request is not known until page N has
193
+ * answered. Only the filters are independent, which is why they are the
194
+ * axis {@link Relay.queryAll} parallelises.
134
195
  */
135
- queryAll(filters: Record<string, unknown>[], options?: {
136
- pageSize?: number;
137
- maxPages?: number;
138
- }): Promise<SignedEvent[]>;
196
+ private pageFilter;
139
197
  }
140
198
  //# sourceMappingURL=bridge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAEvC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,CAehF;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAgB5E;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KACpE,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAAA;AAKzD,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAEzF,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuB;gBAErC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,YAAY,GAAG,YAAiB;YAWpE,IAAI;IAwBZ,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAKzD;;;;;;OAMG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAOvE;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACG,QAAQ,CACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAClC,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GACrD,OAAO,CAAC,WAAW,EAAE,CAAC;CAqC1B"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
package/dist/bridge.js CHANGED
@@ -53,6 +53,40 @@ import { authorizationHeader } from './nip98.js';
53
53
  * is the relay's real ceiling — see its note on why.
54
54
  */
55
55
  export const RELAY_PAGE_CEILING = 1000;
56
+ /**
57
+ * How many of a {@link Relay.queryAll} call's filters may be in flight at once.
58
+ *
59
+ * Filters are independent — only paging *within* one is a cursor walk — and
60
+ * running them one after another made a read as slow as the sum of its parts.
61
+ * Measured on Ship's `loadAll` against production: **33 filters, 66 sequential
62
+ * round trips, median 206 ms, 100% of wall clock spent inside `query` one
63
+ * request at a time.** At a concurrency of 8 the same read returned a
64
+ * byte-identical answer in 1.9 s instead of 9.0 s.
65
+ *
66
+ * Bounded rather than unbounded on purpose. A workspace's filter count grows
67
+ * with its Folders, so `Promise.all` over all of them would open a fan-out
68
+ * whose width is set by the *data* — fine at 33, an accidental flood at 500,
69
+ * and the relay is shared. Eight is enough to hide the latency without any
70
+ * caller having to think about it.
71
+ *
72
+ * Pass `concurrency: 1` to restore the strictly serial read.
73
+ *
74
+ * ## This does not buy a caller more relay budget
75
+ *
76
+ * Concurrency changes how fast a read spends its requests, never how many it
77
+ * makes. Buzz meters `POST /query` against `human_api_calls_per_min` — a fixed
78
+ * 60-second window, **default 300, applied to every bridge call whatever tier
79
+ * the caller is** (`enforce_http_admission` in `api/bridge.rs` reads the human
80
+ * limit unconditionally). At 66 requests, one Ship workspace read is 22% of a
81
+ * minute's entire allowance, so no client gets more than ~4.5 of them a minute
82
+ * however it schedules them.
83
+ *
84
+ * A poller therefore has to slow down as its reads get faster, or it simply
85
+ * spends the same budget sooner and starts collecting
86
+ * `rate-limited: quota exceeded`. Making a read cheap is the fix for that;
87
+ * making it parallel is not.
88
+ */
89
+ export const DEFAULT_QUERY_CONCURRENCY = 8;
56
90
  export function parsePublishResponse(status, text) {
57
91
  let parsed;
58
92
  try {
@@ -178,38 +212,108 @@ export class Relay {
178
212
  * value of `until` reaches past them without skipping some, and no correct
179
213
  * answer exists from this API — so it says so instead of returning a
180
214
  * plausible subset.
215
+ *
216
+ * **Filters run concurrently, up to {@link DEFAULT_QUERY_CONCURRENCY}.** They
217
+ * are independent of one another; only the pages inside one are a cursor
218
+ * walk. Doing them in sequence made a read cost the sum of every filter's
219
+ * latency, which is what put Ship's workspace read at nine seconds against a
220
+ * five-second poll — long enough that a write's re-read had usually not
221
+ * finished before the next one began.
222
+ *
223
+ * The concurrency is deliberately **not observable in the answer**: results
224
+ * are collected per filter and concatenated in filter order, so the returned
225
+ * array is identical to the serial one, and a failure reports the
226
+ * lowest-indexed filter's error rather than whichever lost the race.
181
227
  */
182
228
  async queryAll(filters, options = {}) {
183
229
  const pageSize = options.pageSize ?? RELAY_PAGE_CEILING;
184
230
  const maxPages = options.maxPages ?? 100;
185
- const seen = new Set();
186
- const out = [];
187
- for (const filter of filters) {
188
- let until;
189
- for (let page = 0;; page++) {
190
- if (page >= maxPages) {
191
- throw new Error(`queryAll: gave up after ${maxPages} pages refusing to return a partial set`);
231
+ const concurrency = Math.max(1, options.concurrency ?? DEFAULT_QUERY_CONCURRENCY);
232
+ /*
233
+ Per filter, in filter order not one shared accumulator.
234
+
235
+ Concurrency must not be observable in the answer. Collecting each
236
+ filter's pages into its own slot and concatenating in order at the end
237
+ makes the output byte-identical to the serial version, whatever order the
238
+ responses actually arrive in. Dedup then runs over that ordered
239
+ concatenation, so an id first seen under filter 0 still belongs to filter
240
+ 0's run of events, exactly as before.
241
+ */
242
+ const perFilter = new Array(filters.length);
243
+ const failures = new Array(filters.length);
244
+ let next = 0;
245
+ let failed = false;
246
+ const worker = async () => {
247
+ for (;;) {
248
+ // Stop *starting* filters once one has failed. The serial version never
249
+ // reached them at all; this is as close as a fan-out gets, and it keeps
250
+ // a broken read from firing the whole remaining queue at the relay.
251
+ if (failed)
252
+ return;
253
+ const index = next++;
254
+ if (index >= filters.length)
255
+ return;
256
+ try {
257
+ perFilter[index] = await this.pageFilter(filters[index], pageSize, maxPages);
192
258
  }
193
- const events = await this.query([
194
- { ...filter, limit: pageSize, ...(until === undefined ? {} : { until }) },
195
- ]);
196
- if (events.length === 0)
197
- break;
198
- for (const e of events) {
199
- if (seen.has(e.id))
200
- continue;
201
- seen.add(e.id);
202
- out.push(e);
259
+ catch (error) {
260
+ failures[index] = error;
261
+ failed = true;
262
+ return;
203
263
  }
204
- const oldest = Math.min(...events.map((e) => e.created_at));
205
- if (until !== undefined && oldest >= until) {
206
- if (events.length >= pageSize) {
207
- throw new Error(`queryAll: more than ${pageSize} events share created_at=${until} — cannot page without skipping`);
208
- }
209
- break;
264
+ }
265
+ };
266
+ await Promise.all(Array.from({ length: Math.min(concurrency, filters.length) }, () => worker()));
267
+ /*
268
+ The lowest-indexed failure, not the first to reject in wall-clock time.
269
+
270
+ Under `Promise.all` the error a caller sees would otherwise depend on
271
+ which request happened to lose the race, so two runs of the same broken
272
+ read could report different filters. Serial order is the one order that
273
+ is reproducible, and it is what the serial version reported.
274
+ */
275
+ const firstFailure = failures.findIndex((error) => error !== undefined);
276
+ if (firstFailure !== -1)
277
+ throw failures[firstFailure];
278
+ const seen = new Set();
279
+ const out = [];
280
+ for (const events of perFilter) {
281
+ for (const e of events) {
282
+ if (seen.has(e.id))
283
+ continue;
284
+ seen.add(e.id);
285
+ out.push(e);
286
+ }
287
+ }
288
+ return out;
289
+ }
290
+ /**
291
+ * One filter, paged to exhaustion. The sequential half, and it has to be:
292
+ * `until` is a cursor, so page N+1's request is not known until page N has
293
+ * answered. Only the filters are independent, which is why they are the
294
+ * axis {@link Relay.queryAll} parallelises.
295
+ */
296
+ async pageFilter(filter, pageSize, maxPages) {
297
+ const out = [];
298
+ let until;
299
+ for (let page = 0;; page++) {
300
+ if (page >= maxPages) {
301
+ throw new Error(`queryAll: gave up after ${maxPages} pages — refusing to return a partial set`);
302
+ }
303
+ const events = await this.query([
304
+ { ...filter, limit: pageSize, ...(until === undefined ? {} : { until }) },
305
+ ]);
306
+ if (events.length === 0)
307
+ break;
308
+ out.push(...events);
309
+ const oldest = Math.min(...events.map((e) => e.created_at));
310
+ if (until !== undefined && oldest >= until) {
311
+ if (events.length >= pageSize) {
312
+ throw new Error(`queryAll: more than ${pageSize} events share created_at=${until} — cannot page without skipping`);
210
313
  }
211
- until = oldest;
314
+ break;
212
315
  }
316
+ until = oldest;
213
317
  }
214
318
  return out;
215
319
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -46,12 +46,12 @@
46
46
  /** Bumped by hand with the version in package.json — `test/version.test.ts`
47
47
  * pins the two together. It exists so "the upgrade reached the app" can be
48
48
  * checked by grepping a built bundle rather than by trusting a lockfile. */
49
- export declare const PROTOCOL_VERSION = "0.2.0";
49
+ export declare const PROTOCOL_VERSION = "0.4.0";
50
50
  export { type NostrTag, type UnsignedEvent, type SignedEvent, type Profile, type ThreadRef, type ChannelVisibility, type ChannelKind, type MemberRole, type Label, type ResolutionAction, KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, RELAY_AUTH_TOLERANCE_SECS, ASSERTION_SUBTYPE, computeEventId, toNostrSeconds, canonicalChannelName, threadTags, addr, relayAuthUrl, buildProfile, parseProfile, buildCreateChannel, buildDeleteChannel, buildEditChannelMetadata, buildAddMember, buildReaction, buildDeletion, buildMessage, buildResolution, buildFile, buildComponent, buildHighlight, buildUnsignedRelayAuthEvent, } from './events.js';
51
- export { type AddressPointer, convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
51
+ export { type AddressPointer, type EventPointer, encodeNevent, decodeNevent, convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
52
52
  export { type AuthEventArgs, TIMESTAMP_TOLERANCE_SECS, normalizeUrl, buildUnsignedAuthEvent, base64, authorizationHeaderFor, authorizationHeader, } from './nip98.js';
53
53
  export { type Signer, type SignerKind, publicKeyFromSecret, signEvent, secretKeySigner, } from './sign.js';
54
- export { type PublishResult, type QueryResult, type RelayHeaders, type RelayOptions, type FetchLike, parsePublishResponse, parseQueryResponse, RELAY_PAGE_CEILING, Relay, } from './bridge.js';
54
+ export { type PublishResult, type QueryResult, type RelayHeaders, type RelayOptions, type FetchLike, type QueryAllOptions, parsePublishResponse, parseQueryResponse, RELAY_PAGE_CEILING, DEFAULT_QUERY_CONCURRENCY, Relay, } from './bridge.js';
55
55
  export { type RelayState, type SocketLike, type RelayCredential, type LiveRelayOptions, type Subscription, type LiveRelay, toWebSocketUrl, parseFrame, createLiveRelay, } from './live.js';
56
56
  export { type ChannelEventHandler, type ChannelSubscription, type ChannelSubscriptions, createChannelSubscriptions, } from './subscriptions.js';
57
57
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;4EAE4E;AAC5E,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,gBAAgB,EAErB,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EAEjB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY,EAEZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,cAAc,EACnB,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,MAAM,EACX,KAAK,UAAU,EACf,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,GACN,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,cAAc,EACd,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;4EAE4E;AAC5E,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,gBAAgB,EAErB,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EAEjB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY,EAEZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,MAAM,EACX,KAAK,UAAU,EACf,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,KAAK,GACN,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,cAAc,EACd,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -46,7 +46,7 @@
46
46
  /** Bumped by hand with the version in package.json — `test/version.test.ts`
47
47
  * pins the two together. It exists so "the upgrade reached the app" can be
48
48
  * checked by grepping a built bundle rather than by trusting a lockfile. */
49
- export const PROTOCOL_VERSION = '0.2.0';
49
+ export const PROTOCOL_VERSION = '0.4.0';
50
50
  export {
51
51
  // constants
52
52
  KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, RELAY_AUTH_TOLERANCE_SECS, ASSERTION_SUBTYPE,
@@ -54,10 +54,10 @@ KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, REL
54
54
  computeEventId, toNostrSeconds, canonicalChannelName, threadTags, addr, relayAuthUrl,
55
55
  // builders
56
56
  buildProfile, parseProfile, buildCreateChannel, buildDeleteChannel, buildEditChannelMetadata, buildAddMember, buildReaction, buildDeletion, buildMessage, buildResolution, buildFile, buildComponent, buildHighlight, buildUnsignedRelayAuthEvent, } from './events.js';
57
- export { convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
57
+ export { encodeNevent, decodeNevent, convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
58
58
  export { TIMESTAMP_TOLERANCE_SECS, normalizeUrl, buildUnsignedAuthEvent, base64, authorizationHeaderFor, authorizationHeader, } from './nip98.js';
59
59
  export { publicKeyFromSecret, signEvent, secretKeySigner, } from './sign.js';
60
- export { parsePublishResponse, parseQueryResponse, RELAY_PAGE_CEILING, Relay, } from './bridge.js';
60
+ export { parsePublishResponse, parseQueryResponse, RELAY_PAGE_CEILING, DEFAULT_QUERY_CONCURRENCY, Relay, } from './bridge.js';
61
61
  export { toWebSocketUrl, parseFrame, createLiveRelay, } from './live.js';
62
62
  export { createChannelSubscriptions, } from './subscriptions.js';
63
63
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;4EAE4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAA;AAEvC,OAAO;AAYL,YAAY;AACZ,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB;AACjB,8CAA8C;AAC9C,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY;AACZ,WAAW;AACX,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EAEL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EAEL,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAGL,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EAML,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,GACN,MAAM,aAAa,CAAA;AAEpB,OAAO,EAOL,cAAc,EACd,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EAIL,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;4EAE4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAA;AAEvC,OAAO;AAYL,YAAY;AACZ,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB;AACjB,8CAA8C;AAC9C,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY;AACZ,WAAW;AACX,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EAGL,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EAEL,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAGL,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EAOL,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,KAAK,GACN,MAAM,aAAa,CAAA;AAEpB,OAAO,EAOL,cAAc,EACd,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EAIL,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA"}
package/dist/nip19.d.ts CHANGED
@@ -29,6 +29,41 @@ export interface AddressPointer {
29
29
  * TLV order is identifier, relays, author, kind — see the header on why that is
30
30
  * a choice rather than a rule.
31
31
  */
32
+ /**
33
+ * A pointer to **one event**, by its id — NIP-19 `nevent`.
34
+ *
35
+ * The counterpart to `AddressPointer`, and the two are not interchangeable.
36
+ * An address names *whatever is currently at* `(kind, pubkey, d)` and survives
37
+ * its author replacing the event. An event id names one immutable event and
38
+ * nothing else: a `kind:9` message has no `d`, so an address cannot be built
39
+ * for it at all.
40
+ *
41
+ * `author` and `kind` are optional in the format and worth including whenever
42
+ * they are known — a reader that has them can query by author and kind rather
43
+ * than scanning, and a consumer can find the manifest that renders the kind
44
+ * before it has the event.
45
+ */
46
+ export interface EventPointer {
47
+ /** 32-byte event id, hex. */
48
+ id: string;
49
+ relays: string[];
50
+ /** Optional in NIP-19; include it when known. */
51
+ pubkey?: string;
52
+ /** Optional in NIP-19; include it when known. */
53
+ kind?: number;
54
+ }
55
+ /**
56
+ * `nevent1…` for one event.
57
+ *
58
+ * The TLV layout is `naddr`'s with one difference that matters: type 0 holds
59
+ * the event id as **32 raw bytes**, where an naddr holds the `d` identifier as
60
+ * UTF-8. Encoding an id as text produces a bech32 string every decoder accepts
61
+ * and no relay can answer — the same silent-but-invalid shape the author-length
62
+ * guard below was added for.
63
+ */
64
+ export declare function encodeNevent(pointer: EventPointer): string;
65
+ /** The inverse of `encodeNevent`. Throws on anything that is not an `nevent`. */
66
+ export declare function decodeNevent(encoded: string): EventPointer;
32
67
  export declare function encodeNaddr(pointer: AddressPointer): string;
33
68
  /**
34
69
  * Decode `naddr1…`, with or without a `nostr:` prefix, in any case.
@@ -1 +1 @@
1
- {"version":3,"file":"nip19.d.ts","sourceRoot":"","sources":["../src/nip19.ts"],"names":[],"mappings":"AAkFA,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAqBrG;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAGhE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAgB7E;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAWD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA8B3D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAyC3D;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAWhE;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,MAAM,CAG1E;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAKhE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,QAAwD,CAAA;AAE7E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBhD"}
1
+ {"version":3,"file":"nip19.d.ts","sourceRoot":"","sources":["../src/nip19.ts"],"names":[],"mappings":"AAkFA,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAqBrG;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAGhE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAgB7E;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAWD;;;;;GAKG;AACH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iDAAiD;IACjD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAgC1D;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA0C1D;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA8B3D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAyC3D;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAWhE;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,MAAM,CAG1E;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAKhE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,QAAwD,CAAA;AAE7E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBhD"}
package/dist/nip19.js CHANGED
@@ -136,11 +136,89 @@ const TLV_RELAY = 1;
136
136
  const TLV_AUTHOR = 2;
137
137
  const TLV_KIND = 3;
138
138
  /**
139
- * Encode an address as `naddr1…`.
139
+ * `nevent1…` for one event.
140
140
  *
141
- * TLV order is identifier, relays, author, kind see the header on why that is
142
- * a choice rather than a rule.
141
+ * The TLV layout is `naddr`'s with one difference that matters: type 0 holds
142
+ * the event id as **32 raw bytes**, where an naddr holds the `d` identifier as
143
+ * UTF-8. Encoding an id as text produces a bech32 string every decoder accepts
144
+ * and no relay can answer — the same silent-but-invalid shape the author-length
145
+ * guard below was added for.
143
146
  */
147
+ export function encodeNevent(pointer) {
148
+ const bytes = [];
149
+ const push = (type, value) => {
150
+ if (value.length > 255)
151
+ throw new Error(`TLV value too long for type ${type}`);
152
+ bytes.push(type, value.length, ...value);
153
+ };
154
+ const id = hexToBytes(pointer.id);
155
+ if (id.length !== 32)
156
+ throw new Error(`event id must be 32 bytes, got ${id.length}`);
157
+ push(TLV_IDENTIFIER, id);
158
+ for (const relay of pointer.relays)
159
+ push(TLV_RELAY, utf8ToBytes(relay));
160
+ if (pointer.pubkey !== undefined) {
161
+ const author = hexToBytes(pointer.pubkey);
162
+ if (author.length !== 32)
163
+ throw new Error(`author must be 32 bytes, got ${author.length}`);
164
+ push(TLV_AUTHOR, author);
165
+ }
166
+ if (pointer.kind !== undefined) {
167
+ push(TLV_KIND, new Uint8Array([
168
+ (pointer.kind >>> 24) & 0xff,
169
+ (pointer.kind >>> 16) & 0xff,
170
+ (pointer.kind >>> 8) & 0xff,
171
+ pointer.kind & 0xff,
172
+ ]));
173
+ }
174
+ return bech32Encode('nevent', convertBits(bytes, 8, 5, true));
175
+ }
176
+ /** The inverse of `encodeNevent`. Throws on anything that is not an `nevent`. */
177
+ export function decodeNevent(encoded) {
178
+ const { hrp, data } = bech32Decode(encoded.replace(/^nostr:/i, '').toLowerCase());
179
+ if (hrp !== 'nevent')
180
+ throw new Error(`expected an nevent, got ${hrp}`);
181
+ const bytes = convertBits(data, 5, 8, false);
182
+ let id;
183
+ let pubkey;
184
+ let kind;
185
+ const relays = [];
186
+ for (let i = 0; i < bytes.length;) {
187
+ const type = bytes[i];
188
+ const length = bytes[i + 1];
189
+ const value = bytes.slice(i + 2, i + 2 + length);
190
+ if (value.length !== length)
191
+ throw new Error('truncated TLV');
192
+ i += 2 + length;
193
+ switch (type) {
194
+ case TLV_IDENTIFIER:
195
+ if (length !== 32)
196
+ throw new Error(`event id must be 32 bytes, got ${length}`);
197
+ id = bytesToHex(new Uint8Array(value));
198
+ break;
199
+ case TLV_RELAY:
200
+ relays.push(new TextDecoder().decode(new Uint8Array(value)));
201
+ break;
202
+ case TLV_AUTHOR:
203
+ if (length !== 32)
204
+ throw new Error(`author must be 32 bytes, got ${length}`);
205
+ pubkey = bytesToHex(new Uint8Array(value));
206
+ break;
207
+ case TLV_KIND:
208
+ if (length !== 4)
209
+ throw new Error(`kind must be 4 bytes, got ${length}`);
210
+ kind = ((value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]) >>> 0;
211
+ break;
212
+ // Unknown TLV types are skipped rather than rejected, as in `decodeNaddr`.
213
+ }
214
+ }
215
+ // Only the id is required. An `nevent` carrying nothing else is legal and
216
+ // still resolvable — by scanning, which is why the optional fields are worth
217
+ // writing when they are known.
218
+ if (id === undefined)
219
+ throw new Error('nevent is missing its event id');
220
+ return { id, relays, ...(pubkey !== undefined ? { pubkey } : {}), ...(kind !== undefined ? { kind } : {}) };
221
+ }
144
222
  export function encodeNaddr(pointer) {
145
223
  const bytes = [];
146
224
  const push = (type, value) => {
package/dist/nip19.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"nip19.js","sourceRoot":"","sources":["../src/nip19.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nip19.js","sourceRoot":"","sources":["../src/nip19.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@estiva-app/protocol",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "The Estiva wire format: Buzz-shaped Nostr event builders, NIP-01 ids, NIP-19 naddr, NIP-98 HTTP auth, and the relay clients. Speaks the protocol; interprets nothing.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/bridge.ts CHANGED
@@ -67,6 +67,50 @@ export interface PublishResult {
67
67
  */
68
68
  export const RELAY_PAGE_CEILING = 1000
69
69
 
70
+ /**
71
+ * How many of a {@link Relay.queryAll} call's filters may be in flight at once.
72
+ *
73
+ * Filters are independent — only paging *within* one is a cursor walk — and
74
+ * running them one after another made a read as slow as the sum of its parts.
75
+ * Measured on Ship's `loadAll` against production: **33 filters, 66 sequential
76
+ * round trips, median 206 ms, 100% of wall clock spent inside `query` one
77
+ * request at a time.** At a concurrency of 8 the same read returned a
78
+ * byte-identical answer in 1.9 s instead of 9.0 s.
79
+ *
80
+ * Bounded rather than unbounded on purpose. A workspace's filter count grows
81
+ * with its Folders, so `Promise.all` over all of them would open a fan-out
82
+ * whose width is set by the *data* — fine at 33, an accidental flood at 500,
83
+ * and the relay is shared. Eight is enough to hide the latency without any
84
+ * caller having to think about it.
85
+ *
86
+ * Pass `concurrency: 1` to restore the strictly serial read.
87
+ *
88
+ * ## This does not buy a caller more relay budget
89
+ *
90
+ * Concurrency changes how fast a read spends its requests, never how many it
91
+ * makes. Buzz meters `POST /query` against `human_api_calls_per_min` — a fixed
92
+ * 60-second window, **default 300, applied to every bridge call whatever tier
93
+ * the caller is** (`enforce_http_admission` in `api/bridge.rs` reads the human
94
+ * limit unconditionally). At 66 requests, one Ship workspace read is 22% of a
95
+ * minute's entire allowance, so no client gets more than ~4.5 of them a minute
96
+ * however it schedules them.
97
+ *
98
+ * A poller therefore has to slow down as its reads get faster, or it simply
99
+ * spends the same budget sooner and starts collecting
100
+ * `rate-limited: quota exceeded`. Making a read cheap is the fix for that;
101
+ * making it parallel is not.
102
+ */
103
+ export const DEFAULT_QUERY_CONCURRENCY = 8
104
+
105
+ export interface QueryAllOptions {
106
+ /** Events per request. Defaults to {@link RELAY_PAGE_CEILING}. */
107
+ pageSize?: number
108
+ /** Give up after this many pages *per filter*, rather than looping forever. */
109
+ maxPages?: number
110
+ /** Filters in flight at once. Defaults to {@link DEFAULT_QUERY_CONCURRENCY}; 1 is serial. */
111
+ concurrency?: number
112
+ }
113
+
70
114
  export function parsePublishResponse(status: number, text: string): PublishResult {
71
115
  let parsed: { accepted?: boolean; event_id?: string; message?: string; error?: string }
72
116
  try {
@@ -241,44 +285,122 @@ export class Relay {
241
285
  * value of `until` reaches past them without skipping some, and no correct
242
286
  * answer exists from this API — so it says so instead of returning a
243
287
  * plausible subset.
288
+ *
289
+ * **Filters run concurrently, up to {@link DEFAULT_QUERY_CONCURRENCY}.** They
290
+ * are independent of one another; only the pages inside one are a cursor
291
+ * walk. Doing them in sequence made a read cost the sum of every filter's
292
+ * latency, which is what put Ship's workspace read at nine seconds against a
293
+ * five-second poll — long enough that a write's re-read had usually not
294
+ * finished before the next one began.
295
+ *
296
+ * The concurrency is deliberately **not observable in the answer**: results
297
+ * are collected per filter and concatenated in filter order, so the returned
298
+ * array is identical to the serial one, and a failure reports the
299
+ * lowest-indexed filter's error rather than whichever lost the race.
244
300
  */
245
301
  async queryAll(
246
302
  filters: Record<string, unknown>[],
247
- options: { pageSize?: number; maxPages?: number } = {},
303
+ options: QueryAllOptions = {},
248
304
  ): Promise<SignedEvent[]> {
249
305
  const pageSize = options.pageSize ?? RELAY_PAGE_CEILING
250
306
  const maxPages = options.maxPages ?? 100
307
+ const concurrency = Math.max(1, options.concurrency ?? DEFAULT_QUERY_CONCURRENCY)
308
+
309
+ /*
310
+ Per filter, in filter order — not one shared accumulator.
311
+
312
+ Concurrency must not be observable in the answer. Collecting each
313
+ filter's pages into its own slot and concatenating in order at the end
314
+ makes the output byte-identical to the serial version, whatever order the
315
+ responses actually arrive in. Dedup then runs over that ordered
316
+ concatenation, so an id first seen under filter 0 still belongs to filter
317
+ 0's run of events, exactly as before.
318
+ */
319
+ const perFilter: SignedEvent[][] = new Array(filters.length)
320
+ const failures: unknown[] = new Array(filters.length)
321
+
322
+ let next = 0
323
+ let failed = false
324
+
325
+ const worker = async (): Promise<void> => {
326
+ for (;;) {
327
+ // Stop *starting* filters once one has failed. The serial version never
328
+ // reached them at all; this is as close as a fan-out gets, and it keeps
329
+ // a broken read from firing the whole remaining queue at the relay.
330
+ if (failed) return
331
+ const index = next++
332
+ if (index >= filters.length) return
333
+ try {
334
+ perFilter[index] = await this.pageFilter(filters[index], pageSize, maxPages)
335
+ } catch (error) {
336
+ failures[index] = error
337
+ failed = true
338
+ return
339
+ }
340
+ }
341
+ }
342
+
343
+ await Promise.all(
344
+ Array.from({ length: Math.min(concurrency, filters.length) }, () => worker()),
345
+ )
346
+
347
+ /*
348
+ The lowest-indexed failure, not the first to reject in wall-clock time.
349
+
350
+ Under `Promise.all` the error a caller sees would otherwise depend on
351
+ which request happened to lose the race, so two runs of the same broken
352
+ read could report different filters. Serial order is the one order that
353
+ is reproducible, and it is what the serial version reported.
354
+ */
355
+ const firstFailure = failures.findIndex((error) => error !== undefined)
356
+ if (firstFailure !== -1) throw failures[firstFailure]
357
+
251
358
  const seen = new Set<string>()
252
359
  const out: SignedEvent[] = []
360
+ for (const events of perFilter) {
361
+ for (const e of events) {
362
+ if (seen.has(e.id)) continue
363
+ seen.add(e.id)
364
+ out.push(e)
365
+ }
366
+ }
367
+ return out
368
+ }
253
369
 
254
- for (const filter of filters) {
255
- let until: number | undefined
256
- for (let page = 0; ; page++) {
257
- if (page >= maxPages) {
370
+ /**
371
+ * One filter, paged to exhaustion. The sequential half, and it has to be:
372
+ * `until` is a cursor, so page N+1's request is not known until page N has
373
+ * answered. Only the filters are independent, which is why they are the
374
+ * axis {@link Relay.queryAll} parallelises.
375
+ */
376
+ private async pageFilter(
377
+ filter: Record<string, unknown>,
378
+ pageSize: number,
379
+ maxPages: number,
380
+ ): Promise<SignedEvent[]> {
381
+ const out: SignedEvent[] = []
382
+ let until: number | undefined
383
+ for (let page = 0; ; page++) {
384
+ if (page >= maxPages) {
385
+ throw new Error(
386
+ `queryAll: gave up after ${maxPages} pages — refusing to return a partial set`,
387
+ )
388
+ }
389
+ const events = await this.query([
390
+ { ...filter, limit: pageSize, ...(until === undefined ? {} : { until }) },
391
+ ])
392
+ if (events.length === 0) break
393
+ out.push(...events)
394
+ const oldest = Math.min(...events.map((e) => e.created_at))
395
+ if (until !== undefined && oldest >= until) {
396
+ if (events.length >= pageSize) {
258
397
  throw new Error(
259
- `queryAll: gave up after ${maxPages} pages refusing to return a partial set`,
398
+ `queryAll: more than ${pageSize} events share created_at=${until} cannot page without skipping`,
260
399
  )
261
400
  }
262
- const events = await this.query([
263
- { ...filter, limit: pageSize, ...(until === undefined ? {} : { until }) },
264
- ])
265
- if (events.length === 0) break
266
- for (const e of events) {
267
- if (seen.has(e.id)) continue
268
- seen.add(e.id)
269
- out.push(e)
270
- }
271
- const oldest = Math.min(...events.map((e) => e.created_at))
272
- if (until !== undefined && oldest >= until) {
273
- if (events.length >= pageSize) {
274
- throw new Error(
275
- `queryAll: more than ${pageSize} events share created_at=${until} — cannot page without skipping`,
276
- )
277
- }
278
- break
279
- }
280
- until = oldest
401
+ break
281
402
  }
403
+ until = oldest
282
404
  }
283
405
  return out
284
406
  }
package/src/index.ts CHANGED
@@ -47,7 +47,7 @@
47
47
  /** Bumped by hand with the version in package.json — `test/version.test.ts`
48
48
  * pins the two together. It exists so "the upgrade reached the app" can be
49
49
  * checked by grepping a built bundle rather than by trusting a lockfile. */
50
- export const PROTOCOL_VERSION = '0.2.0'
50
+ export const PROTOCOL_VERSION = '0.4.0'
51
51
 
52
52
  export {
53
53
  // types
@@ -95,6 +95,9 @@ export {
95
95
 
96
96
  export {
97
97
  type AddressPointer,
98
+ type EventPointer,
99
+ encodeNevent,
100
+ decodeNevent,
98
101
  convertBits,
99
102
  bech32Encode,
100
103
  bech32Decode,
@@ -134,9 +137,11 @@ export {
134
137
  type RelayHeaders,
135
138
  type RelayOptions,
136
139
  type FetchLike,
140
+ type QueryAllOptions,
137
141
  parsePublishResponse,
138
142
  parseQueryResponse,
139
143
  RELAY_PAGE_CEILING,
144
+ DEFAULT_QUERY_CONCURRENCY,
140
145
  Relay,
141
146
  } from './bridge.js'
142
147
 
package/src/nip19.ts CHANGED
@@ -161,6 +161,118 @@ const TLV_KIND = 3
161
161
  * TLV order is identifier, relays, author, kind — see the header on why that is
162
162
  * a choice rather than a rule.
163
163
  */
164
+ /**
165
+ * A pointer to **one event**, by its id — NIP-19 `nevent`.
166
+ *
167
+ * The counterpart to `AddressPointer`, and the two are not interchangeable.
168
+ * An address names *whatever is currently at* `(kind, pubkey, d)` and survives
169
+ * its author replacing the event. An event id names one immutable event and
170
+ * nothing else: a `kind:9` message has no `d`, so an address cannot be built
171
+ * for it at all.
172
+ *
173
+ * `author` and `kind` are optional in the format and worth including whenever
174
+ * they are known — a reader that has them can query by author and kind rather
175
+ * than scanning, and a consumer can find the manifest that renders the kind
176
+ * before it has the event.
177
+ */
178
+ export interface EventPointer {
179
+ /** 32-byte event id, hex. */
180
+ id: string
181
+ relays: string[]
182
+ /** Optional in NIP-19; include it when known. */
183
+ pubkey?: string
184
+ /** Optional in NIP-19; include it when known. */
185
+ kind?: number
186
+ }
187
+
188
+ /**
189
+ * `nevent1…` for one event.
190
+ *
191
+ * The TLV layout is `naddr`'s with one difference that matters: type 0 holds
192
+ * the event id as **32 raw bytes**, where an naddr holds the `d` identifier as
193
+ * UTF-8. Encoding an id as text produces a bech32 string every decoder accepts
194
+ * and no relay can answer — the same silent-but-invalid shape the author-length
195
+ * guard below was added for.
196
+ */
197
+ export function encodeNevent(pointer: EventPointer): string {
198
+ const bytes: number[] = []
199
+ const push = (type: number, value: Uint8Array) => {
200
+ if (value.length > 255) throw new Error(`TLV value too long for type ${type}`)
201
+ bytes.push(type, value.length, ...value)
202
+ }
203
+
204
+ const id = hexToBytes(pointer.id)
205
+ if (id.length !== 32) throw new Error(`event id must be 32 bytes, got ${id.length}`)
206
+ push(TLV_IDENTIFIER, id)
207
+
208
+ for (const relay of pointer.relays) push(TLV_RELAY, utf8ToBytes(relay))
209
+
210
+ if (pointer.pubkey !== undefined) {
211
+ const author = hexToBytes(pointer.pubkey)
212
+ if (author.length !== 32) throw new Error(`author must be 32 bytes, got ${author.length}`)
213
+ push(TLV_AUTHOR, author)
214
+ }
215
+
216
+ if (pointer.kind !== undefined) {
217
+ push(
218
+ TLV_KIND,
219
+ new Uint8Array([
220
+ (pointer.kind >>> 24) & 0xff,
221
+ (pointer.kind >>> 16) & 0xff,
222
+ (pointer.kind >>> 8) & 0xff,
223
+ pointer.kind & 0xff,
224
+ ]),
225
+ )
226
+ }
227
+
228
+ return bech32Encode('nevent', convertBits(bytes, 8, 5, true))
229
+ }
230
+
231
+ /** The inverse of `encodeNevent`. Throws on anything that is not an `nevent`. */
232
+ export function decodeNevent(encoded: string): EventPointer {
233
+ const { hrp, data } = bech32Decode(encoded.replace(/^nostr:/i, '').toLowerCase())
234
+ if (hrp !== 'nevent') throw new Error(`expected an nevent, got ${hrp}`)
235
+ const bytes = convertBits(data, 5, 8, false)
236
+
237
+ let id: string | undefined
238
+ let pubkey: string | undefined
239
+ let kind: number | undefined
240
+ const relays: string[] = []
241
+
242
+ for (let i = 0; i < bytes.length; ) {
243
+ const type = bytes[i]
244
+ const length = bytes[i + 1]
245
+ const value = bytes.slice(i + 2, i + 2 + length)
246
+ if (value.length !== length) throw new Error('truncated TLV')
247
+ i += 2 + length
248
+
249
+ switch (type) {
250
+ case TLV_IDENTIFIER:
251
+ if (length !== 32) throw new Error(`event id must be 32 bytes, got ${length}`)
252
+ id = bytesToHex(new Uint8Array(value))
253
+ break
254
+ case TLV_RELAY:
255
+ relays.push(new TextDecoder().decode(new Uint8Array(value)))
256
+ break
257
+ case TLV_AUTHOR:
258
+ if (length !== 32) throw new Error(`author must be 32 bytes, got ${length}`)
259
+ pubkey = bytesToHex(new Uint8Array(value))
260
+ break
261
+ case TLV_KIND:
262
+ if (length !== 4) throw new Error(`kind must be 4 bytes, got ${length}`)
263
+ kind = ((value[0] << 24) | (value[1] << 16) | (value[2] << 8) | value[3]) >>> 0
264
+ break
265
+ // Unknown TLV types are skipped rather than rejected, as in `decodeNaddr`.
266
+ }
267
+ }
268
+
269
+ // Only the id is required. An `nevent` carrying nothing else is legal and
270
+ // still resolvable — by scanning, which is why the optional fields are worth
271
+ // writing when they are known.
272
+ if (id === undefined) throw new Error('nevent is missing its event id')
273
+ return { id, relays, ...(pubkey !== undefined ? { pubkey } : {}), ...(kind !== undefined ? { kind } : {}) }
274
+ }
275
+
164
276
  export function encodeNaddr(pointer: AddressPointer): string {
165
277
  const bytes: number[] = []
166
278
  const push = (type: number, value: Uint8Array) => {