libp2r2p 0.10.7 → 0.10.9

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.
@@ -24,8 +24,8 @@ function stripReferencePrefix (value) {
24
24
  }
25
25
 
26
26
  // Decodes a user reference without performing any network lookup.
27
- // Returns `{ kind: 'pubkey', pubkey, relays, raw }` for npub/nprofile/hex or
28
- // `{ kind: 'nip05', local, domain, raw }` for NIP-05 (standard or extended),
27
+ // Returns `{ type: 'pubkey', pubkey, relays, raw }` for npub/nprofile/hex or
28
+ // `{ type: 'nip05', local, domain, raw }` for NIP-05 (standard or extended),
29
29
  // where `raw` is always the most compact canonical spelling.
30
30
  export function decodeUserReference (value) {
31
31
  if (typeof value !== 'string') return null
@@ -34,13 +34,13 @@ export function decodeUserReference (value) {
34
34
 
35
35
  if (HEX_PUBKEY.test(text)) {
36
36
  const raw = text.toLowerCase()
37
- return { kind: 'pubkey', pubkey: raw, relays: [], raw }
37
+ return { type: 'pubkey', pubkey: raw, relays: [], raw }
38
38
  }
39
39
 
40
40
  if (text.toLowerCase().startsWith('npub1')) {
41
41
  try {
42
42
  const raw = text.toLowerCase()
43
- return { kind: 'pubkey', pubkey: npubDecode(raw), relays: [], raw }
43
+ return { type: 'pubkey', pubkey: npubDecode(raw), relays: [], raw }
44
44
  } catch {
45
45
  return null
46
46
  }
@@ -50,7 +50,7 @@ export function decodeUserReference (value) {
50
50
  try {
51
51
  const raw = text.toLowerCase()
52
52
  const { pubkey, relays } = nprofileDecode(raw)
53
- return { kind: 'pubkey', pubkey, relays, raw }
53
+ return { type: 'pubkey', pubkey, relays, raw }
54
54
  } catch {
55
55
  return null
56
56
  }
@@ -59,7 +59,7 @@ export function decodeUserReference (value) {
59
59
  const nip05 = decodeNip05Identifier(text)
60
60
  if (!nip05) return null
61
61
  const raw = compactNip05Raw(nip05.local, nip05.domain)
62
- return { kind: 'nip05', ...nip05, raw }
62
+ return { type: 'nip05', ...nip05, raw }
63
63
  }
64
64
 
65
65
  // Returns the canonical compact spelling for a user reference, either as a
@@ -68,12 +68,12 @@ export function encodeUserReference (value) {
68
68
  const ref = typeof value === 'string'
69
69
  ? decodeUserReference(value)
70
70
  : value && typeof value === 'object' &&
71
- (value.kind === 'pubkey' || value.kind === 'nip05')
71
+ (value.type === 'pubkey' || value.type === 'nip05')
72
72
  ? value
73
73
  : null
74
74
  if (!ref) {
75
75
  throw new ValidationError('INVALID_USER_REFERENCE', { message: 'Invalid user reference' })
76
76
  }
77
- if (ref.kind === 'pubkey') return ref.raw ?? ref.pubkey
77
+ if (ref.type === 'pubkey') return ref.raw ?? ref.pubkey
78
78
  return ref.raw ?? compactNip05Raw(ref.local, ref.domain)
79
79
  }
package/nip27/index.js CHANGED
@@ -119,7 +119,7 @@ export function decodeReference (value) {
119
119
 
120
120
  const account = decodeUserReference(text)
121
121
  if (account) {
122
- return account.kind === 'pubkey'
122
+ return account.type === 'pubkey'
123
123
  ? {
124
124
  type: 'pubkey',
125
125
  original,
@@ -350,7 +350,7 @@ export function extractMedia (content, { bareNip05 = false, getMimeType } = {})
350
350
  export async function resolveUserReference (value, options = {}) {
351
351
  const account = decodeUserReference(value)
352
352
  if (!account) return null
353
- if (account.kind === 'pubkey') {
353
+ if (account.type === 'pubkey') {
354
354
  return { pubkey: account.pubkey, relays: account.relays, label: account.raw }
355
355
  }
356
356
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libp2r2p",
3
- "version": "0.10.7",
3
+ "version": "0.10.9",
4
4
  "description": "Peer-to-relay-to-peer",
5
5
  "keywords": [
6
6
  "p2r2p",
package/url/app-url.js CHANGED
@@ -9,11 +9,25 @@ import {
9
9
  } from '../nip27/helpers/user-reference.js'
10
10
  import {
11
11
  NAPP_ENTITY_REGEX,
12
- appDecode
12
+ appDecode,
13
+ appEncode,
14
+ naddrDecode
13
15
  } from '../nip19/index.js'
16
+ import {
17
+ DRAFT_SITE_MANIFEST,
18
+ MAIN_SITE_MANIFEST,
19
+ NEXT_SITE_MANIFEST
20
+ } from '../kind/index.js'
14
21
 
15
22
  export const APP_URL_MIN_ENTITY_BODY_LENGTH = 48
16
23
 
24
+ const SITE_MANIFEST_KINDS = new Set([
25
+ MAIN_SITE_MANIFEST,
26
+ NEXT_SITE_MANIFEST,
27
+ DRAFT_SITE_MANIFEST
28
+ ])
29
+ const NADDR_PREFIX = 'naddr1'
30
+
17
31
  const APP_NAME_MAX_LENGTH = 260
18
32
  const CHANNEL_BY_PREFIX = { '+': 'main', '++': 'next', '+++': 'draft' }
19
33
  const PREFIX_BY_CHANNEL = { main: '+', next: '++', draft: '+++' }
@@ -38,6 +52,38 @@ function isValidAppName (appName) {
38
52
  !CONTROL_CHARS.test(appName)
39
53
  }
40
54
 
55
+ // `naddr` already carries the event kind, so it does not need the `+`/`++`/
56
+ // `+++` channel prefix (a leading prefix is still tolerated). Only site
57
+ // manifests are app URLs; the result is canonicalized to the `appEncode`
58
+ // entity so downstream code keeps working unchanged.
59
+ function tryDecodeNaddr (value) {
60
+ if (typeof value !== 'string' || !value) return null
61
+ const body = value.replace(/^\+{1,3}/, '')
62
+ if (!body.startsWith(NADDR_PREFIX)) return null
63
+
64
+ let decoded
65
+ try {
66
+ decoded = naddrDecode(body)
67
+ } catch {
68
+ return null
69
+ }
70
+ if (!SITE_MANIFEST_KINDS.has(decoded.kind)) return null
71
+
72
+ try {
73
+ return {
74
+ type: 'entity',
75
+ entity: appEncode({
76
+ dTag: decoded.identifier,
77
+ pubkey: decoded.pubkey,
78
+ kind: decoded.kind,
79
+ relays: decoded.relays
80
+ })
81
+ }
82
+ } catch {
83
+ return null
84
+ }
85
+ }
86
+
41
87
  // Decodes a raw (still percent-encoded) first path segment such as
42
88
  // `+apps` or `+caf%C3%A9@bob@example.com` or `+3swFhu...`.
43
89
  // Returns:
@@ -47,6 +93,9 @@ function isValidAppName (appName) {
47
93
  // - `null` when the segment is not a valid app URL.
48
94
  export function decodeAppUrl (segment) {
49
95
  if (typeof segment !== 'string' || !segment) return null
96
+ const decodedNaddr = tryDecodeNaddr(segment)
97
+ if (decodedNaddr) return decodedNaddr
98
+
50
99
  const prefixMatch = segment.match(/^\+{1,3}/)
51
100
  if (!prefixMatch) return null
52
101
  const prefix = prefixMatch[0]
@@ -77,7 +126,7 @@ export function decodeAppUrl (segment) {
77
126
  const domain = safeDecode(parts[parts.length - 1])
78
127
  const nip05 = nip05FromLocalDomain(local, domain)
79
128
  if (nip05) {
80
- user = { kind: 'nip05', ...nip05, raw: compactNip05Raw(local, domain) }
129
+ user = { type: 'nip05', ...nip05, raw: compactNip05Raw(local, domain) }
81
130
  appName = parts.slice(0, -2).map(safeDecode).join('@')
82
131
  } else {
83
132
  appName = safeDecode(remainder)
@@ -114,7 +163,7 @@ export function encodeAppUrl ({ appName, channel = 'main', user }) {
114
163
 
115
164
  let encodedAppName = encodeURIComponent(appName)
116
165
  let userText
117
- if (userRef.kind === 'nip05') {
166
+ if (userRef.type === 'nip05') {
118
167
  // Keep `@` raw inside the app name so the verbose NIP-05 form stays
119
168
  // readable (`+my@app@bob@example.com`).
120
169
  encodedAppName = encodedAppName.replace(/%40/g, '@')