@helia/ipns 10.0.0 → 10.0.1-883ff053

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.
Files changed (84) hide show
  1. package/README.md +3 -7
  2. package/dist/index.min.js +16 -5
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/errors.d.ts +0 -8
  5. package/dist/src/errors.d.ts.map +1 -1
  6. package/dist/src/errors.js +0 -8
  7. package/dist/src/errors.js.map +1 -1
  8. package/dist/src/index.d.ts +68 -31
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +11 -11
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/ipns/publisher.d.ts +2 -2
  13. package/dist/src/ipns/publisher.d.ts.map +1 -1
  14. package/dist/src/ipns/publisher.js +27 -14
  15. package/dist/src/ipns/publisher.js.map +1 -1
  16. package/dist/src/ipns/republisher.d.ts.map +1 -1
  17. package/dist/src/ipns/republisher.js +22 -9
  18. package/dist/src/ipns/republisher.js.map +1 -1
  19. package/dist/src/ipns/resolver.d.ts +2 -2
  20. package/dist/src/ipns/resolver.d.ts.map +1 -1
  21. package/dist/src/ipns/resolver.js +39 -17
  22. package/dist/src/ipns/resolver.js.map +1 -1
  23. package/dist/src/ipns.d.ts +3 -3
  24. package/dist/src/ipns.d.ts.map +1 -1
  25. package/dist/src/ipns.js +8 -8
  26. package/dist/src/ipns.js.map +1 -1
  27. package/dist/src/local-store.d.ts +4 -4
  28. package/dist/src/local-store.d.ts.map +1 -1
  29. package/dist/src/local-store.js +2 -1
  30. package/dist/src/local-store.js.map +1 -1
  31. package/dist/src/pb/ipns.d.ts +29 -29
  32. package/dist/src/pb/ipns.d.ts.map +1 -1
  33. package/dist/src/pb/ipns.js +15 -15
  34. package/dist/src/records.d.ts +27 -142
  35. package/dist/src/records.d.ts.map +1 -1
  36. package/dist/src/records.js +39 -46
  37. package/dist/src/records.js.map +1 -1
  38. package/dist/src/routing/helia.d.ts +5 -5
  39. package/dist/src/routing/helia.d.ts.map +1 -1
  40. package/dist/src/routing/helia.js +3 -3
  41. package/dist/src/routing/helia.js.map +1 -1
  42. package/dist/src/routing/index.d.ts +7 -7
  43. package/dist/src/routing/index.d.ts.map +1 -1
  44. package/dist/src/routing/index.js +2 -2
  45. package/dist/src/routing/index.js.map +1 -1
  46. package/dist/src/routing/local-store.d.ts +1 -1
  47. package/dist/src/routing/local-store.d.ts.map +1 -1
  48. package/dist/src/routing/local-store.js +3 -3
  49. package/dist/src/routing/local-store.js.map +1 -1
  50. package/dist/src/routing/pubsub.d.ts +11 -11
  51. package/dist/src/routing/pubsub.d.ts.map +1 -1
  52. package/dist/src/routing/pubsub.js +11 -12
  53. package/dist/src/routing/pubsub.js.map +1 -1
  54. package/dist/src/selector.d.ts +2 -2
  55. package/dist/src/selector.d.ts.map +1 -1
  56. package/dist/src/selector.js +13 -9
  57. package/dist/src/selector.js.map +1 -1
  58. package/dist/src/utils.d.ts +10 -11
  59. package/dist/src/utils.d.ts.map +1 -1
  60. package/dist/src/utils.js +20 -128
  61. package/dist/src/utils.js.map +1 -1
  62. package/dist/src/validator.d.ts +9 -3
  63. package/dist/src/validator.d.ts.map +1 -1
  64. package/dist/src/validator.js +57 -14
  65. package/dist/src/validator.js.map +1 -1
  66. package/package.json +6 -31
  67. package/src/errors.ts +0 -10
  68. package/src/index.ts +85 -36
  69. package/src/ipns/publisher.ts +29 -16
  70. package/src/ipns/republisher.ts +31 -13
  71. package/src/ipns/resolver.ts +40 -22
  72. package/src/ipns.ts +11 -11
  73. package/src/local-store.ts +8 -7
  74. package/src/pb/ipns.proto +1 -1
  75. package/src/pb/ipns.ts +37 -37
  76. package/src/records.ts +57 -210
  77. package/src/routing/helia.ts +6 -6
  78. package/src/routing/index.ts +7 -7
  79. package/src/routing/local-store.ts +6 -6
  80. package/src/routing/pubsub.ts +24 -25
  81. package/src/selector.ts +14 -11
  82. package/src/utils.ts +26 -148
  83. package/src/validator.ts +73 -16
  84. package/dist/typedoc-urls.json +0 -49
