libp2r2p 0.10.27 → 0.10.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -534,6 +534,14 @@ returned events; received messages may already have been queued. This is a
534
534
  history completeness failure, not evidence that an outgoing message failed.
535
535
  Existing rewatch/resume and relay-list refresh paths retry pending intervals;
536
536
  there is no dedicated periodic retry timer for a failed history fetch.
537
+ Subscription relay errors forwarded to `onError` include `relay` when known
538
+ and `operation: 'private-channel.subscribe'`. A per-notification wrapper retains
539
+ the native message, name, code, category and WebSocket close fields; `cause`
540
+ references the untouched original error, including its stack and causes.
541
+ Aggregate errors keep their nested errors. This also works with frozen/shared
542
+ errors without leaking attribution between subscribers. Missing relay metadata
543
+ is not inferred from the selected relay list. This does not change reconnection,
544
+ delivery or error classification; processing errors keep their existing path.
537
545
  `lastSeenAt` tracks messages persisted in the incoming queue, not app commits.
538
546
  The default recovery window is seven days; recovery still depends on available
539
547
  relay/seeder data, and retention limits cannot guarantee indefinite delivery.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libp2r2p",
3
- "version": "0.10.27",
3
+ "version": "0.10.28",
4
4
  "description": "Peer-to-relay-to-peer",
5
5
  "keywords": [
6
6
  "p2r2p",
@@ -0,0 +1,14 @@
1
+ // Relay errors can be shared by multiple subscriptions or be frozen. Attach
2
+ // consumer context to a new error and retain the untouched original as cause.
3
+ export function subscriptionError (reason, relay) {
4
+ const message = reason?.message ?? String(reason)
5
+ const error = reason instanceof AggregateError
6
+ ? new AggregateError(reason.errors, message, { cause: reason })
7
+ : new Error(message, { cause: reason })
8
+ for (const key of ['name', 'code', 'category', 'closeCode', 'closeReason', 'wasClean']) {
9
+ if (reason?.[key] !== undefined) error[key] = reason[key]
10
+ }
11
+ error.operation = 'private-channel.subscribe'
12
+ if (typeof relay === 'string') error.relay = relay
13
+ return error
14
+ }
@@ -7,6 +7,7 @@ import { getIykcProofs } from '../content-key/index.js'
7
7
  import { ValidationError } from '../error/index.js'
8
8
  import { normalizeRumor, deliveryInfo } from './helpers/rumor.js'
9
9
  import { incompleteFetchError } from './helpers/fetch-error.js'
10
+ import { subscriptionError } from './helpers/subscription-error.js'
10
11
  import * as nip44v3 from '../nip44-v3/index.js'
11
12
  import { relayPool } from '../relay/index.js'
12
13
  import { JSONL_CHUNK_BYTES, NYM_CARRIER_CHUNK_CHARS } from './helpers/chunk-size.js'
@@ -962,7 +963,7 @@ export function subscribe ({ receiverSigner, iykcSigner, privateChannelSigner =
962
963
  try {
963
964
  for await (const item of events) {
964
965
  if (controller.signal.aborted) continue
965
- if (item.type === 'error') onError?.(item.error)
966
+ if (item.type === 'error') onError?.(subscriptionError(item.error, item.relay))
966
967
  else if (item.type === 'event') await processOuterEvent(item.event)
967
968
  }
968
969
  } catch (error) {