@helia/ipns 2.0.2 → 3.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 +110 -0
- package/dist/index.min.js +26 -15
- package/dist/src/dns-resolvers/default.d.ts +3 -0
- package/dist/src/dns-resolvers/default.d.ts.map +1 -0
- package/dist/src/dns-resolvers/default.js +8 -0
- package/dist/src/dns-resolvers/default.js.map +1 -0
- package/dist/src/dns-resolvers/dns-json-over-https.d.ts +18 -0
- package/dist/src/dns-resolvers/dns-json-over-https.d.ts.map +1 -0
- package/dist/src/dns-resolvers/dns-json-over-https.js +72 -0
- package/dist/src/dns-resolvers/dns-json-over-https.js.map +1 -0
- package/dist/src/dns-resolvers/dns-over-https.d.ts +16 -0
- package/dist/src/dns-resolvers/dns-over-https.d.ts.map +1 -0
- package/dist/src/dns-resolvers/dns-over-https.js +123 -0
- package/dist/src/dns-resolvers/dns-over-https.js.map +1 -0
- package/dist/src/dns-resolvers/index.d.ts +3 -0
- package/dist/src/dns-resolvers/index.d.ts.map +1 -0
- package/dist/src/dns-resolvers/index.js +3 -0
- package/dist/src/dns-resolvers/index.js.map +1 -0
- package/dist/src/dns-resolvers/resolver.browser.d.ts +4 -0
- package/dist/src/dns-resolvers/resolver.browser.d.ts.map +1 -0
- package/dist/src/dns-resolvers/resolver.browser.js +39 -0
- package/dist/src/dns-resolvers/resolver.browser.js.map +1 -0
- package/dist/src/dns-resolvers/resolver.d.ts +4 -0
- package/dist/src/dns-resolvers/resolver.d.ts.map +1 -0
- package/dist/src/dns-resolvers/resolver.js +21 -0
- package/dist/src/dns-resolvers/resolver.js.map +1 -0
- package/dist/src/index.d.ts +102 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +82 -12
- package/dist/src/index.js.map +1 -1
- package/dist/src/routing/dht.js.map +1 -1
- package/dist/src/routing/local-store.js +3 -3
- package/dist/src/routing/local-store.js.map +1 -1
- package/dist/src/routing/pubsub.js.map +1 -1
- package/dist/src/utils/dns.d.ts +35 -0
- package/dist/src/utils/dns.d.ts.map +1 -0
- package/dist/src/utils/dns.js +79 -0
- package/dist/src/utils/dns.js.map +1 -0
- package/dist/src/utils/tlru.js.map +1 -1
- package/dist/typedoc-urls.json +8 -0
- package/package.json +14 -5
- package/src/dns-resolvers/default.ts +9 -0
- package/src/dns-resolvers/dns-json-over-https.ts +90 -0
- package/src/dns-resolvers/dns-over-https.ts +146 -0
- package/src/dns-resolvers/index.ts +2 -0
- package/src/dns-resolvers/resolver.browser.ts +50 -0
- package/src/dns-resolvers/resolver.ts +25 -0
- package/src/index.ts +121 -13
- package/src/routing/local-store.ts +3 -3
- package/src/utils/dns.ts +126 -0
- package/dist/src/utils/resolve-dns-link.browser.d.ts +0 -6
- package/dist/src/utils/resolve-dns-link.browser.d.ts.map +0 -1
- package/dist/src/utils/resolve-dns-link.browser.js +0 -46
- package/dist/src/utils/resolve-dns-link.browser.js.map +0 -1
- package/dist/src/utils/resolve-dns-link.d.ts +0 -3
- package/dist/src/utils/resolve-dns-link.d.ts.map +0 -1
- package/dist/src/utils/resolve-dns-link.js +0 -54
- package/dist/src/utils/resolve-dns-link.js.map +0 -1
- package/src/utils/resolve-dns-link.browser.ts +0 -61
- package/src/utils/resolve-dns-link.ts +0 -65
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import dns from 'dns';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
|
-
import * as isIPFS from 'is-ipfs';
|
|
4
|
-
const MAX_RECURSIVE_DEPTH = 32;
|
|
5
|
-
export async function resolveDnslink(domain, options = {}) {
|
|
6
|
-
return recursiveResolveDnslink(domain, MAX_RECURSIVE_DEPTH, options);
|
|
7
|
-
}
|
|
8
|
-
async function recursiveResolveDnslink(domain, depth, options = {}) {
|
|
9
|
-
if (depth === 0) {
|
|
10
|
-
throw new Error('recursion limit exceeded');
|
|
11
|
-
}
|
|
12
|
-
let dnslinkRecord;
|
|
13
|
-
try {
|
|
14
|
-
dnslinkRecord = await resolve(domain);
|
|
15
|
-
}
|
|
16
|
-
catch (err) {
|
|
17
|
-
// If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND or ENODATA then throw the error
|
|
18
|
-
if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND' && err.code !== 'ENODATA') {
|
|
19
|
-
throw err;
|
|
20
|
-
}
|
|
21
|
-
if (domain.startsWith('_dnslink.')) {
|
|
22
|
-
// The supplied domain contains a _dnslink component
|
|
23
|
-
// Check the non-_dnslink domain
|
|
24
|
-
dnslinkRecord = await resolve(domain.replace('_dnslink.', ''));
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
// Check the _dnslink subdomain
|
|
28
|
-
const _dnslinkDomain = `_dnslink.${domain}`;
|
|
29
|
-
// If this throws then we propagate the error
|
|
30
|
-
dnslinkRecord = await resolve(_dnslinkDomain);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const result = dnslinkRecord.replace('dnslink=', '');
|
|
34
|
-
const domainOrCID = result.split('/')[2];
|
|
35
|
-
const isIPFSCID = isIPFS.cid(domainOrCID);
|
|
36
|
-
if (isIPFSCID || depth === 0) {
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
return recursiveResolveDnslink(domainOrCID, depth - 1, options);
|
|
40
|
-
}
|
|
41
|
-
async function resolve(domain, options = {}) {
|
|
42
|
-
const DNSLINK_REGEX = /^dnslink=.+$/;
|
|
43
|
-
const records = await promisify(dns.resolveTxt)(domain);
|
|
44
|
-
const dnslinkRecords = records.reduce((rs, r) => rs.concat(r), [])
|
|
45
|
-
.filter(record => DNSLINK_REGEX.test(record));
|
|
46
|
-
const dnslinkRecord = dnslinkRecords[0];
|
|
47
|
-
// we now have dns text entries as an array of strings
|
|
48
|
-
// only records passing the DNSLINK_REGEX text are included
|
|
49
|
-
if (dnslinkRecord == null) {
|
|
50
|
-
throw new Error(`No dnslink records found for domain: ${domain}`);
|
|
51
|
-
}
|
|
52
|
-
return dnslinkRecord;
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=resolve-dns-link.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-dns-link.js","sourceRoot":"","sources":["../../../src/utils/resolve-dns-link.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAChC,OAAO,KAAK,MAAM,MAAM,SAAS,CAAA;AAGjC,MAAM,mBAAmB,GAAG,EAAE,CAAA;AAE9B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAE,MAAc,EAAE,UAAwB,EAAE;IAC9E,OAAO,uBAAuB,CAAC,MAAM,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAA;AACtE,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAE,MAAc,EAAE,KAAa,EAAE,UAAwB,EAAE;IAC/F,IAAI,KAAK,KAAK,CAAC,EAAE;QACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;KAC5C;IAED,IAAI,aAAa,CAAA;IAEjB,IAAI;QACF,aAAa,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;KACtC;IAAC,OAAO,GAAQ,EAAE;QACjB,wFAAwF;QACxF,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,IAAI,GAAG,CAAC,IAAI,KAAK,uBAAuB,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE;YAC9F,MAAM,GAAG,CAAA;SACV;QAED,IAAI,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE;YAClC,oDAAoD;YACpD,gCAAgC;YAChC,aAAa,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;SAC/D;aAAM;YACL,+BAA+B;YAC/B,MAAM,cAAc,GAAG,YAAY,MAAM,EAAE,CAAA;YAC3C,6CAA6C;YAC7C,aAAa,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,CAAA;SAC9C;KACF;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IACpD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IACxC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAEzC,IAAI,SAAS,IAAI,KAAK,KAAK,CAAC,EAAE;QAC5B,OAAO,MAAM,CAAA;KACd;IAED,OAAO,uBAAuB,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAA;AACjE,CAAC;AAED,KAAK,UAAU,OAAO,CAAE,MAAc,EAAE,UAAwB,EAAE;IAChE,MAAM,aAAa,GAAG,cAAc,CAAA;IACpC,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;IACvD,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;SAC/D,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IAE/C,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;IAEvC,sDAAsD;IACtD,2DAA2D;IAC3D,IAAI,aAAa,IAAI,IAAI,EAAE;QACzB,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,EAAE,CAAC,CAAA;KAClE;IAED,OAAO,aAAa,CAAA;AACtB,CAAC"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/* eslint-env browser */
|
|
2
|
-
|
|
3
|
-
import PQueue from 'p-queue'
|
|
4
|
-
import { TLRU } from './tlru.js'
|
|
5
|
-
import type { AbortOptions } from '@libp2p/interface'
|
|
6
|
-
|
|
7
|
-
// Avoid sending multiple queries for the same hostname by caching results
|
|
8
|
-
const cache = new TLRU<{ Path: string, Message: string }>(1000)
|
|
9
|
-
// TODO: /api/v0/dns does not return TTL yet: https://github.com/ipfs/go-ipfs/issues/5884
|
|
10
|
-
// However we know browsers themselves cache DNS records for at least 1 minute,
|
|
11
|
-
// which acts a provisional default ttl: https://stackoverflow.com/a/36917902/11518426
|
|
12
|
-
const ttl = 60 * 1000
|
|
13
|
-
|
|
14
|
-
// browsers limit concurrent connections per host,
|
|
15
|
-
// we don't want preload calls to exhaust the limit (~6)
|
|
16
|
-
const httpQueue = new PQueue({ concurrency: 4 })
|
|
17
|
-
|
|
18
|
-
const ipfsPath = (response: { Path: string, Message: string }): string => {
|
|
19
|
-
if (response.Path != null) {
|
|
20
|
-
return response.Path
|
|
21
|
-
}
|
|
22
|
-
throw new Error(response.Message)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface ResolveDnsLinkOptions extends AbortOptions {
|
|
26
|
-
nocache?: boolean
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function resolveDnslink (fqdn: string, opts: ResolveDnsLinkOptions = {}): Promise<string> { // eslint-disable-line require-await
|
|
30
|
-
const resolve = async (fqdn: string, opts: ResolveDnsLinkOptions = {}): Promise<string> => {
|
|
31
|
-
// @ts-expect-error - URLSearchParams does not take boolean options, only strings
|
|
32
|
-
const searchParams = new URLSearchParams(opts)
|
|
33
|
-
searchParams.set('arg', fqdn)
|
|
34
|
-
|
|
35
|
-
// try cache first
|
|
36
|
-
const query = searchParams.toString()
|
|
37
|
-
if (opts.nocache !== true && cache.has(query)) {
|
|
38
|
-
const response = cache.get(query)
|
|
39
|
-
|
|
40
|
-
if (response != null) {
|
|
41
|
-
return ipfsPath(response)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// fallback to delegated DNS resolver
|
|
46
|
-
const response = await httpQueue.add(async () => {
|
|
47
|
-
// Delegated HTTP resolver sending DNSLink queries to ipfs.io
|
|
48
|
-
// TODO: replace hardcoded host with configurable DNS over HTTPS: https://github.com/ipfs/js-ipfs/issues/2212
|
|
49
|
-
const res = await fetch(`https://ipfs.io/api/v0/dns?${searchParams}`)
|
|
50
|
-
const query = new URL(res.url).search.slice(1)
|
|
51
|
-
const json = await res.json()
|
|
52
|
-
cache.set(query, json, ttl)
|
|
53
|
-
|
|
54
|
-
return json
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
return ipfsPath(response)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return resolve(fqdn, opts)
|
|
61
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import dns from 'dns'
|
|
2
|
-
import { promisify } from 'util'
|
|
3
|
-
import * as isIPFS from 'is-ipfs'
|
|
4
|
-
import type { AbortOptions } from '@libp2p/interface'
|
|
5
|
-
|
|
6
|
-
const MAX_RECURSIVE_DEPTH = 32
|
|
7
|
-
|
|
8
|
-
export async function resolveDnslink (domain: string, options: AbortOptions = {}): Promise<string> {
|
|
9
|
-
return recursiveResolveDnslink(domain, MAX_RECURSIVE_DEPTH, options)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
async function recursiveResolveDnslink (domain: string, depth: number, options: AbortOptions = {}): Promise<string> {
|
|
13
|
-
if (depth === 0) {
|
|
14
|
-
throw new Error('recursion limit exceeded')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
let dnslinkRecord
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
dnslinkRecord = await resolve(domain)
|
|
21
|
-
} catch (err: any) {
|
|
22
|
-
// If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND or ENODATA then throw the error
|
|
23
|
-
if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND' && err.code !== 'ENODATA') {
|
|
24
|
-
throw err
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (domain.startsWith('_dnslink.')) {
|
|
28
|
-
// The supplied domain contains a _dnslink component
|
|
29
|
-
// Check the non-_dnslink domain
|
|
30
|
-
dnslinkRecord = await resolve(domain.replace('_dnslink.', ''))
|
|
31
|
-
} else {
|
|
32
|
-
// Check the _dnslink subdomain
|
|
33
|
-
const _dnslinkDomain = `_dnslink.${domain}`
|
|
34
|
-
// If this throws then we propagate the error
|
|
35
|
-
dnslinkRecord = await resolve(_dnslinkDomain)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = dnslinkRecord.replace('dnslink=', '')
|
|
40
|
-
const domainOrCID = result.split('/')[2]
|
|
41
|
-
const isIPFSCID = isIPFS.cid(domainOrCID)
|
|
42
|
-
|
|
43
|
-
if (isIPFSCID || depth === 0) {
|
|
44
|
-
return result
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return recursiveResolveDnslink(domainOrCID, depth - 1, options)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function resolve (domain: string, options: AbortOptions = {}): Promise<string> {
|
|
51
|
-
const DNSLINK_REGEX = /^dnslink=.+$/
|
|
52
|
-
const records = await promisify(dns.resolveTxt)(domain)
|
|
53
|
-
const dnslinkRecords = records.reduce((rs, r) => rs.concat(r), [])
|
|
54
|
-
.filter(record => DNSLINK_REGEX.test(record))
|
|
55
|
-
|
|
56
|
-
const dnslinkRecord = dnslinkRecords[0]
|
|
57
|
-
|
|
58
|
-
// we now have dns text entries as an array of strings
|
|
59
|
-
// only records passing the DNSLINK_REGEX text are included
|
|
60
|
-
if (dnslinkRecord == null) {
|
|
61
|
-
throw new Error(`No dnslink records found for domain: ${domain}`)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return dnslinkRecord
|
|
65
|
-
}
|