package/src/utils.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isPublicKey } from '@helia/interface'
2
+ import * as dagCbor from '@ipld/dag-cbor'
2
3
  import { InvalidParametersError } from '@libp2p/interface'
3
- import * as cborg from 'cborg'
4
4
  import { Key } from 'interface-datastore'
5
5
  import { base36 } from 'multiformats/bases/base36'
6
6
  import { base58btc } from 'multiformats/bases/base58'
@@ -10,12 +10,12 @@ import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
10
10
  import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
11
11
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
12
12
  import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
13
+ import { withArrayBuffer } from 'uint8arrays/with-array-buffer'
13
14
  import { DHT_EXPIRY_MS, REPUBLISH_THRESHOLD } from './constants.ts'
14
- import { InvalidEmbeddedPublicKeyError, InvalidRecordDataError, InvalidValueError, RecordTooLargeError, SignatureVerificationError, UnsupportedValidityError } from './errors.ts'
15
- import { IpnsEntry } from './pb/ipns.ts'
16
- import type { IPNSRecord, IPNSRecordV2, IPNSRecordData } from './records.ts'
17
- import type { PublicKey, Keychain } from '@helia/interface'
18
- import type { AbortOptions } from '@libp2p/interface'
15
+ import { InvalidRecordDataError, InvalidValueError, SignatureVerificationError, UnsupportedValidityError } from './errors.ts'
16
+ import { IPNSEntry } from './pb/ipns.ts'
17
+ import type { IPNSRecordData } from './index.ts'
18
+ import type { PublicKey } from '@helia/interface'
19
19
  import type { MultibaseDecoder } from 'multiformats/cid'
20
20
  import type { MultihashDigest } from 'multiformats/hashes/interface'
21
21
 
@@ -23,11 +23,6 @@ export const LIBP2P_KEY_CODEC = 0x72
23
23
  export const IDENTITY_CODEC = 0x0
24
24
  export const SHA2_256_CODEC = 0x12
25
25
 
26
- /**
27
- * Limit valid IPNS record sizes to 10kb
28
- */
29
- const MAX_RECORD_SIZE = 1024 * 10
30
-
31
26
  const IPNS_PREFIX = uint8ArrayFromString('/ipns/')
32
27
  export const IPNS_STRING_PREFIX = '/ipns/'
33
28
 
@@ -60,10 +55,9 @@ export function ipnsMetadataKey (key: Uint8Array): Key {
60
55
  return new Key(IPNS_METADATA_PREFIX + uint8ArrayToString(key, 'base32'), false)
61
56
  }
62
57
 
