@helia/ipns 6.0.0 → 6.0.1-2c71b6e

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 (54) hide show
  1. package/README.md +16 -1
  2. package/dist/index.min.js +5 -5
  3. package/dist/src/dnslink.d.ts +5 -0
  4. package/dist/src/dnslink.d.ts.map +1 -0
  5. package/dist/src/dnslink.js +123 -0
  6. package/dist/src/dnslink.js.map +1 -0
  7. package/dist/src/index.d.ts +18 -22
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/index.js +10 -9
  10. package/dist/src/index.js.map +1 -1
  11. package/package.json +14 -18
  12. package/src/dnslink.ts +142 -0
  13. package/src/index.ts +30 -38
  14. package/dist/src/dns-resolvers/default.d.ts +0 -3
  15. package/dist/src/dns-resolvers/default.d.ts.map +0 -1
  16. package/dist/src/dns-resolvers/default.js +0 -8
  17. package/dist/src/dns-resolvers/default.js.map +0 -1
  18. package/dist/src/dns-resolvers/dns-json-over-https.d.ts +0 -18
  19. package/dist/src/dns-resolvers/dns-json-over-https.d.ts.map +0 -1
  20. package/dist/src/dns-resolvers/dns-json-over-https.js +0 -72
  21. package/dist/src/dns-resolvers/dns-json-over-https.js.map +0 -1
  22. package/dist/src/dns-resolvers/dns-over-https.d.ts +0 -16
  23. package/dist/src/dns-resolvers/dns-over-https.d.ts.map +0 -1
  24. package/dist/src/dns-resolvers/dns-over-https.js +0 -123
  25. package/dist/src/dns-resolvers/dns-over-https.js.map +0 -1
  26. package/dist/src/dns-resolvers/index.d.ts +0 -3
  27. package/dist/src/dns-resolvers/index.d.ts.map +0 -1
  28. package/dist/src/dns-resolvers/index.js +0 -3
  29. package/dist/src/dns-resolvers/index.js.map +0 -1
  30. package/dist/src/dns-resolvers/resolver.browser.d.ts +0 -4
  31. package/dist/src/dns-resolvers/resolver.browser.d.ts.map +0 -1
  32. package/dist/src/dns-resolvers/resolver.browser.js +0 -39
  33. package/dist/src/dns-resolvers/resolver.browser.js.map +0 -1
  34. package/dist/src/dns-resolvers/resolver.d.ts +0 -4
  35. package/dist/src/dns-resolvers/resolver.d.ts.map +0 -1
  36. package/dist/src/dns-resolvers/resolver.js +0 -21
  37. package/dist/src/dns-resolvers/resolver.js.map +0 -1
  38. package/dist/src/utils/dns.d.ts +0 -35
  39. package/dist/src/utils/dns.d.ts.map +0 -1
  40. package/dist/src/utils/dns.js +0 -79
  41. package/dist/src/utils/dns.js.map +0 -1
  42. package/dist/src/utils/tlru.d.ts +0 -15
  43. package/dist/src/utils/tlru.d.ts.map +0 -1
  44. package/dist/src/utils/tlru.js +0 -40
  45. package/dist/src/utils/tlru.js.map +0 -1
  46. package/dist/typedoc-urls.json +0 -44
  47. package/src/dns-resolvers/default.ts +0 -9
  48. package/src/dns-resolvers/dns-json-over-https.ts +0 -90
  49. package/src/dns-resolvers/dns-over-https.ts +0 -146
  50. package/src/dns-resolvers/index.ts +0 -2
  51. package/src/dns-resolvers/resolver.browser.ts +0 -50
  52. package/src/dns-resolvers/resolver.ts +0 -25
  53. package/src/utils/dns.ts +0 -126
  54. package/src/utils/tlru.ts +0 -52
