@atproto-labs/handle-resolver-node 0.2.2 → 0.2.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @atproto-labs/handle-resolver-node
2
2
 
3
+ ## 0.2.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update TypeScript build to rely on references to composite internal projects
8
+
9
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Bundle only necessary files in the NPM tarball, including the `CHANGELOG.md` and `README.md` files (if present).
10
+
11
+ - Updated dependencies [[`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07)]:
12
+ - @atproto-labs/handle-resolver@0.4.4
13
+ - @atproto-labs/fetch-node@0.3.4
14
+ - @atproto/did@0.5.3
15
+
16
+ ## 0.2.3
17
+
18
+ ### Patch Changes
19
+
20
+ - [#5151](https://github.com/bluesky-social/atproto/pull/5151) [`a51c45d`](https://github.com/bluesky-social/atproto/commit/a51c45d38f6bd7b8765f640e564cf921d52162e7) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update dependencies
21
+
22
+ - Updated dependencies [[`60e9b83`](https://github.com/bluesky-social/atproto/commit/60e9b8391f212c274b1f21991ee2a3a2d14f2f88), [`60e9b83`](https://github.com/bluesky-social/atproto/commit/60e9b8391f212c274b1f21991ee2a3a2d14f2f88), [`60e9b83`](https://github.com/bluesky-social/atproto/commit/60e9b8391f212c274b1f21991ee2a3a2d14f2f88), [`60e9b83`](https://github.com/bluesky-social/atproto/commit/60e9b8391f212c274b1f21991ee2a3a2d14f2f88), [`a51c45d`](https://github.com/bluesky-social/atproto/commit/a51c45d38f6bd7b8765f640e564cf921d52162e7), [`60e9b83`](https://github.com/bluesky-social/atproto/commit/60e9b8391f212c274b1f21991ee2a3a2d14f2f88)]:
23
+ - @atproto-labs/fetch-node@0.3.3
24
+ - @atproto/did@0.5.2
25
+ - @atproto-labs/handle-resolver@0.4.3
26
+
3
27
  ## 0.2.2
4
28
 
5
29
  ### Patch Changes
@@ -49,14 +49,14 @@ function handleError(err) {
49
49
  if (err instanceof TypeError)
50
50
  throw err;
51
51
  // If the hostname does not resolve, return null
52
- if (err instanceof Error) {
53
- if (err['code'] === 'ENOTFOUND')
52
+ if (err instanceof Error && 'code' in err) {
53
+ if (err.code === 'ENOTFOUND')
54
54
  return null;
55
55
  // Hostname is not a valid domain name
56
- if (err['code'] === 'EBADNAME')
56
+ if (err.code === 'EBADNAME')
57
57
  throw err;
58
58
  // DNS server unreachable
59
- // if (err['code'] === 'ETIMEOUT') throw err
59
+ // if (err.code === 'ETIMEOUT') throw err
60
60
  }
61
61
  // Historically, errors were not thrown here. A "null" value indicates to the
62
62
  // AtprotoHandleResolver that it should try the fallback resolver.
@@ -1 +1 @@
1
- {"version":3,"file":"node-resolve-txt-factory.js","sourceRoot":"","sources":["../src/node-resolve-txt-factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, lookup, resolveTxt } from 'node:dns/promises'\nimport { isIP } from 'node:net'\nimport { ResolveTxt } from '@atproto-labs/handle-resolver'\n\nexport const nodeResolveTxtDefault: ResolveTxt = (hostname) =>\n resolveTxt(hostname).then(groupChunks, handleError)\n\nexport function nodeResolveTxtFactory(nameservers: string[]): ResolveTxt {\n // Optimization\n if (!nameservers.length) return async () => null\n\n // Build the resolver asynchronously (will be awaited on every use)\n const resolverPromise: Promise<Resolver | null> = Promise.all<string[]>(\n nameservers.map((nameserver) => {\n const [domain, port = null] = nameserver.split(':', 2)\n\n if (port !== null && !/^\\d+$/.test(port)) {\n throw new TypeError(`Invalid name server \"${nameserver}\"`)\n }\n\n return isIP(domain) === 4 || isBracedIPv6(domain)\n ? [nameserver] // No need to lookup\n : lookup(domain, { all: true }).then(\n (r) => r.map((a) => appendPort(a.address, port)),\n // Let's just ignore failed nameservers resolution\n (_err) => [],\n )\n }),\n ).then((results) => {\n const backupIps = results.flat(1)\n // No resolver if no valid IP\n if (!backupIps.length) return null\n\n const resolver = new Resolver()\n resolver.setServers(backupIps)\n return resolver\n })\n\n // Avoid uncaught promise rejection\n void resolverPromise.catch(() => {\n // Should never happen though...\n })\n\n return async (hostname) => {\n const resolver = await resolverPromise\n return resolver\n ? resolver.resolveTxt(hostname).then(groupChunks, handleError)\n : null\n }\n}\n\nfunction isBracedIPv6(address: string): boolean {\n return (\n address.startsWith('[') &&\n address.endsWith(']') &&\n isIP(address.slice(1, -1)) === 6\n )\n}\n\nfunction groupChunks(results: string[][]): string[] {\n return results.map((chunks) => chunks.join(''))\n}\n\nfunction handleError(err: unknown) {\n // Invalid argument type (e.g. hostname is a number)\n if (err instanceof TypeError) throw err\n\n // If the hostname does not resolve, return null\n if (err instanceof Error) {\n if (err['code'] === 'ENOTFOUND') return null\n\n // Hostname is not a valid domain name\n if (err['code'] === 'EBADNAME') throw err\n\n // DNS server unreachable\n // if (err['code'] === 'ETIMEOUT') throw err\n }\n\n // Historically, errors were not thrown here. A \"null\" value indicates to the\n // AtprotoHandleResolver that it should try the fallback resolver.\n\n // @TODO We might want to re-visit this to only apply when an unexpected error\n // occurs (by throwing here). For now, let's keep the same behavior as before.\n\n // throw err\n\n return null\n}\n\nfunction appendPort(address: string, port: string | null): string {\n switch (isIP(address)) {\n case 4:\n return port ? `${address}:${port}` : address\n case 6:\n return port ? `[${address}]:${port}` : `[${address}]`\n default:\n throw new TypeError(`Invalid IP address \"${address}\"`)\n }\n}\n"]}
1
+ {"version":3,"file":"node-resolve-txt-factory.js","sourceRoot":"","sources":["../src/node-resolve-txt-factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, lookup, resolveTxt } from 'node:dns/promises'\nimport { isIP } from 'node:net'\nimport { ResolveTxt } from '@atproto-labs/handle-resolver'\n\nexport const nodeResolveTxtDefault: ResolveTxt = (hostname) =>\n resolveTxt(hostname).then(groupChunks, handleError)\n\nexport function nodeResolveTxtFactory(nameservers: string[]): ResolveTxt {\n // Optimization\n if (!nameservers.length) return async () => null\n\n // Build the resolver asynchronously (will be awaited on every use)\n const resolverPromise: Promise<Resolver | null> = Promise.all<string[]>(\n nameservers.map((nameserver) => {\n const [domain, port = null] = nameserver.split(':', 2)\n\n if (port !== null && !/^\\d+$/.test(port)) {\n throw new TypeError(`Invalid name server \"${nameserver}\"`)\n }\n\n return isIP(domain) === 4 || isBracedIPv6(domain)\n ? [nameserver] // No need to lookup\n : lookup(domain, { all: true }).then(\n (r) => r.map((a) => appendPort(a.address, port)),\n // Let's just ignore failed nameservers resolution\n (_err) => [],\n )\n }),\n ).then((results) => {\n const backupIps = results.flat(1)\n // No resolver if no valid IP\n if (!backupIps.length) return null\n\n const resolver = new Resolver()\n resolver.setServers(backupIps)\n return resolver\n })\n\n // Avoid uncaught promise rejection\n void resolverPromise.catch(() => {\n // Should never happen though...\n })\n\n return async (hostname) => {\n const resolver = await resolverPromise\n return resolver\n ? resolver.resolveTxt(hostname).then(groupChunks, handleError)\n : null\n }\n}\n\nfunction isBracedIPv6(address: string): boolean {\n return (\n address.startsWith('[') &&\n address.endsWith(']') &&\n isIP(address.slice(1, -1)) === 6\n )\n}\n\nfunction groupChunks(results: string[][]): string[] {\n return results.map((chunks) => chunks.join(''))\n}\n\nfunction handleError(err: unknown) {\n // Invalid argument type (e.g. hostname is a number)\n if (err instanceof TypeError) throw err\n\n // If the hostname does not resolve, return null\n if (err instanceof Error && 'code' in err) {\n if (err.code === 'ENOTFOUND') return null\n\n // Hostname is not a valid domain name\n if (err.code === 'EBADNAME') throw err\n\n // DNS server unreachable\n // if (err.code === 'ETIMEOUT') throw err\n }\n\n // Historically, errors were not thrown here. A \"null\" value indicates to the\n // AtprotoHandleResolver that it should try the fallback resolver.\n\n // @TODO We might want to re-visit this to only apply when an unexpected error\n // occurs (by throwing here). For now, let's keep the same behavior as before.\n\n // throw err\n\n return null\n}\n\nfunction appendPort(address: string, port: string | null): string {\n switch (isIP(address)) {\n case 4:\n return port ? `${address}:${port}` : address\n case 6:\n return port ? `[${address}]:${port}` : `[${address}]`\n default:\n throw new TypeError(`Invalid IP address \"${address}\"`)\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto-labs/handle-resolver-node",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "license": "MIT",
5
5
  "description": "Node specific ATProto handle to DID resolver",
6
6
  "keywords": [
@@ -16,6 +16,10 @@
16
16
  "url": "https://github.com/bluesky-social/atproto",
17
17
  "directory": "packages/internal/handle-resolver-node"
18
18
  },
19
+ "files": [
20
+ "./dist",
21
+ "./CHANGELOG.md"
22
+ ],
19
23
  "type": "module",
20
24
  "exports": {
21
25
  ".": {
@@ -27,11 +31,10 @@
27
31
  "node": ">=22"
28
32
  },
29
33
  "dependencies": {
30
- "@atproto-labs/fetch-node": "^0.3.1",
31
- "@atproto-labs/handle-resolver": "^0.4.2",
32
- "@atproto/did": "^0.5.1"
34
+ "@atproto-labs/fetch-node": "^0.3.4",
35
+ "@atproto/did": "^0.5.3",
36
+ "@atproto-labs/handle-resolver": "^0.4.4"
33
37
  },
34
- "devDependencies": {},
35
38
  "scripts": {
36
39
  "build": "tsgo --build tsconfig.build.json"
37
40
  }
@@ -1,50 +0,0 @@
1
- import { Fetch, safeFetchWrap } from '@atproto-labs/fetch-node'
2
- import {
3
- AtprotoHandleResolver,
4
- HandleResolver,
5
- } from '@atproto-labs/handle-resolver'
6
- import {
7
- nodeResolveTxtDefault,
8
- nodeResolveTxtFactory,
9
- } from './node-resolve-txt-factory.js'
10
-
11
- export type AtprotoHandleResolverNodeOptions = {
12
- /**
13
- * List of backup nameservers to use in case the primary ones fail. Will
14
- * default to no fallback nameservers.
15
- */
16
- fallbackNameservers?: string[]
17
-
18
- /**
19
- * Fetch function to use for HTTP requests. Allows customizing the request
20
- * behavior, e.g. adding headers, setting a timeout, mocking, etc. The
21
- * provided fetch function will be wrapped with a safeFetchWrap function that
22
- * adds SSRF protection.
23
- *
24
- * @default `globalThis.fetch`
25
- */
26
- fetch?: Fetch
27
- }
28
-
29
- export class AtprotoHandleResolverNode
30
- extends AtprotoHandleResolver
31
- implements HandleResolver
32
- {
33
- constructor({
34
- fetch = globalThis.fetch,
35
- fallbackNameservers,
36
- }: AtprotoHandleResolverNodeOptions = {}) {
37
- super({
38
- fetch: safeFetchWrap({
39
- fetch,
40
- timeout: 3000, // 3 seconds
41
- ssrfProtection: true,
42
- responseMaxSize: 10 * 1048, // DID are max 2048 characters, 10kb for safety
43
- }),
44
- resolveTxt: nodeResolveTxtDefault,
45
- resolveTxtFallback: fallbackNameservers?.length
46
- ? nodeResolveTxtFactory(fallbackNameservers)
47
- : undefined,
48
- })
49
- }
50
- }
package/src/index.ts DELETED
@@ -1 +0,0 @@
1
- export * from './atproto-handle-resolver-node.js'
@@ -1,99 +0,0 @@
1
- import { Resolver, lookup, resolveTxt } from 'node:dns/promises'
2
- import { isIP } from 'node:net'
3
- import { ResolveTxt } from '@atproto-labs/handle-resolver'
4
-
5
- export const nodeResolveTxtDefault: ResolveTxt = (hostname) =>
6
- resolveTxt(hostname).then(groupChunks, handleError)
7
-
8
- export function nodeResolveTxtFactory(nameservers: string[]): ResolveTxt {
9
- // Optimization
10
- if (!nameservers.length) return async () => null
11
-
12
- // Build the resolver asynchronously (will be awaited on every use)
13
- const resolverPromise: Promise<Resolver | null> = Promise.all<string[]>(
14
- nameservers.map((nameserver) => {
15
- const [domain, port = null] = nameserver.split(':', 2)
16
-
17
- if (port !== null && !/^\d+$/.test(port)) {
18
- throw new TypeError(`Invalid name server "${nameserver}"`)
19
- }
20
-
21
- return isIP(domain) === 4 || isBracedIPv6(domain)
22
- ? [nameserver] // No need to lookup
23
- : lookup(domain, { all: true }).then(
24
- (r) => r.map((a) => appendPort(a.address, port)),
25
- // Let's just ignore failed nameservers resolution
26
- (_err) => [],
27
- )
28
- }),
29
- ).then((results) => {
30
- const backupIps = results.flat(1)
31
- // No resolver if no valid IP
32
- if (!backupIps.length) return null
33
-
34
- const resolver = new Resolver()
35
- resolver.setServers(backupIps)
36
- return resolver
37
- })
38
-
39
- // Avoid uncaught promise rejection
40
- void resolverPromise.catch(() => {
41
- // Should never happen though...
42
- })
43
-
44
- return async (hostname) => {
45
- const resolver = await resolverPromise
46
- return resolver
47
- ? resolver.resolveTxt(hostname).then(groupChunks, handleError)
48
- : null
49
- }
50
- }
51
-
52
- function isBracedIPv6(address: string): boolean {
53
- return (
54
- address.startsWith('[') &&
55
- address.endsWith(']') &&
56
- isIP(address.slice(1, -1)) === 6
57
- )
58
- }
59
-
60
- function groupChunks(results: string[][]): string[] {
61
- return results.map((chunks) => chunks.join(''))
62
- }
63
-
64
- function handleError(err: unknown) {
65
- // Invalid argument type (e.g. hostname is a number)
66
- if (err instanceof TypeError) throw err
67
-
68
- // If the hostname does not resolve, return null
69
- if (err instanceof Error) {
70
- if (err['code'] === 'ENOTFOUND') return null
71
-
72
- // Hostname is not a valid domain name
73
- if (err['code'] === 'EBADNAME') throw err
74
-
75
- // DNS server unreachable
76
- // if (err['code'] === 'ETIMEOUT') throw err
77
- }
78
-
79
- // Historically, errors were not thrown here. A "null" value indicates to the
80
- // AtprotoHandleResolver that it should try the fallback resolver.
81
-
82
- // @TODO We might want to re-visit this to only apply when an unexpected error
83
- // occurs (by throwing here). For now, let's keep the same behavior as before.
84
-
85
- // throw err
86
-
87
- return null
88
- }
89
-
90
- function appendPort(address: string, port: string | null): string {
91
- switch (isIP(address)) {
92
- case 4:
93
- return port ? `${address}:${port}` : address
94
- case 6:
95
- return port ? `[${address}]:${port}` : `[${address}]`
96
- default:
97
- throw new TypeError(`Invalid IP address "${address}"`)
98
- }
99
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": ["../../../tsconfig/node.json"],
3
- "compilerOptions": {
4
- "rootDir": "./src",
5
- "outDir": "./dist",
6
- },
7
- "include": ["./src"],
8
- }
@@ -1 +0,0 @@
1
- {"version":"7.0.0-dev.20260614.1","root":["./src/atproto-handle-resolver-node.ts","./src/index.ts","./src/node-resolve-txt-factory.ts"]}
package/tsconfig.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "include": [],
3
- "references": [{ "path": "./tsconfig.build.json" }],
4
- }