@atproto-labs/handle-resolver-node 0.2.4 → 0.2.6
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 +20 -0
- package/dist/atproto-handle-resolver-node.d.ts +11 -3
- package/dist/atproto-handle-resolver-node.d.ts.map +1 -1
- package/dist/atproto-handle-resolver-node.js +2 -1
- package/dist/atproto-handle-resolver-node.js.map +1 -1
- package/dist/node-resolve-txt-factory.d.ts +1 -1
- package/dist/node-resolve-txt-factory.d.ts.map +1 -1
- package/dist/node-resolve-txt-factory.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @atproto-labs/handle-resolver-node
|
|
2
2
|
|
|
3
|
+
## 0.2.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#5193](https://github.com/bluesky-social/atproto/pull/5193) [`ce386ee`](https://github.com/bluesky-social/atproto/commit/ce386eed324f813601db57f873fbb3b987492001) Thanks [@Rex0Lux](https://github.com/Rex0Lux)! - Add an `onError` observability option to the handle resolvers. `WellKnownHandleResolver` previously swallowed every non-abort failure and returned `null`, indistinguishable from "no `.well-known/atproto-did` endpoint exists". Passing `onError` when constructing a resolver (including `AtprotoHandleResolver` and `AtprotoHandleResolverNode`) exposes the underlying cause (SSRF blocks, 5xx upstream errors, redirects, network errors, etc.) without changing the `null` return contract. Because it is set on the instance, it also covers resolution performed internally, for example by an OAuth client the resolver is passed to.
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`ce386ee`](https://github.com/bluesky-social/atproto/commit/ce386eed324f813601db57f873fbb3b987492001)]:
|
|
10
|
+
- @atproto-labs/handle-resolver@0.4.6
|
|
11
|
+
|
|
12
|
+
## 0.2.5
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [#5197](https://github.com/bluesky-social/atproto/pull/5197) [`a0c49d9`](https://github.com/bluesky-social/atproto/commit/a0c49d9e8bc685c5a747a8d3b2775c73c63fdb6f) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Rewrite import statements to be compatible with TypeScript's `verbatimModuleSyntax` config.
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [[`a0c49d9`](https://github.com/bluesky-social/atproto/commit/a0c49d9e8bc685c5a747a8d3b2775c73c63fdb6f)]:
|
|
19
|
+
- @atproto-labs/handle-resolver@0.4.5
|
|
20
|
+
- @atproto-labs/fetch-node@0.3.5
|
|
21
|
+
- @atproto/did@0.5.4
|
|
22
|
+
|
|
3
23
|
## 0.2.4
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Fetch } from '@atproto-labs/fetch-node';
|
|
2
|
-
import { AtprotoHandleResolver, HandleResolver } from '@atproto-labs/handle-resolver';
|
|
1
|
+
import { type Fetch } from '@atproto-labs/fetch-node';
|
|
2
|
+
import { AtprotoHandleResolver, type HandleResolver, type HandleResolverErrorHandler } from '@atproto-labs/handle-resolver';
|
|
3
3
|
export type AtprotoHandleResolverNodeOptions = {
|
|
4
4
|
/**
|
|
5
5
|
* List of backup nameservers to use in case the primary ones fail. Will
|
|
@@ -15,8 +15,16 @@ export type AtprotoHandleResolverNodeOptions = {
|
|
|
15
15
|
* @default `globalThis.fetch`
|
|
16
16
|
*/
|
|
17
17
|
fetch?: Fetch;
|
|
18
|
+
/**
|
|
19
|
+
* Optional observability hook, invoked when handle resolution fails for a
|
|
20
|
+
* non-abort reason (network error, SSRF block, non-2xx response, etc.). The
|
|
21
|
+
* resolver still returns `null`; this only exposes the cause for logging or
|
|
22
|
+
* telemetry. Handy for diagnosing why a handle fails to resolve, e.g. when a
|
|
23
|
+
* PDS sits behind a firewall that trips SSRF protection.
|
|
24
|
+
*/
|
|
25
|
+
onError?: HandleResolverErrorHandler;
|
|
18
26
|
};
|
|
19
27
|
export declare class AtprotoHandleResolverNode extends AtprotoHandleResolver implements HandleResolver {
|
|
20
|
-
constructor({ fetch, fallbackNameservers, }?: AtprotoHandleResolverNodeOptions);
|
|
28
|
+
constructor({ fetch, fallbackNameservers, onError, }?: AtprotoHandleResolverNodeOptions);
|
|
21
29
|
}
|
|
22
30
|
//# sourceMappingURL=atproto-handle-resolver-node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atproto-handle-resolver-node.d.ts","sourceRoot":"","sources":["../src/atproto-handle-resolver-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAiB,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"atproto-handle-resolver-node.d.ts","sourceRoot":"","sources":["../src/atproto-handle-resolver-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAiB,MAAM,0BAA0B,CAAA;AACpE,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,0BAA0B,EAChC,MAAM,+BAA+B,CAAA;AAMtC,MAAM,MAAM,gCAAgC,GAAG;IAC7C;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE9B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,KAAK,CAAA;IAEb;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,0BAA0B,CAAA;CACrC,CAAA;AAED,qBAAa,yBACX,SAAQ,qBACR,YAAW,cAAc;IAEzB,YAAY,EACV,KAAwB,EACxB,mBAAmB,EACnB,OAAO,GACR,GAAE,gCAAqC,EAcvC;CACF"}
|
|
@@ -2,7 +2,7 @@ import { safeFetchWrap } from '@atproto-labs/fetch-node';
|
|
|
2
2
|
import { AtprotoHandleResolver, } from '@atproto-labs/handle-resolver';
|
|
3
3
|
import { nodeResolveTxtDefault, nodeResolveTxtFactory, } from './node-resolve-txt-factory.js';
|
|
4
4
|
export class AtprotoHandleResolverNode extends AtprotoHandleResolver {
|
|
5
|
-
constructor({ fetch = globalThis.fetch, fallbackNameservers, } = {}) {
|
|
5
|
+
constructor({ fetch = globalThis.fetch, fallbackNameservers, onError, } = {}) {
|
|
6
6
|
super({
|
|
7
7
|
fetch: safeFetchWrap({
|
|
8
8
|
fetch,
|
|
@@ -14,6 +14,7 @@ export class AtprotoHandleResolverNode extends AtprotoHandleResolver {
|
|
|
14
14
|
resolveTxtFallback: fallbackNameservers?.length
|
|
15
15
|
? nodeResolveTxtFactory(fallbackNameservers)
|
|
16
16
|
: undefined,
|
|
17
|
+
onError,
|
|
17
18
|
});
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atproto-handle-resolver-node.js","sourceRoot":"","sources":["../src/atproto-handle-resolver-node.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"atproto-handle-resolver-node.js","sourceRoot":"","sources":["../src/atproto-handle-resolver-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACpE,OAAO,EACL,qBAAqB,GAGtB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,+BAA+B,CAAA;AA6BtC,MAAM,OAAO,yBACX,SAAQ,qBAAqB;IAG7B,YAAY,EACV,KAAK,GAAG,UAAU,CAAC,KAAK,EACxB,mBAAmB,EACnB,OAAO,GACR,GAAqC,EAAE;QACtC,KAAK,CAAC;YACJ,KAAK,EAAE,aAAa,CAAC;gBACnB,KAAK;gBACL,OAAO,EAAE,IAAI,EAAE,YAAY;gBAC3B,cAAc,EAAE,IAAI;gBACpB,eAAe,EAAE,EAAE,GAAG,IAAI,EAAE,+CAA+C;aAC5E,CAAC;YACF,UAAU,EAAE,qBAAqB;YACjC,kBAAkB,EAAE,mBAAmB,EAAE,MAAM;gBAC7C,CAAC,CAAC,qBAAqB,CAAC,mBAAmB,CAAC;gBAC5C,CAAC,CAAC,SAAS;YACb,OAAO;SACR,CAAC,CAAA;IACJ,CAAC;CACF","sourcesContent":["import { type Fetch, safeFetchWrap } from '@atproto-labs/fetch-node'\nimport {\n AtprotoHandleResolver,\n type HandleResolver,\n type HandleResolverErrorHandler,\n} from '@atproto-labs/handle-resolver'\nimport {\n nodeResolveTxtDefault,\n nodeResolveTxtFactory,\n} from './node-resolve-txt-factory.js'\n\nexport type AtprotoHandleResolverNodeOptions = {\n /**\n * List of backup nameservers to use in case the primary ones fail. Will\n * default to no fallback nameservers.\n */\n fallbackNameservers?: string[]\n\n /**\n * Fetch function to use for HTTP requests. Allows customizing the request\n * behavior, e.g. adding headers, setting a timeout, mocking, etc. The\n * provided fetch function will be wrapped with a safeFetchWrap function that\n * adds SSRF protection.\n *\n * @default `globalThis.fetch`\n */\n fetch?: Fetch\n\n /**\n * Optional observability hook, invoked when handle resolution fails for a\n * non-abort reason (network error, SSRF block, non-2xx response, etc.). The\n * resolver still returns `null`; this only exposes the cause for logging or\n * telemetry. Handy for diagnosing why a handle fails to resolve, e.g. when a\n * PDS sits behind a firewall that trips SSRF protection.\n */\n onError?: HandleResolverErrorHandler\n}\n\nexport class AtprotoHandleResolverNode\n extends AtprotoHandleResolver\n implements HandleResolver\n{\n constructor({\n fetch = globalThis.fetch,\n fallbackNameservers,\n onError,\n }: AtprotoHandleResolverNodeOptions = {}) {\n super({\n fetch: safeFetchWrap({\n fetch,\n timeout: 3000, // 3 seconds\n ssrfProtection: true,\n responseMaxSize: 10 * 1048, // DID are max 2048 characters, 10kb for safety\n }),\n resolveTxt: nodeResolveTxtDefault,\n resolveTxtFallback: fallbackNameservers?.length\n ? nodeResolveTxtFactory(fallbackNameservers)\n : undefined,\n onError,\n })\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ResolveTxt } from '@atproto-labs/handle-resolver';
|
|
1
|
+
import type { ResolveTxt } from '@atproto-labs/handle-resolver';
|
|
2
2
|
export declare const nodeResolveTxtDefault: ResolveTxt;
|
|
3
3
|
export declare function nodeResolveTxtFactory(nameservers: string[]): ResolveTxt;
|
|
4
4
|
//# sourceMappingURL=node-resolve-txt-factory.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-resolve-txt-factory.d.ts","sourceRoot":"","sources":["../src/node-resolve-txt-factory.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"node-resolve-txt-factory.d.ts","sourceRoot":"","sources":["../src/node-resolve-txt-factory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,eAAO,MAAM,qBAAqB,EAAE,UACiB,CAAA;AAErD,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,UAAU,CA0CvE"}
|
|
@@ -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 && '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"]}
|
|
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 type { 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.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Node specific ATProto handle to DID resolver",
|
|
6
6
|
"keywords": [
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"node": ">=22"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@atproto-labs/fetch-node": "^0.3.
|
|
35
|
-
"@atproto/did": "^0.5.
|
|
36
|
-
"@atproto-labs/handle-resolver": "^0.4.
|
|
34
|
+
"@atproto-labs/fetch-node": "^0.3.5",
|
|
35
|
+
"@atproto/did": "^0.5.4",
|
|
36
|
+
"@atproto-labs/handle-resolver": "^0.4.6"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsgo --build tsconfig.build.json"
|