@helia/ipns 5.0.0 → 6.0.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/README.md +83 -12
- package/dist/index.min.js +4 -4
- package/dist/src/index.d.ts +91 -16
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +99 -15
- package/dist/src/index.js.map +1 -1
- package/dist/typedoc-urls.json +2 -0
- package/package.json +1 -1
- package/src/index.ts +111 -24
package/src/index.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* With {@link IPNSRouting} routers:
|
|
9
9
|
*
|
|
10
|
-
* ```
|
|
10
|
+
* ```TypeScript
|
|
11
11
|
* import { createHelia } from 'helia'
|
|
12
12
|
* import { ipns } from '@helia/ipns'
|
|
13
13
|
* import { unixfs } from '@helia/unixfs'
|
|
@@ -27,7 +27,78 @@
|
|
|
27
27
|
* await name.publish(peerId, cid)
|
|
28
28
|
*
|
|
29
29
|
* // resolve the name
|
|
30
|
-
* const
|
|
30
|
+
* const result = name.resolve(peerId)
|
|
31
|
+
*
|
|
32
|
+
* console.info(result.cid, result.path)
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Publishing a recursive record
|
|
36
|
+
*
|
|
37
|
+
* A recursive record is a one that points to another record rather than to a
|
|
38
|
+
* value.
|
|
39
|
+
*
|
|
40
|
+
* ```TypeScript
|
|
41
|
+
* import { createHelia } from 'helia'
|
|
42
|
+
* import { ipns } from '@helia/ipns'
|
|
43
|
+
* import { unixfs } from '@helia/unixfs'
|
|
44
|
+
*
|
|
45
|
+
* const helia = await createHelia()
|
|
46
|
+
* const name = ipns(helia)
|
|
47
|
+
*
|
|
48
|
+
* // create a public key to publish as an IPNS name
|
|
49
|
+
* const keyInfo = await helia.libp2p.services.keychain.createKey('my-key')
|
|
50
|
+
* const peerId = await helia.libp2p.services.keychain.exportPeerId(keyInfo.name)
|
|
51
|
+
*
|
|
52
|
+
* // store some data to publish
|
|
53
|
+
* const fs = unixfs(helia)
|
|
54
|
+
* const cid = await fs.add(Uint8Array.from([0, 1, 2, 3, 4]))
|
|
55
|
+
*
|
|
56
|
+
* // publish the name
|
|
57
|
+
* await name.publish(peerId, cid)
|
|
58
|
+
*
|
|
59
|
+
* // create another public key to re-publish the original record
|
|
60
|
+
* const recursiveKeyInfo = await helia.libp2p.services.keychain.createKey('my-recursive-key')
|
|
61
|
+
* const recursivePeerId = await helia.libp2p.services.keychain.exportPeerId(recursiveKeyInfo.name)
|
|
62
|
+
*
|
|
63
|
+
* // publish the recursive name
|
|
64
|
+
* await name.publish(recursivePeerId, peerId)
|
|
65
|
+
*
|
|
66
|
+
* // resolve the name recursively - it resolves until a CID is found
|
|
67
|
+
* const result = name.resolve(recursivePeerId)
|
|
68
|
+
* console.info(result.cid.toString() === cid.toString()) // true
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example Publishing a record with a path
|
|
72
|
+
*
|
|
73
|
+
* It is possible to publish CIDs with an associated path.
|
|
74
|
+
*
|
|
75
|
+
* ```TypeScript
|
|
76
|
+
* import { createHelia } from 'helia'
|
|
77
|
+
* import { ipns } from '@helia/ipns'
|
|
78
|
+
* import { unixfs } from '@helia/unixfs'
|
|
79
|
+
*
|
|
80
|
+
* const helia = await createHelia()
|
|
81
|
+
* const name = ipns(helia)
|
|
82
|
+
*
|
|
83
|
+
* // create a public key to publish as an IPNS name
|
|
84
|
+
* const keyInfo = await helia.libp2p.services.keychain.createKey('my-key')
|
|
85
|
+
* const peerId = await helia.libp2p.services.keychain.exportPeerId(keyInfo.name)
|
|
86
|
+
*
|
|
87
|
+
* // store some data to publish
|
|
88
|
+
* const fs = unixfs(helia)
|
|
89
|
+
* const fileCid = await fs.add(Uint8Array.from([0, 1, 2, 3, 4]))
|
|
90
|
+
*
|
|
91
|
+
* // store the file in a directory
|
|
92
|
+
* const dirCid = await fs.mkdir()
|
|
93
|
+
* const finalDirCid = await fs.cp(fileCid, dirCid, '/foo.txt')
|
|
94
|
+
*
|
|
95
|
+
* // publish the name
|
|
96
|
+
* await name.publish(peerId, `/ipfs/${finalDirCid}/foo.txt)
|
|
97
|
+
*
|
|
98
|
+
* // resolve the name
|
|
99
|
+
* const result = name.resolve(peerId)
|
|
100
|
+
*
|
|
101
|
+
* console.info(result.cid, result.path) // QmFoo.. 'foo.txt'
|
|
31
102
|
* ```
|
|
32
103
|
*
|
|
33
104
|
* @example Using custom PubSub router
|
|
@@ -46,7 +117,7 @@
|
|
|
46
117
|
* and multiple peers are listening on the topic(s), otherwise update messages
|
|
47
118
|
* may fail to be published with "Insufficient peers" errors.
|
|
48
119
|
*
|
|
49
|
-
* ```
|
|
120
|
+
* ```TypeScript
|
|
50
121
|
* import { createHelia, libp2pDefaults } from 'helia'
|
|
51
122
|
* import { ipns } from '@helia/ipns'
|
|
52
123
|
* import { pubsub } from '@helia/ipns/routing'
|
|
@@ -77,14 +148,14 @@
|
|
|
77
148
|
* await name.publish(peerId, cid)
|
|
78
149
|
*
|
|
79
150
|
* // resolve the name
|
|
80
|
-
* const cid = name.resolve(peerId)
|
|
151
|
+
* const { cid, path } = name.resolve(peerId)
|
|
81
152
|
* ```
|
|
82
153
|
*
|
|
83
154
|
* @example Using custom DNS over HTTPS resolvers
|
|
84
155
|
*
|
|
85
156
|
* With default {@link DNSResolver} resolvers:
|
|
86
157
|
*
|
|
87
|
-
* ```
|
|
158
|
+
* ```TypeScript
|
|
88
159
|
* import { createHelia } from 'helia'
|
|
89
160
|
* import { ipns } from '@helia/ipns'
|
|
90
161
|
* import { unixfs } from '@helia/unixfs'
|
|
@@ -97,14 +168,14 @@
|
|
|
97
168
|
* ]
|
|
98
169
|
* })
|
|
99
170
|
*
|
|
100
|
-
* const cid = name.resolveDns('some-domain-with-dnslink-entry.com')
|
|
171
|
+
* const { cid, path } = name.resolveDns('some-domain-with-dnslink-entry.com')
|
|
101
172
|
* ```
|
|
102
173
|
*
|
|
103
174
|
* @example Resolving a domain with a dnslink entry
|
|
104
175
|
*
|
|
105
176
|
* Calling `resolveDns` with the `@helia/ipns` instance:
|
|
106
177
|
*
|
|
107
|
-
* ```
|
|
178
|
+
* ```TypeScript
|
|
108
179
|
* // resolve a CID from a TXT record in a DNS zone file, using the default
|
|
109
180
|
* // resolver for the current platform eg:
|
|
110
181
|
* // > dig _dnslink.ipfs.io TXT
|
|
@@ -114,7 +185,7 @@
|
|
|
114
185
|
* // ;; ANSWER SECTION:
|
|
115
186
|
* // _dnslink.website.ipfs.io. 60 IN TXT "dnslink=/ipfs/QmWebsite"
|
|
116
187
|
*
|
|
117
|
-
* const cid = name.resolveDns('ipfs.io')
|
|
188
|
+
* const { cid, path } = name.resolveDns('ipfs.io')
|
|
118
189
|
*
|
|
119
190
|
* console.info(cid)
|
|
120
191
|
* // QmWebsite
|
|
@@ -128,11 +199,11 @@
|
|
|
128
199
|
*
|
|
129
200
|
* If this is a concern, use the DNS-JSON-Over-HTTPS resolver instead.
|
|
130
201
|
*
|
|
131
|
-
* ```
|
|
202
|
+
* ```TypeScript
|
|
132
203
|
* // use DNS-Over-HTTPS
|
|
133
204
|
* import { dnsOverHttps } from '@helia/ipns/dns-resolvers'
|
|
134
205
|
*
|
|
135
|
-
* const cid = name.resolveDns('ipfs.io', {
|
|
206
|
+
* const { cid, path } = name.resolveDns('ipfs.io', {
|
|
136
207
|
* resolvers: [
|
|
137
208
|
* dnsOverHttps('https://mozilla.cloudflare-dns.com/dns-query')
|
|
138
209
|
* ]
|
|
@@ -144,11 +215,11 @@
|
|
|
144
215
|
* DNS-JSON-Over-HTTPS resolvers use the RFC 8427 `application/dns-json` and can
|
|
145
216
|
* result in a smaller browser bundle due to the response being plain JSON.
|
|
146
217
|
*
|
|
147
|
-
* ```
|
|
218
|
+
* ```TypeScript
|
|
148
219
|
* // use DNS-JSON-Over-HTTPS
|
|
149
220
|
* import { dnsJsonOverHttps } from '@helia/ipns/dns-resolvers'
|
|
150
221
|
*
|
|
151
|
-
* const cid = name.resolveDns('ipfs.io', {
|
|
222
|
+
* const { cid, path } = name.resolveDns('ipfs.io', {
|
|
152
223
|
* resolvers: [
|
|
153
224
|
* dnsJsonOverHttps('https://mozilla.cloudflare-dns.com/dns-query')
|
|
154
225
|
* ]
|
|
@@ -266,24 +337,29 @@ export interface RepublishOptions extends AbortOptions, ProgressOptions<Republis
|
|
|
266
337
|
interval?: number
|
|
267
338
|
}
|
|
268
339
|
|
|
340
|
+
export interface ResolveResult {
|
|
341
|
+
cid: CID
|
|
342
|
+
path: string
|
|
343
|
+
}
|
|
344
|
+
|
|
269
345
|
export interface IPNS {
|
|
270
346
|
/**
|
|
271
347
|
* Creates an IPNS record signed by the passed PeerId that will resolve to the passed value
|
|
272
348
|
*
|
|
273
349
|
* If the value is a PeerId, a recursive IPNS record will be created.
|
|
274
350
|
*/
|
|
275
|
-
publish(key: PeerId, value: CID | PeerId, options?: PublishOptions): Promise<IPNSRecord>
|
|
351
|
+
publish(key: PeerId, value: CID | PeerId | string, options?: PublishOptions): Promise<IPNSRecord>
|
|
276
352
|
|
|
277
353
|
/**
|
|
278
354
|
* Accepts a public key formatted as a libp2p PeerID and resolves the IPNS record
|
|
279
355
|
* corresponding to that public key until a value is found
|
|
280
356
|
*/
|
|
281
|
-
resolve(key: PeerId, options?: ResolveOptions): Promise<
|
|
357
|
+
resolve(key: PeerId, options?: ResolveOptions): Promise<ResolveResult>
|
|
282
358
|
|
|
283
359
|
/**
|
|
284
360
|
* Resolve a CID from a dns-link style IPNS record
|
|
285
361
|
*/
|
|
286
|
-
resolveDns(domain: string, options?: ResolveDNSOptions): Promise<
|
|
362
|
+
resolveDns(domain: string, options?: ResolveDNSOptions): Promise<ResolveResult>
|
|
287
363
|
|
|
288
364
|
/**
|
|
289
365
|
* Periodically republish all IPNS records found in the datastore
|
|
@@ -313,7 +389,7 @@ class DefaultIPNS implements IPNS {
|
|
|
313
389
|
this.defaultResolvers = resolvers.length > 0 ? resolvers : [defaultResolver()]
|
|
314
390
|
}
|
|
315
391
|
|
|
316
|
-
async publish (key: PeerId, value: CID | PeerId, options: PublishOptions = {}): Promise<IPNSRecord> {
|
|
392
|
+
async publish (key: PeerId, value: CID | PeerId | string, options: PublishOptions = {}): Promise<IPNSRecord> {
|
|
317
393
|
try {
|
|
318
394
|
let sequenceNumber = 1n
|
|
319
395
|
const routingKey = peerIdToRoutingKey(key)
|
|
@@ -343,14 +419,14 @@ class DefaultIPNS implements IPNS {
|
|
|
343
419
|
}
|
|
344
420
|
}
|
|
345
421
|
|
|
346
|
-
async resolve (key: PeerId, options: ResolveOptions = {}): Promise<
|
|
422
|
+
async resolve (key: PeerId, options: ResolveOptions = {}): Promise<ResolveResult> {
|
|
347
423
|
const routingKey = peerIdToRoutingKey(key)
|
|
348
424
|
const record = await this.#findIpnsRecord(routingKey, options)
|
|
349
425
|
|
|
350
426
|
return this.#resolve(record.value, options)
|
|
351
427
|
}
|
|
352
428
|
|
|
353
|
-
async resolveDns (domain: string, options: ResolveDNSOptions = {}): Promise<
|
|
429
|
+
async resolveDns (domain: string, options: ResolveDNSOptions = {}): Promise<ResolveResult> {
|
|
354
430
|
const resolvers = options.resolvers ?? this.defaultResolvers
|
|
355
431
|
|
|
356
432
|
const dnslink = await Promise.any(
|
|
@@ -396,17 +472,28 @@ class DefaultIPNS implements IPNS {
|
|
|
396
472
|
}, options.interval ?? DEFAULT_REPUBLISH_INTERVAL_MS)
|
|
397
473
|
}
|
|
398
474
|
|
|
399
|
-
async #resolve (ipfsPath: string, options: ResolveOptions = {}): Promise<
|
|
475
|
+
async #resolve (ipfsPath: string, options: ResolveOptions = {}): Promise<ResolveResult> {
|
|
400
476
|
const parts = ipfsPath.split('/')
|
|
401
|
-
|
|
402
|
-
if (parts.length === 3) {
|
|
477
|
+
try {
|
|
403
478
|
const scheme = parts[1]
|
|
404
479
|
|
|
405
480
|
if (scheme === 'ipns') {
|
|
406
|
-
|
|
481
|
+
const { cid } = await this.resolve(peerIdFromString(parts[2]), options)
|
|
482
|
+
const path = parts.slice(3).join('/')
|
|
483
|
+
return {
|
|
484
|
+
cid,
|
|
485
|
+
path
|
|
486
|
+
}
|
|
407
487
|
} else if (scheme === 'ipfs') {
|
|
408
|
-
|
|
488
|
+
const cid = CID.parse(parts[2])
|
|
489
|
+
const path = parts.slice(3).join('/')
|
|
490
|
+
return {
|
|
491
|
+
cid,
|
|
492
|
+
path
|
|
493
|
+
}
|
|
409
494
|
}
|
|
495
|
+
} catch (err) {
|
|
496
|
+
log.error('error parsing ipfs path', err)
|
|
410
497
|
}
|
|
411
498
|
|
|
412
499
|
log.error('invalid ipfs path %s', ipfsPath)
|
|
@@ -484,5 +571,5 @@ export function ipns (components: IPNSComponents, { routers = [], resolvers = []
|
|
|
484
571
|
return new DefaultIPNS(components, routers, resolvers)
|
|
485
572
|
}
|
|
486
573
|
|
|
487
|
-
export { ipnsValidator }
|
|
574
|
+
export { ipnsValidator, type IPNSRoutingEvents }
|
|
488
575
|
export { ipnsSelector } from 'ipns/selector'
|