@@ -1,79 +0,0 @@
1
- import { CodeError } from '@libp2p/interface';
2
- import * as isIPFS from 'is-ipfs';
3
- export const ipfsPathForAnswer = (answer) => {
4
- let data = answer.data;
5
- if (data.startsWith('"')) {
6
- data = data.substring(1);
7
- }
8
- if (data.endsWith('"')) {
9
- data = data.substring(0, data.length - 1);
10
- }
11
- return data.replace('dnslink=', '');
12
- };
13
- export const ipfsPathAndAnswer = (domain, response) => {
14
- const answer = findDNSLinkAnswer(domain, response);
15
- return {
16
- ipfsPath: ipfsPathForAnswer(answer),
17
- answer
18
- };
19
- };
20
- export const findDNSLinkAnswer = (domain, response) => {
21
- const answer = response.Answer?.filter(a => a.data.includes('dnslink=/ipfs') || a.data.includes('dnslink=/ipns')).pop();
22
- if (answer == null) {
23
- throw new CodeError(`No dnslink records found for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND');
24
- }
25
- return answer;
26
- };
27
- export const MAX_RECURSIVE_DEPTH = 32;
28
- export const recursiveResolveDnslink = async (domain, depth, resolve, options = {}) => {
29
- if (depth === 0) {
30
- throw new Error('recursion limit exceeded');
31
- }
32
- let dnslinkRecord;
33
- try {
34
- dnslinkRecord = await resolve(domain, options);
35
- }
36
- catch (err) {
37
- // If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND or ENODATA then throw the error
38
- if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND' && err.code !== 'ENODATA') {
39
- throw err;
40
- }
41
- if (domain.startsWith('_dnslink.')) {
42
- // The supplied domain contains a _dnslink component
43
- // Check the non-_dnslink domain
44
- domain = domain.replace('_dnslink.', '');
45
- }
46
- else {
47
- // Check the _dnslink subdomain
48
- domain = `_dnslink.${domain}`;
49
- }
50
- // If this throws then we propagate the error
51
- dnslinkRecord = await resolve(domain, options);
52
- }
53
- const result = dnslinkRecord.replace('dnslink=', '');
54
- // result is now a `/ipfs/<cid>` or `/ipns/<cid>` string
55
- const domainOrCID = result.split('/')[2]; // e.g. ["", "ipfs", "<cid>"]
56
- const isIPFSCID = isIPFS.cid(domainOrCID);
57
- // if the result is a CID, or depth is 1, we've reached the end of the recursion
58
- // if depth is 1, another recursive call will be made, but it would throw.
59
- // we could return if depth is 1 and allow users to handle, but that may be a breaking change
60
- if (isIPFSCID) {
61
- return result;
62
- }
63
- return recursiveResolveDnslink(domainOrCID, depth - 1, resolve, options);
64
- };
65
- const DNSLINK_REGEX = /^dnslink=.+$/;
66
- export const resolveFn = async (resolver, domain) => {
67
- const records = await resolver.resolveTxt(domain);
68
- const dnslinkRecords = records.flat()
69
- .filter(record => DNSLINK_REGEX.test(record));
70
- // we now have dns text entries as an array of strings
71
- // only records passing the DNSLINK_REGEX text are included
72
- // TODO: support multiple dnslink records
73
- const dnslinkRecord = dnslinkRecords[0];
74
- if (dnslinkRecord == null) {
75
- throw new CodeError(`No dnslink records found for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND');
76
- }
77
- return dnslinkRecord;
78
- };
79
- //# sourceMappingURL=dns.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dns.js","sourceRoot":"","sources":["../../../src/utils/dns.ts"],"names":[],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- /**
2
- * Time Aware Least Recent Used Cache
3
- *
4
- * @see https://arxiv.org/pdf/1801.00390
5
- */
6
- export declare class TLRU<T> {
7
- private readonly lru;
8
- constructor(maxSize: number);
9
- get(key: string): T | undefined;
10
- set(key: string, value: T, ttl: number): void;
11
- has(key: string): boolean;
12
- remove(key: string): void;
13
- clear(): void;
14
- }
15
- //# sourceMappingURL=tlru.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tlru.d.ts","sourceRoot":"","sources":["../../../src/utils/tlru.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,qBAAa,IAAI,CAAC,CAAC;IACjB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4B;gBAEnC,OAAO,EAAE,MAAM;IAI5B,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAgBhC,GAAG,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAI9C,GAAG,CAAE,GAAG,EAAE,MAAM,GAAG,OAAO;IAU1B,MAAM,CAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAI1B,KAAK,IAAK,IAAI;CAGf"}
@@ -1,40 +0,0 @@
1
- import hashlru from 'hashlru';
2
- /**
3
- * Time Aware Least Recent Used Cache
4
- *
5
- * @see https://arxiv.org/pdf/1801.00390
6
- */
7
- export class TLRU {
8
- lru;
9
- constructor(maxSize) {
10
- this.lru = hashlru(maxSize);
11
- }
12
- get(key) {
13
- const value = this.lru.get(key);
14
- if (value != null) {
15
- if (value.expire != null && value.expire < Date.now()) {
16
- this.lru.remove(key);
17
- return undefined;
18
- }
19
- return value.value;
20
- }
21
- return undefined;
22
- }
23
- set(key, value, ttl) {
24
- this.lru.set(key, { value, expire: Date.now() + ttl });
25
- }
26
- has(key) {
27
- const value = this.get(key);
28
- if (value != null) {
29
- return true;
30
- }
31
- return false;
32
- }
33
- remove(key) {
34
- this.lru.remove(key);
35
- }
36
- clear() {
37
- this.lru.clear();
38
- }
39
- }
40
- //# sourceMappingURL=tlru.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tlru.js","sourceRoot":"","sources":["../../../src/utils/tlru.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B;;;;GAIG;AACH,MAAM,OAAO,IAAI;IACE,GAAG,CAA4B;IAEhD,YAAa,OAAe;QAC1B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7B,CAAC;IAED,GAAG,CAAE,GAAW;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAE/B,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACtD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;gBAEpB,OAAO,SAAS,CAAA;YAClB,CAAC;YAED,OAAO,KAAK,CAAC,KAAK,CAAA;QACpB,CAAC;QAED,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,GAAG,CAAE,GAAW,EAAE,KAAQ,EAAE,GAAW;QACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,CAAA;IACxD,CAAC;IAED,GAAG,CAAE,GAAW;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAE3B,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,CAAE,GAAW;QACjB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACtB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAA;IAClB,CAAC;CACF"}
@@ -1,44 +0,0 @@
1
- {
2
- "dnsJsonOverHttps": "https://ipfs.github.io/helia/functions/_helia_ipns.dns_resolvers.dnsJsonOverHttps.html",
3
- "dnsOverHttps": "https://ipfs.github.io/helia/functions/_helia_ipns.dns_resolvers.dnsOverHttps.html",
4
- "DNSResolver": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.DNSResolver.html",
5
- ".:DNSResolver": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.DNSResolver.html",
6
- "IPNS": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNS.html",
7
- ".:IPNS": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNS.html",
8
- "IPNSComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSComponents.html",
9
- ".:IPNSComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSComponents.html",
10
- "IPNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSOptions.html",
11
- ".:IPNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.IPNSOptions.html",
12
- "PublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.PublishOptions.html",
13
- ".:PublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.PublishOptions.html",
14
- "RepublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.RepublishOptions.html",
15
- ".:RepublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.RepublishOptions.html",
16
- "ResolveDNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveDNSOptions.html",
17
- ".:ResolveDNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveDNSOptions.html",
18
- "ResolveDnsLinkOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveDnsLinkOptions.html",
19
- ".:ResolveDnsLinkOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveDnsLinkOptions.html",
20
- "ResolveOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveOptions.html",
21
- ".:ResolveOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveOptions.html",
22
- "ResolveResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveResult.html",
23
- ".:ResolveResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.index.ResolveResult.html",
24
- "PublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.PublishProgressEvents.html",
25
- ".:PublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.PublishProgressEvents.html",
26
- "RepublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.RepublishProgressEvents.html",
27
- ".:RepublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.RepublishProgressEvents.html",
28
- "ResolveDnsLinkProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.ResolveDnsLinkProgressEvents.html",
29
- ".:ResolveDnsLinkProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.ResolveDnsLinkProgressEvents.html",
30
- "ResolveProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.ResolveProgressEvents.html",
31
- ".:ResolveProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.index.ResolveProgressEvents.html",
32
- "ipns": "https://ipfs.github.io/helia/functions/_helia_ipns.index.ipns-1.html",
33
- ".:ipns": "https://ipfs.github.io/helia/functions/_helia_ipns.index.ipns-1.html",
34
- "GetOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.GetOptions.html",
35
- "./routing:GetOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.GetOptions.html",
36
- "IPNSRouting": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.IPNSRouting.html",
37
- "./routing:IPNSRouting": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.IPNSRouting.html",
38
- "PutOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PutOptions.html",
39
- "./routing:PutOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.routing.PutOptions.html",
40
- "IPNSRoutingEvents": "https://ipfs.github.io/helia/types/_helia_ipns.routing.IPNSRoutingEvents.html",
41
- "./routing:IPNSRoutingEvents": "https://ipfs.github.io/helia/types/_helia_ipns.routing.IPNSRoutingEvents.html",
42
- "helia": "https://ipfs.github.io/helia/functions/_helia_ipns.routing.helia.html",
43
- "pubsub": "https://ipfs.github.io/helia/functions/_helia_ipns.routing.pubsub.html"
44
- }
@@ -1,9 +0,0 @@
1
- import { MAX_RECURSIVE_DEPTH, recursiveResolveDnslink } from '../utils/dns.js'
2
- import resolve from './resolver.js'
3
- import type { DNSResolver, ResolveDnsLinkOptions } from '../index.js'
4
-
5
- export function defaultResolver (): DNSResolver {
6
- return async (domain: string, options: ResolveDnsLinkOptions = {}): Promise<string> => {
7
- return recursiveResolveDnslink(domain, MAX_RECURSIVE_DEPTH, resolve, options)
8
- }
9
- }
@@ -1,90 +0,0 @@
1
- /* eslint-env browser */
2
-
3
- import PQueue from 'p-queue'
4
- import { CustomProgressEvent } from 'progress-events'
5
- import { type DNSResponse, MAX_RECURSIVE_DEPTH, recursiveResolveDnslink, ipfsPathAndAnswer } from '../utils/dns.js'
6
- import { TLRU } from '../utils/tlru.js'
7
- import type { ResolveDnsLinkOptions, DNSResolver } from '../index.js'
8
-
9
- // Avoid sending multiple queries for the same hostname by caching results
10
- const cache = new TLRU<string>(1000)
11
- // This TTL will be used if the remote service does not return one
12
- const ttl = 60 * 1000
13
-
14
- /**
15
- * Uses the RFC 8427 'application/dns-json' content-type to resolve DNS queries.
16
- *
17
- * Supports and server that uses the same schema as Google's DNS over HTTPS
18
- * resolver.
19
- *
20
- * This resolver needs fewer dependencies than the regular DNS-over-HTTPS
21
- * resolver so can result in a smaller bundle size and consequently is preferred
22
- * for browser use.
23
- *
24
- * @see https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-json/
25
- * @see https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers
26
- * @see https://dnsprivacy.org/public_resolvers/
27
- * @see https://datatracker.ietf.org/doc/html/rfc8427
28
- */
29
- export function dnsJsonOverHttps (url: string): DNSResolver {
30
- // browsers limit concurrent connections per host,
31
- // we don't want preload calls to exhaust the limit (~6)
32
- const httpQueue = new PQueue({ concurrency: 4 })
33
-
34
- const resolve = async (fqdn: string, options: ResolveDnsLinkOptions = {}): Promise<string> => {
35
- const searchParams = new URLSearchParams()
36
- searchParams.set('name', fqdn)
37
- searchParams.set('type', 'TXT')
38
-
39
- const query = searchParams.toString()
40
-
41
- // try cache first
42
- if (options.nocache !== true && cache.has(query)) {
43
- const response = cache.get(query)
44
-
45
- if (response != null) {
46
- options.onProgress?.(new CustomProgressEvent<string>('dnslink:cache', { detail: response }))
47
- return response
48
- }
49
- }
50
-
51
- options.onProgress?.(new CustomProgressEvent<string>('dnslink:query', { detail: fqdn }))
52
-
53
- // query DNS-JSON over HTTPS server
54
- const response = await httpQueue.add(async () => {
55
- const res = await fetch(`${url}?${searchParams}`, {
56
- headers: {
57
- accept: 'application/dns-json'
58
- },
59
- signal: options.signal
60
- })
61
-
62
- if (res.status !== 200) {
63
- throw new Error(`Unexpected HTTP status: ${res.status} - ${res.statusText}`)
64
- }
65
-
66
- const query = new URL(res.url).search.slice(1)
67
- const json: DNSResponse = await res.json()
68
-
69
- options.onProgress?.(new CustomProgressEvent<DNSResponse>('dnslink:answer', { detail: json }))
70
-
71
- const { ipfsPath, answer } = ipfsPathAndAnswer(fqdn, json)
72
-
73
- cache.set(query, ipfsPath, answer.TTL ?? ttl)
74
-
75
- return ipfsPath
76
- }, {
77
- signal: options.signal
78
- })
79
-
80
- if (response == null) {
81
- throw new Error('No DNS response received')
82
- }
83
-
84
- return response
85
- }
86
-
87
- return async (domain: string, options: ResolveDnsLinkOptions = {}) => {
88
- return recursiveResolveDnslink(domain, MAX_RECURSIVE_DEPTH, resolve, options)
89
- }
90
- }
@@ -1,146 +0,0 @@
1
- /* eslint-env browser */
2
-
3
- import { Buffer } from 'buffer'
4
- import dnsPacket, { type DecodedPacket } from 'dns-packet'
5
- import { base64url } from 'multiformats/bases/base64'
6
- import PQueue from 'p-queue'
7
- import { CustomProgressEvent } from 'progress-events'
8
- import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
9
- import { type DNSResponse, MAX_RECURSIVE_DEPTH, recursiveResolveDnslink, ipfsPathAndAnswer } from '../utils/dns.js'
10
- import { TLRU } from '../utils/tlru.js'
11
- import type { ResolveDnsLinkOptions, DNSResolver } from '../index.js'
12
-
13
- // Avoid sending multiple queries for the same hostname by caching results
14
- const cache = new TLRU<string>(1000)
15
- // This TTL will be used if the remote service does not return one
16
- const ttl = 60 * 1000
17
-
18
- /**
19
- * Uses the RFC 1035 'application/dns-message' content-type to resolve DNS
20
- * queries.
21
- *
22
- * This resolver needs more dependencies than the non-standard
23
- * DNS-JSON-over-HTTPS resolver so can result in a larger bundle size and
24
- * consequently is not preferred for browser use.
25
- *
26
- * @see https://datatracker.ietf.org/doc/html/rfc1035
27
- * @see https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-wireformat/
28
- * @see https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers
29
- * @see https://dnsprivacy.org/public_resolvers/
30
- */
31
- export function dnsOverHttps (url: string): DNSResolver {
32
- // browsers limit concurrent connections per host,
33
- // we don't want preload calls to exhaust the limit (~6)
34
- const httpQueue = new PQueue({ concurrency: 4 })
35
-
36
- const resolve = async (fqdn: string, options: ResolveDnsLinkOptions = {}): Promise<string> => {
37
- const dnsQuery = dnsPacket.encode({
38
- type: 'query',
39
- id: 0,
40
- flags: dnsPacket.RECURSION_DESIRED,
41
- questions: [{
42
- type: 'TXT',
43
- name: fqdn
44
- }]
45
- })
46
-
47
- const searchParams = new URLSearchParams()
48
- searchParams.set('dns', base64url.encode(dnsQuery).substring(1))
49
-
50
- const query = searchParams.toString()
51
-
52
- // try cache first
53
- if (options.nocache !== true && cache.has(query)) {
54
- const response = cache.get(query)
55
-
56
- if (response != null) {
57
- options.onProgress?.(new CustomProgressEvent<string>('dnslink:cache', { detail: response }))
58
- return response
59
- }
60
- }
61
-
62
- options.onProgress?.(new CustomProgressEvent<string>('dnslink:query', { detail: fqdn }))
63
-
64
- // query DNS over HTTPS server
65
- const response = await httpQueue.add(async () => {
66
- const res = await fetch(`${url}?${searchParams}`, {
67
- headers: {
68
- accept: 'application/dns-message'
69
- },
70
- signal: options.signal
71
- })
72
-
73
- if (res.status !== 200) {
74
- throw new Error(`Unexpected HTTP status: ${res.status} - ${res.statusText}`)
75
- }
76
-
77
- const query = new URL(res.url).search.slice(1)
78
- const buf = await res.arrayBuffer()
79
- // map to expected response format
80
- const json = toDNSResponse(dnsPacket.decode(Buffer.from(buf)))
81
-
82
- options.onProgress?.(new CustomProgressEvent<DNSResponse>('dnslink:answer', { detail: json }))
83
-
84
- const { ipfsPath, answer } = ipfsPathAndAnswer(fqdn, json)
85
-
86
- cache.set(query, ipfsPath, answer.TTL ?? ttl)
87
-
88
- return ipfsPath
89
- }, {
90
- signal: options.signal
91
- })
92
-
93
- if (response == null) {
94
- throw new Error('No DNS response received')
95
- }
96
-
97
- return response
98
- }
99
-
100
- return async (domain: string, options: ResolveDnsLinkOptions = {}) => {
101
- return recursiveResolveDnslink(domain, MAX_RECURSIVE_DEPTH, resolve, options)
102
- }
103
- }
104
-
105
- function toDNSResponse (response: DecodedPacket): DNSResponse {
106
- const txtType = 16
107
-
108
- return {
109
- Status: 0,
110
- TC: response.flag_tc ?? false,
111
- RD: response.flag_rd ?? false,
112
- RA: response.flag_ra ?? false,
113
- AD: response.flag_ad ?? false,
114
- CD: response.flag_cd ?? false,
115
- Question: response.questions?.map(q => ({
116
- name: q.name,
117
- type: txtType
118
- })) ?? [],
119
- Answer: response.answers?.map(a => {
120
- if (a.type !== 'TXT' || a.data.length < 1) {
121
- return {
122
- name: a.name,
123
- type: txtType,
124
- TTL: 0,
125
- data: 'invalid'
126
- }
127
- }
128
-
129
- if (!Buffer.isBuffer(a.data[0])) {
130
- return {
131
- name: a.name,
132
- type: txtType,
133
- TTL: a.ttl ?? ttl,
134
- data: String(a.data[0])
135
- }
136
- }
137
-
138
- return {
139
- name: a.name,
140
- type: txtType,
141
- TTL: a.ttl ?? ttl,
142
- data: uint8ArrayToString(a.data[0])
143
- }
144
- }) ?? []
145
- }
146
- }
@@ -1,2 +0,0 @@
1
- export { dnsOverHttps } from './dns-over-https.js'
2
- export { dnsJsonOverHttps } from './dns-json-over-https.js'
@@ -1,50 +0,0 @@
1
- import Resolver from 'dns-over-http-resolver'
2
- import PQueue from 'p-queue'
3
- import { CustomProgressEvent } from 'progress-events'
4
- import { resolveFn, type DNSResponse } from '../utils/dns.js'
5
- import { TLRU } from '../utils/tlru.js'
6
- import type { DNSResolver } from '../index.js'
7
-
8
- const cache = new TLRU<string>(1000)
9
- // We know browsers themselves cache DNS records for at least 1 minute,
10
- // which acts a provisional default ttl: https://stackoverflow.com/a/36917902/11518426
11
- const ttl = 60 * 1000
12
-
13
- // browsers limit concurrent connections per host,
14
- // we don't want to exhaust the limit (~6)
15
- const httpQueue = new PQueue({ concurrency: 4 })
16
-
17
- const resolve: DNSResolver = async function resolve (domain, options = {}) {
18
- const resolver = new Resolver({ maxCache: 0 })
19
- // try cache first
20
- if (options.nocache !== true && cache.has(domain)) {
21
- const response = cache.get(domain)
22
-
23
- if (response != null) {
24
- options?.onProgress?.(new CustomProgressEvent<string>('dnslink:cache', { detail: response }))
25
- return response
26
- }
27
- }
28
-
29
- options.onProgress?.(new CustomProgressEvent<string>('dnslink:query', { detail: domain }))
30
-
31
- // Add the query to the queue
32
- const response = await httpQueue.add(async () => {
33
- const dnslinkRecord = await resolveFn(resolver, domain)
34
-
35
- options.onProgress?.(new CustomProgressEvent<DNSResponse>('dnslink:answer', { detail: dnslinkRecord }))
36
- cache.set(domain, dnslinkRecord, ttl)
37
-
38
- return dnslinkRecord
39
- }, {
40
- signal: options?.signal
41
- })
42
-
43
- if (response == null) {
44
- throw new Error('No DNS response received')
45
- }
46
-
47
- return response
48
- }
49
-
50
- export default resolve
@@ -1,25 +0,0 @@
1
- import { Resolver } from 'dns/promises'
2
- import { CustomProgressEvent } from 'progress-events'
3
- import { resolveFn, type DNSResponse } from '../utils/dns.js'
4
- import type { DNSResolver } from '../index.js'
5
-
6
- const resolve: DNSResolver = async function resolve (domain, options = {}) {
7
- const resolver = new Resolver()
8
- const listener = (): void => {
9
- resolver.cancel()
10
- }
11
-
12
- options.signal?.addEventListener('abort', listener)
13
-
14
- try {
15
- options.onProgress?.(new CustomProgressEvent<string>('dnslink:query', { detail: domain }))
16
- const dnslinkRecord = await resolveFn(resolver, domain)
17
-
18
- options.onProgress?.(new CustomProgressEvent<DNSResponse>('dnslink:answer', { detail: dnslinkRecord }))
19
- return dnslinkRecord
20
- } finally {
21
- options.signal?.removeEventListener('abort', listener)
22
- }
23
- }
24
-
25
- export default resolve
package/src/utils/dns.ts DELETED
@@ -1,126 +0,0 @@
1
- import { CodeError } from '@libp2p/interface'
2
- import * as isIPFS from 'is-ipfs'
3
- import type { DNSResolver, ResolveDnsLinkOptions } from '../index.js'
4
-
5
- export interface Question {
6
- name: string
7
- type: number
8
- }
9
-
10
- export interface Answer {
11
- name: string
12
- type: number
13
- TTL: number
14
- data: string
15
- }
16
-
17
- export interface DNSResponse {
18
- Status: number
19
- TC: boolean
20
- RD: boolean
21
- RA: boolean
22
- AD: boolean
23
- CD: boolean
24
- Question: Question[]
25
- Answer?: Answer[]
26
- }
27
-
28
- export const ipfsPathForAnswer = (answer: Answer): string => {
29
- let data = answer.data
30
-
31
- if (data.startsWith('"')) {
32
- data = data.substring(1)
33
- }
34
-
35
- if (data.endsWith('"')) {
36
- data = data.substring(0, data.length - 1)
37
- }
38
-
39
- return data.replace('dnslink=', '')
40
- }
41
-
42
- export const ipfsPathAndAnswer = (domain: string, response: DNSResponse): { ipfsPath: string, answer: Answer } => {
43
- const answer = findDNSLinkAnswer(domain, response)
44
-
45
- return {
46
- ipfsPath: ipfsPathForAnswer(answer),
47
- answer
48
- }
49
- }
50
-
51
- export const findDNSLinkAnswer = (domain: string, response: DNSResponse): Answer => {
52
- const answer = response.Answer?.filter(a => a.data.includes('dnslink=/ipfs') || a.data.includes('dnslink=/ipns')).pop()
53
-
54
- if (answer == null) {
55
- throw new CodeError(`No dnslink records found for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND')
56
- }
57
-
58
- return answer
59
- }
60
-
61
- export const MAX_RECURSIVE_DEPTH = 32
62
-
63
- export const recursiveResolveDnslink = async (domain: string, depth: number, resolve: DNSResolver, options: ResolveDnsLinkOptions = {}): Promise<string> => {
64
- if (depth === 0) {
65
- throw new Error('recursion limit exceeded')
66
- }
67
-
68
- let dnslinkRecord: string
69
-
70
- try {
71
- dnslinkRecord = await resolve(domain, options)
72
- } catch (err: any) {
73
- // If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND or ENODATA then throw the error
74
- if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND' && err.code !== 'ENODATA') {
75
- throw err
76
- }
77
-
78
- if (domain.startsWith('_dnslink.')) {
79
- // The supplied domain contains a _dnslink component
80
- // Check the non-_dnslink domain
81
- domain = domain.replace('_dnslink.', '')
82
- } else {
83
- // Check the _dnslink subdomain
84
- domain = `_dnslink.${domain}`
85
- }
86
-
87
- // If this throws then we propagate the error
88
- dnslinkRecord = await resolve(domain, options)
89
- }
90
-
91
- const result = dnslinkRecord.replace('dnslink=', '')
92
- // result is now a `/ipfs/<cid>` or `/ipns/<cid>` string
93
- const domainOrCID = result.split('/')[2] // e.g. ["", "ipfs", "<cid>"]
94
- const isIPFSCID = isIPFS.cid(domainOrCID)
95
-
96
- // if the result is a CID, or depth is 1, we've reached the end of the recursion
97
- // if depth is 1, another recursive call will be made, but it would throw.
98
- // we could return if depth is 1 and allow users to handle, but that may be a breaking change
99
- if (isIPFSCID) {
100
- return result
101
- }
102
-
103
- return recursiveResolveDnslink(domainOrCID, depth - 1, resolve, options)
104
- }
105
-
106
- interface DnsResolver {
107
- resolveTxt(domain: string): Promise<string[][]>
108
- }
109
-
110
- const DNSLINK_REGEX = /^dnslink=.+$/
111
- export const resolveFn = async (resolver: DnsResolver, domain: string): Promise<string> => {
112
- const records = await resolver.resolveTxt(domain)
113
- const dnslinkRecords = records.flat()
114
- .filter(record => DNSLINK_REGEX.test(record))
115
-
116
- // we now have dns text entries as an array of strings
117
- // only records passing the DNSLINK_REGEX text are included
118
- // TODO: support multiple dnslink records
119
- const dnslinkRecord = dnslinkRecords[0]
120
-
121
- if (dnslinkRecord == null) {
122
- throw new CodeError(`No dnslink records found for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND')
123
- }
124
-
125
- return dnslinkRecord
126
- }