63
- export function shouldRepublish (ipnsRecord: IPNSRecord, created: Date): boolean {
58
+ export function shouldRepublish (created: Date, expiry: Date): boolean {
64
59
  const now = Date.now()
65
60
  const dhtExpiry = created.getTime() + DHT_EXPIRY_MS
66
- const recordExpiry = new Date(ipnsRecord.validity).getTime()
67
61
 
68
62
  // If the DHT expiry is within the threshold, republish it
69
63
  if (dhtExpiry - now < REPUBLISH_THRESHOLD) {
@@ -71,7 +65,7 @@ export function shouldRepublish (ipnsRecord: IPNSRecord, created: Date): boolean
71
65
  }
72
66
 
73
67
  // If the record expiry (based on validity/lifetime) is within the threshold, republish it
74
- if (recordExpiry - now < REPUBLISH_THRESHOLD) {
68
+ if (expiry.getTime() - now < REPUBLISH_THRESHOLD) {
75
69
  return true
76
70
  }
77
71
 
@@ -101,15 +95,14 @@ export function isLibp2pCID (obj?: any): obj is CID<unknown, 0x72, 0x00 | 0x12,
101
95
  /**
102
96
  * Utility for creating the record data for being signed
103
97
  */
104
- export function ipnsRecordDataForV1Sig (value: string, validityType: IpnsEntry.ValidityType, validity: Uint8Array): Uint8Array {
98
+ export function ipnsRecordDataForV1Sig (value: Uint8Array, validityType: IPNSEntry.ValidityType, validity: Uint8Array): Uint8Array {
105
99
  const validityTypeBuffer = uint8ArrayFromString(validityType)
106
- const valueBytes = uint8ArrayFromString(value)
107
100
 
108
101
  return uint8ArrayConcat([
109
- valueBytes,
102
+ value,
110
103
  validity,
111
104
  validityTypeBuffer
112
- ], valueBytes.byteLength + validity.byteLength + validityTypeBuffer.byteLength)
105
+ ], value.byteLength + validity.byteLength + validityTypeBuffer.byteLength)
113
106
  }
114
107
 
115
108
  /**
@@ -121,37 +114,7 @@ export function ipnsRecordDataForV2Sig (data: Uint8Array): Uint8Array {
121
114
  return uint8ArrayConcat([entryData, data])
122
115
  }
123
116
 
124
- export function marshalIPNSRecord (obj: IPNSRecord | IPNSRecordV2): Uint8Array {
125
- let publicKey: Uint8Array | undefined = obj.publicKey?.toProtobuf()
126
-
127
- // do not embed public keys whose multihash is an identity hash as these can
128
- // be derived from the routing key
129
- if (obj.publicKey?.toMultihash().code === 0x00) {
130
- publicKey = undefined
131
- }
132
-
133
- if ('signatureV1' in obj) {
134
- return IpnsEntry.encode({
135
- value: uint8ArrayFromString(obj.value),
136
- signatureV1: obj.signatureV1,
137
- validityType: obj.validityType,
138
- validity: uint8ArrayFromString(obj.validity),
139
- sequence: obj.sequence,
140
- ttl: obj.ttl,
141
- publicKey,
142
- signatureV2: obj.signatureV2,
143
- data: obj.data
144
- })
145
- } else {
146
- return IpnsEntry.encode({
147
- publicKey,
148
- signatureV2: obj.signatureV2,
149
- data: obj.data
150
- })
151
- }
152
- }
153
-
154
- function valueToString (value: Uint8Array): string {
117
+ export function ipnsRecordValueToString (value: Uint8Array): string {
155
118
  // handle legacy case where record value is raw CID bytes
156
119
  try {
157
120
  const cid = CID.decode(value)
@@ -163,76 +126,6 @@ function valueToString (value: Uint8Array): string {
163
126
  return uint8ArrayToString(value)
164
127
  }
165
128
 
166
- export async function unmarshalIPNSRecord (routingKey: Uint8Array, marshalledRecord: Uint8Array, keychain: Keychain, options?: AbortOptions): Promise<IPNSRecord> {
167
- if (marshalledRecord.byteLength > MAX_RECORD_SIZE) {
168
- throw new RecordTooLargeError('The record is too large')
169
- }
170
-
171
- const message = IpnsEntry.decode(marshalledRecord)
172
-
173
- // Check if we have the data field. If we don't, we fail. We've been producing
174
- // V1+V2 records for quite a while and we don't support V1-only records during
175
- // validation any more
176
- if (message.signatureV2 == null || message.data == null) {
177
- throw new SignatureVerificationError('Missing data or signatureV2')
178
- }
179
-
180
- const data = parseCborData(message.data)
181
- const validity = uint8ArrayToString(data.Validity)
182
-
183
- let publicKey: PublicKey | undefined
184
-
185
- // try to extract public key from routing key
186
- const routingMultihash = multihashFromIPNSRoutingKey(routingKey)
187
-
188
- // identity hash
189
- if (isCodec(routingMultihash, 0x0)) {
190
- publicKey = await keychain.loadPublicKeyFromProtobuf(routingMultihash.digest, options)
191
- }
192
-
193
- // otherwise try to load key from message
194
- if (publicKey == null && message.publicKey != null) {
195
- publicKey = await keychain.loadPublicKeyFromProtobuf(message.publicKey, options)
196
- }
197
-
198
- if (publicKey == null) {
199
- throw new InvalidEmbeddedPublicKeyError('Could not extract public key from IPNS record or routing key')
200
- }
201
-
202
- if (message.value != null && message.signatureV1 != null) {
203
- // V1+V2
204
- validateCborDataMatchesPbData(message)
205
-
206
- return {
207
- value: valueToString(data.Value),
208
- validityType: IpnsEntry.ValidityType.EOL,
209
- validity,
210
- sequence: data.Sequence,
211
- ttl: data.TTL,
212
- publicKey,
213
- signatureV1: message.signatureV1,
214
- signatureV2: message.signatureV2,
215
- data: message.data,
216
- bytes: marshalledRecord
217
- }
218
- } else if (message.signatureV2 != null) {
219
- // V2-only
220
- return {
221
- value: valueToString(data.Value),
222
- validityType: IpnsEntry.ValidityType.EOL,
223
- validity,
224
- sequence: data.Sequence,
225
- ttl: data.TTL,
226
- publicKey,
227
- signatureV2: message.signatureV2,
228
- data: message.data,
229
- bytes: marshalledRecord
230
- }
231
- } else {
232
- throw new Error('invalid record: does not include signatureV1 or signatureV2')
233
- }
234
- }
235
-
236
129
  export function multihashToIPNSRoutingKey (digest: MultihashDigest): Uint8Array {
237
130
  return uint8ArrayConcat([
238
131
  IPNS_PREFIX,
@@ -244,32 +137,23 @@ export function multihashFromIPNSRoutingKey (key: Uint8Array): MultihashDigest {
244
137
  return Digest.decode(key.slice(IPNS_PREFIX.length))
245
138
  }
246
139
 
247
- export function createCborData (value: string, validityType: IpnsEntry.ValidityType, validity: Uint8Array, sequence: bigint, ttl: bigint): Uint8Array {
248
- let ValidityType
249
-
250
- if (validityType === IpnsEntry.ValidityType.EOL) {
251
- ValidityType = 0
252
- } else {
253
- throw new UnsupportedValidityError('The validity type is unsupported')
254
- }
140
+ export function encodeExtensibleData (data?: IPNSRecordData): Uint8Array<ArrayBuffer> {
141
+ return withArrayBuffer(dagCbor.encode(data))
142
+ }
255
143
 
256
- const data = {
257
- Value: uint8ArrayFromString(value),
258
- Validity: validity,
259
- ValidityType,
260
- Sequence: sequence,
261
- TTL: ttl
144
+ export function decodeExtensibleData (buf?: Uint8Array): IPNSRecordData {
145
+ if (buf == null) {
146
+ throw new InvalidRecordDataError('Record data is missing')
262
147
  }
263
148
 
264
- return cborg.encode(data)
265
- }
266
-
267
- export function parseCborData (buf: Uint8Array): IPNSRecordData {
268
- const data = cborg.decode(buf)
149
+ const data = dagCbor.decode<IPNSRecordData>(buf)
269
150
 
151
+ // @ts-expect-error TODO: remove typescript enums
270
152
  if (data.ValidityType === 0) {
271
- data.ValidityType = IpnsEntry.ValidityType.EOL
272
- } else {
153
+ data.ValidityType = IPNSEntry.ValidityType.EOL
154
+ }
155
+
156
+ if (data.ValidityType !== IPNSEntry.ValidityType.EOL) {
273
157
  throw new UnsupportedValidityError('The validity type is unsupported')
274
158
  }
275
159
 
@@ -335,7 +219,7 @@ function isMultihashDigest (obj: any): obj is MultihashDigest {
335
219
  return typeof obj.code === 'number' && obj.digest instanceof Uint8Array && typeof obj.size === 'number' && obj.bytes instanceof Uint8Array
336
220
  }
337
221
 
338
- export function normalizeKey (key?: PublicKey | CID<unknown, 0x72> | MultihashDigest | string): { digest: MultihashDigest, path: string } {
222
+ export function normalizeKey (key?: PublicKey | CID | MultihashDigest | string): { digest: MultihashDigest, path: string } {
339
223
  if (key != null) {
340
224
  if (isPublicKey(key)) {
341
225
  return {
@@ -397,13 +281,7 @@ export function normalizeKey (key?: PublicKey | CID<unknown, 0x72> | MultihashDi
397
281
  throw new InvalidValueError('Value must be a valid IPNS path starting with /')
398
282
  }
399
283
 
400
- function validateCborDataMatchesPbData (entry: IpnsEntry): void {
401
- if (entry.data == null) {
402
- throw new InvalidRecordDataError('Record data is missing')
403
- }
404
-
405
- const data = parseCborData(entry.data)
406
-
284
+ export function validateCborDataMatchesPbData (entry: IPNSEntry, data: IPNSRecordData): void {
407
285
  if (!uint8ArrayEquals(data.Value, entry.value ?? new Uint8Array(0))) {
408
286
  throw new SignatureVerificationError('Field "value" did not match between protobuf and CBOR')
409
287
  }
package/src/validator.ts CHANGED
@@ -1,27 +1,75 @@
1
1
  import NanoDate from 'timestamp-nano'
2
- import { InvalidEmbeddedPublicKeyError, RecordExpiredError, SignatureVerificationError, UnsupportedValidityError } from './errors.ts'
3
- import { IpnsEntry } from './pb/ipns.ts'
4
- import { ipnsRecordDataForV2Sig } from './utils.ts'
5
- import type { IPNSRecord } from './index.ts'
2
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
3
+ import { InvalidEmbeddedPublicKeyError, RecordExpiredError, RecordTooLargeError, SignatureVerificationError, UnsupportedValidityError } from './errors.ts'
4
+ import { IPNSEntry } from './pb/ipns.ts'
5
+ import { decodeExtensibleData, ipnsRecordDataForV2Sig, isCodec, multihashFromIPNSRoutingKey, validateCborDataMatchesPbData } from './utils.ts'
6
+ import type { PublicKey } from '@ipshipyard/crypto'
7
+ import type { Keychain } from '@ipshipyard/keychain'
6
8
  import type { AbortOptions } from '@libp2p/interface'
7
9
 
10
+ /**
11
+ * Limit valid IPNS record sizes to 10kb
12
+ */
13
+ const MAX_RECORD_SIZE = 1024 * 10
14
+
8
15
  /**
9
16
  * Validate the given IPNS record against the given routing key.
10
17
  *
18
+ * Ensure that
19
+ * - SignatureV2 and Data are present
20
+ * - ValidityType and Validity are of valid types and have a value
21
+ * - CBOR data matches protobuf if it's a V1+V2 record
22
+ *
11
23
  * @see https://specs.ipfs.tech/ipns/ipns-record/#routing-record for the binary
12
24
  * format of the routing key
13
25
  */
14
- export async function ipnsValidator (record: IPNSRecord, options?: AbortOptions): Promise<void> {
15
- if (record.publicKey == null) {
16
- throw new InvalidEmbeddedPublicKeyError('The record had no public key associated with it')
26
+ export async function ipnsValidator (routingKey: Uint8Array, marshalledRecord: Uint8Array, keychain: Keychain, options?: AbortOptions): Promise<IPNSEntry> {
27
+ if (marshalledRecord.byteLength > MAX_RECORD_SIZE) {
28
+ throw new RecordTooLargeError('The record is too large')
29
+ }
30
+
31
+ const record = IPNSEntry.decode(marshalledRecord)
32
+
33
+ // Check if we have the data field. If we don't, we fail. We've been producing
34
+ // V1+V2 records for quite a while and we don't support V1-only records during
35
+ // validation any more
36
+ if (record.signatureV2 == null) {
37
+ throw new SignatureVerificationError('Missing signatureV2')
38
+ }
39
+
40
+ const data = decodeExtensibleData(record.data)
41
+ const validity = uint8ArrayToString(data.Validity)
42
+
43
+ let publicKey: PublicKey | undefined
44
+
45
+ // try to extract public key from routing key
46
+ const routingMultihash = multihashFromIPNSRoutingKey(routingKey)
47
+
48
+ // identity hash
49
+ if (isCodec(routingMultihash, 0x0)) {
50
+ publicKey = await keychain.loadPublicKeyFromProtobuf(routingMultihash.digest, options)
51
+ }
52
+
53
+ // otherwise try to load key from message
54
+ if (publicKey == null && record.publicKey != null) {
55
+ publicKey = await keychain.loadPublicKeyFromProtobuf(record.publicKey, options)
56
+ }
57
+
58
+ if (publicKey == null) {
59
+ throw new InvalidEmbeddedPublicKeyError('Could not extract public key from IPNS record or routing key')
17
60
  }
18
61
 
19
62
  // Validate Signature V2
20
63
  let isValid
21
64
 
22
65
  try {
66
+ if (record.data == null) {
67
+ // n.b. decodeExtensibleData would have thrown if record data was missing
68
+ throw new Error('Missing data')
69
+ }
70
+
23
71
  const dataForSignature = ipnsRecordDataForV2Sig(record.data)
24
- isValid = await record.publicKey.verify(dataForSignature, record.signatureV2, options)
72
+ isValid = await publicKey.verify(dataForSignature, record.signatureV2, options)
25
73
  } catch {
26
74
  isValid = false
27
75
  }
@@ -31,13 +79,20 @@ export async function ipnsValidator (record: IPNSRecord, options?: AbortOptions)
31
79
  }
32
80
 
33
81
  // Validate according to the validity type
34
- if (record.validityType === IpnsEntry.ValidityType.EOL) {
35
- if (NanoDate.fromString(record.validity).toDate().getTime() < Date.now()) {
82
+ if (data.ValidityType === IPNSEntry.ValidityType.EOL) {
83
+ if (NanoDate.fromString(validity).toDate().getTime() < Date.now()) {
36
84
  throw new RecordExpiredError('record has expired')
37
85
  }
38
- } else if (record.validityType != null) {
39
- throw new UnsupportedValidityError('The validity type is unsupported')
86
+ } else if (data.ValidityType != null) {
87
+ throw new UnsupportedValidityError(`The validity type ${data.ValidityType} is unsupported`)
88
+ }
89
+
90
+ if (record.value != null && record.signatureV1 != null) {
91
+ // V1+V2
92
+ validateCborDataMatchesPbData(record, data)
40
93
  }
94
+
95
+ return record
41
96
  }
42
97
 
43
98
  /**
@@ -47,16 +102,18 @@ export async function ipnsValidator (record: IPNSRecord, options?: AbortOptions)
47
102
  * @param record - The IPNS record to validate.
48
103
  * @returns The number of milliseconds until the record expires, or 0 if the record is already expired.
49
104
  */
50
- export function validFor (record: IPNSRecord): number {
51
- if (record.validityType !== IpnsEntry.ValidityType.EOL) {
105
+ export function validFor (record: IPNSEntry): number {
106
+ const data = decodeExtensibleData(record.data)
107
+
108
+ if (data.ValidityType !== IPNSEntry.ValidityType.EOL) {
52
109
  throw new UnsupportedValidityError()
53
110
  }
54
111
 
55
- if (record.validity == null) {
112
+ if (data.Validity == null) {
56
113
  throw new UnsupportedValidityError()
57
114
  }
58
115
 
59
- const validUntil = NanoDate.fromString(record.validity).toDate().getTime()
116
+ const validUntil = NanoDate.fromString(uint8ArrayToString(data.Validity)).toDate().getTime()
60
117
  const now = Date.now()
61
118
 
62
119
  if (validUntil < now) {
@@ -1,49 +0,0 @@
1
- {
2
- "IPNS": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNS.html",
3
- ".:IPNS": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNS.html",
4
- "IPNSComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSComponents.html",
5
- ".:IPNSComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSComponents.html",
6
- "IPNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSOptions.html",
7
- ".:IPNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSOptions.html",
8
- "IPNSRecordMetadata": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSRecordMetadata.html",
9
- ".:IPNSRecordMetadata": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSRecordMetadata.html",
10
- "IPNSResolver": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSResolver.html",
11
- ".:IPNSResolver": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSResolver.html",
12
- "IPNSResolverOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSResolverOptions.html",
13
- ".:IPNSResolverOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSResolverOptions.html",
14
- "PublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.PublishOptions.html",
15
- ".:PublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.PublishOptions.html",
16
- "PublishResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.PublishResult.html",
17
- ".:PublishResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.PublishResult.html",
18
- "ResolveOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveOptions.html",
19
- ".:ResolveOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveOptions.html",
20
- "ResolveResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveResult.html",
21
- ".:ResolveResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveResult.html",
22
- "DatastoreProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.DatastoreProgressEvents.html",
23
- ".:DatastoreProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.DatastoreProgressEvents.html",
24
- "IPNSRecord": "https://ipfs.github.io/helia/types/_helia_ipns.index.IPNSRecord.html",
25
- "PublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.PublishProgressEvents.html",
26
- ".:PublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.PublishProgressEvents.html",
27
- "ResolveProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.ResolveProgressEvents.html",
28
- ".:ResolveProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.ResolveProgressEvents.html",
29
- "ipns": "https://ipfs.github.io/helia/functions/_helia_ipns.index.ipns.html",
30
- ".:ipns": "https://ipfs.github.io/helia/functions/_helia_ipns.index.ipns.html",
31
- "ipnsResolver": "https://ipfs.github.io/helia/functions/_helia_ipns.index.ipnsResolver.html",
32
- ".:ipnsResolver": "https://ipfs.github.io/helia/functions/_helia_ipns.index.ipnsResolver.html",
33
- "GetOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.GetOptions.html",
34
- "./routing:GetOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.GetOptions.html",
35
- "IPNSRouting": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.IPNSRouting.html",
36
- "./routing:IPNSRouting": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.IPNSRouting.html",
37
- "Message": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.Message.html",
38
- "PubSub": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PubSub.html",
39
- "PubSubEvents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PubSubEvents.html",
40
- "PubsubRoutingComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PubsubRoutingComponents.html",
41
- "PutOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PutOptions.html",
42
- "./routing:PutOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PutOptions.html",
43
- "HeliaRoutingProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.routing.HeliaRoutingProgressEvents.html",
44
- "IPNSRoutingProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.routing.IPNSRoutingProgressEvents.html",
45
- "./routing:IPNSRoutingProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.routing.IPNSRoutingProgressEvents.html",
46
- "PubSubProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.routing.PubSubProgressEvents.html",
47
- "helia": "https://ipfs.github.io/helia/functions/_helia_ipns.routing.helia.html",
48
- "pubsub": "https://ipfs.github.io/helia/functions/_helia_ipns.routing.pubsub.html"
49
- }