@atproto-labs/identity-resolver 0.1.19 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @atproto-labs/identity-resolver
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#3982](https://github.com/bluesky-social/atproto/pull/3982) [`4c2d49917`](https://github.com/bluesky-social/atproto/commit/4c2d499178c61eb8a9d7f658e89fe68fa07f81e7) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Identity resolver's `resolve()` method returns value consistent with `com.atproto.identity.resolveIdentity`
8
+
9
+ - [#3982](https://github.com/bluesky-social/atproto/pull/3982) [`4c2d49917`](https://github.com/bluesky-social/atproto/commit/4c2d499178c61eb8a9d7f658e89fe68fa07f81e7) Thanks [@matthieusieben](https://github.com/matthieusieben)! - `IdentityResolver` is now an interface. The `IdentityResolverProto` class is the default implementation for the `IdentityResolver` interface.
10
+
11
+ ### Patch Changes
12
+
13
+ - [#3982](https://github.com/bluesky-social/atproto/pull/3982) [`4c2d49917`](https://github.com/bluesky-social/atproto/commit/4c2d499178c61eb8a9d7f658e89fe68fa07f81e7) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Export `HANDLE_INVALID` constant
14
+
15
+ ## 0.2.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Return the whole did document when resolving an identity
20
+
21
+ - [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Reject did documents containing invalid `alsoKnownAs` ATProto handles
22
+
23
+ - [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Use `IdentityResolverError` instances instead of `TypeError`
24
+
25
+ ### Patch Changes
26
+
27
+ - [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Perform a bi-directional check when resolving identity from did
28
+
29
+ - [#3977](https://github.com/bluesky-social/atproto/pull/3977) [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Allow non-normalized handles in did documents
30
+
31
+ - Updated dependencies [[`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47), [`9dac8b0c6`](https://github.com/bluesky-social/atproto/commit/9dac8b0c600520ecb0066ac104787b27668dea47)]:
32
+ - @atproto-labs/handle-resolver@0.3.0
33
+
3
34
  ## 0.1.19
4
35
 
5
36
  ### Patch Changes
@@ -0,0 +1,20 @@
1
+ import { AtprotoDid, AtprotoIdentityDidMethods, DidDocument, DidResolver, ResolveDidOptions } from '@atproto-labs/did-resolver';
2
+ import { HandleResolver, ResolveHandleOptions } from '@atproto-labs/handle-resolver';
3
+ import { IdentityInfo, IdentityResolver, ResolveIdentityOptions } from './identity-resolver.js';
4
+ /**
5
+ * Implementation of the official ATPROTO identity resolution strategy.
6
+ * This implementation relies on two primitives:
7
+ * - DID resolution (using the `DidResolver` interface)
8
+ * - Handle resolution (using the `HandleResolver` interface)
9
+ */
10
+ export declare class AtprotoIdentityResolver implements IdentityResolver {
11
+ protected readonly didResolver: DidResolver<AtprotoIdentityDidMethods>;
12
+ protected readonly handleResolver: HandleResolver;
13
+ constructor(didResolver: DidResolver<AtprotoIdentityDidMethods>, handleResolver: HandleResolver);
14
+ resolve(input: string, options?: ResolveIdentityOptions): Promise<IdentityInfo>;
15
+ resolveFromDid(did: AtprotoDid, options?: ResolveDidOptions): Promise<IdentityInfo>;
16
+ resolveFromHandle(handle: string, options?: ResolveHandleOptions): Promise<IdentityInfo>;
17
+ getDocumentFromDid(did: AtprotoDid, options?: ResolveDidOptions): Promise<DidDocument<AtprotoIdentityDidMethods>>;
18
+ getDocumentFromHandle(input: string, options?: ResolveHandleOptions): Promise<DidDocument<AtprotoIdentityDidMethods>>;
19
+ }
20
+ //# sourceMappingURL=atproto-identity-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atproto-identity-resolver.d.ts","sourceRoot":"","sources":["../src/atproto-identity-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,WAAW,EACX,WAAW,EACX,iBAAiB,EAElB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACL,cAAc,EACd,oBAAoB,EACrB,MAAM,+BAA+B,CAAA;AAGtC,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,wBAAwB,CAAA;AAO/B;;;;;GAKG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAE5D,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC;IACtE,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc;gBAD9B,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC,EACnD,cAAc,EAAE,cAAc;IAGtC,OAAO,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,YAAY,CAAC;IAMX,cAAc,CACzB,GAAG,EAAE,UAAU,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC;IAqBX,iBAAiB,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,YAAY,CAAC;IAYX,kBAAkB,CAC7B,GAAG,EAAE,UAAU,EACf,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;IAIrC,qBAAqB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;CA8BnD"}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AtprotoIdentityResolver = void 0;
4
+ const did_resolver_1 = require("@atproto-labs/did-resolver");
5
+ const constants_js_1 = require("./constants.js");
6
+ const identity_resolver_error_js_1 = require("./identity-resolver-error.js");
7
+ const util_js_1 = require("./util.js");
8
+ // @TODO Move this to its own package as soon as we have a distinct
9
+ // implementation based on XRPC calls to the
10
+ // "com.atproto.identity.resolveIdentity" method.
11
+ /**
12
+ * Implementation of the official ATPROTO identity resolution strategy.
13
+ * This implementation relies on two primitives:
14
+ * - DID resolution (using the `DidResolver` interface)
15
+ * - Handle resolution (using the `HandleResolver` interface)
16
+ */
17
+ class AtprotoIdentityResolver {
18
+ constructor(didResolver, handleResolver) {
19
+ Object.defineProperty(this, "didResolver", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: didResolver
24
+ });
25
+ Object.defineProperty(this, "handleResolver", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: handleResolver
30
+ });
31
+ }
32
+ async resolve(input, options) {
33
+ return (0, did_resolver_1.isAtprotoDid)(input)
34
+ ? this.resolveFromDid(input, options)
35
+ : this.resolveFromHandle(input, options);
36
+ }
37
+ async resolveFromDid(did, options) {
38
+ const document = await this.getDocumentFromDid(did, options);
39
+ options?.signal?.throwIfAborted();
40
+ // We will only return the document's handle alias if it resolves to the
41
+ // same DID as the input.
42
+ const handle = (0, util_js_1.extractNormalizedHandle)(document);
43
+ const resolvedDid = handle
44
+ ? await this.handleResolver
45
+ .resolve(handle, options)
46
+ .catch(() => undefined) // Ignore errors (temporarily unavailable)
47
+ : undefined;
48
+ return {
49
+ did: document.id,
50
+ didDoc: document,
51
+ handle: handle && resolvedDid === did ? handle : constants_js_1.HANDLE_INVALID,
52
+ };
53
+ }
54
+ async resolveFromHandle(handle, options) {
55
+ const document = await this.getDocumentFromHandle(handle, options);
56
+ // @NOTE bi-directional resolution enforced in getDocumentFromHandle()
57
+ return {
58
+ did: document.id,
59
+ didDoc: document,
60
+ handle: (0, util_js_1.extractNormalizedHandle)(document) || constants_js_1.HANDLE_INVALID,
61
+ };
62
+ }
63
+ async getDocumentFromDid(did, options) {
64
+ return this.didResolver.resolve(did, options);
65
+ }
66
+ async getDocumentFromHandle(input, options) {
67
+ const handle = (0, util_js_1.asNormalizedHandle)(input);
68
+ if (!handle) {
69
+ throw new identity_resolver_error_js_1.IdentityResolverError(`Invalid handle "${input}" provided.`);
70
+ }
71
+ const did = await this.handleResolver.resolve(handle, options);
72
+ if (!did) {
73
+ throw new identity_resolver_error_js_1.IdentityResolverError(`Handle "${handle}" does not resolve to a DID`);
74
+ }
75
+ options?.signal?.throwIfAborted();
76
+ // Note: Not using "return this.resolveDid(did, options)" to make the extra
77
+ // check for the handle in the DID document:
78
+ const document = await this.didResolver.resolve(did, options);
79
+ // Enforce bi-directional resolution
80
+ if (handle !== (0, util_js_1.extractNormalizedHandle)(document)) {
81
+ throw new identity_resolver_error_js_1.IdentityResolverError(`Did document for "${did}" does not include the handle "${handle}"`);
82
+ }
83
+ return document;
84
+ }
85
+ }
86
+ exports.AtprotoIdentityResolver = AtprotoIdentityResolver;
87
+ //# sourceMappingURL=atproto-identity-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atproto-identity-resolver.js","sourceRoot":"","sources":["../src/atproto-identity-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const HANDLE_INVALID = "handle.invalid";
2
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,mBAAmB,CAAA"}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HANDLE_INVALID = void 0;
4
+ exports.HANDLE_INVALID = 'handle.invalid';
5
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,cAAc,GAAG,gBAAgB,CAAA"}
@@ -0,0 +1,4 @@
1
+ export declare class IdentityResolverError extends Error {
2
+ name: string;
3
+ }
4
+ //# sourceMappingURL=identity-resolver-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-resolver-error.d.ts","sourceRoot":"","sources":["../src/identity-resolver-error.ts"],"names":[],"mappings":"AAAA,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,IAAI,SAA0B;CAC/B"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IdentityResolverError = void 0;
4
+ class IdentityResolverError extends Error {
5
+ constructor() {
6
+ super(...arguments);
7
+ Object.defineProperty(this, "name", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: 'IdentityResolverError'
12
+ });
13
+ }
14
+ }
15
+ exports.IdentityResolverError = IdentityResolverError;
16
+ //# sourceMappingURL=identity-resolver-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-resolver-error.js","sourceRoot":"","sources":["../src/identity-resolver-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,qBAAsB,SAAQ,KAAK;IAAhD;;QACE;;;;mBAAO,uBAAuB;WAAA;IAChC,CAAC;CAAA;AAFD,sDAEC"}
@@ -1,17 +1,20 @@
1
- import { DidDocument, DidResolver, ResolveDidOptions } from '@atproto-labs/did-resolver';
2
- import { AtprotoIdentityDidMethods, HandleResolver, ResolveHandleOptions, ResolvedHandle } from '@atproto-labs/handle-resolver';
3
- export type ResolvedIdentity = {
4
- did: NonNullable<ResolvedHandle>;
5
- pds: URL;
6
- handle?: string;
1
+ import { AtprotoDid, AtprotoIdentityDidMethods, DidDocument } from '@atproto-labs/did-resolver';
2
+ import { HANDLE_INVALID } from './constants';
3
+ export type IdentityInfo = {
4
+ did: AtprotoDid;
5
+ didDoc: DidDocument<AtprotoIdentityDidMethods>;
6
+ /**
7
+ * Will be 'handle.invalid' if the handle does not resolve to the
8
+ * same DID as the input, or if the handle is not present in the DID
9
+ * document.
10
+ */
11
+ handle: typeof HANDLE_INVALID | string;
7
12
  };
8
- export type ResolveIdentityOptions = ResolveDidOptions & ResolveHandleOptions;
9
- export declare class IdentityResolver {
10
- readonly didResolver: DidResolver<AtprotoIdentityDidMethods>;
11
- readonly handleResolver: HandleResolver;
12
- constructor(didResolver: DidResolver<AtprotoIdentityDidMethods>, handleResolver: HandleResolver);
13
- resolve(input: string, options?: ResolveIdentityOptions): Promise<ResolvedIdentity>;
14
- getDocumentFromDid(did: NonNullable<ResolvedHandle>, options?: ResolveDidOptions): Promise<DidDocument<AtprotoIdentityDidMethods>>;
15
- getDocumentFromHandle(input: string, options?: ResolveHandleOptions): Promise<DidDocument<AtprotoIdentityDidMethods>>;
13
+ export type ResolveIdentityOptions = {
14
+ signal?: AbortSignal;
15
+ noCache?: boolean;
16
+ };
17
+ export interface IdentityResolver {
18
+ resolve(identifier: string, options?: ResolveIdentityOptions): Promise<IdentityInfo>;
16
19
  }
17
20
  //# sourceMappingURL=identity-resolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity-resolver.d.ts","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,WAAW,EACX,WAAW,EAEX,iBAAiB,EAClB,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,oBAAoB,EACpB,cAAc,EAEf,MAAM,+BAA+B,CAAA;AAEtC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,WAAW,CAAC,cAAc,CAAC,CAAA;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,GAAG,oBAAoB,CAAA;AAE7E,qBAAa,gBAAgB;IAEzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC;IAC5D,QAAQ,CAAC,cAAc,EAAE,cAAc;gBAD9B,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC,EACnD,cAAc,EAAE,cAAc;IAG5B,OAAO,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IAuBf,kBAAkB,CAC7B,GAAG,EAAE,WAAW,CAAC,cAAc,CAAC,EAChC,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;IAIrC,qBAAqB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;CAyBnD"}
1
+ {"version":3,"file":"identity-resolver.d.ts","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,yBAAyB,EACzB,WAAW,EACZ,MAAM,4BAA4B,CAAA;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAI5C,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,UAAU,CAAA;IAEf,MAAM,EAAE,WAAW,CAAC,yBAAyB,CAAC,CAAA;IAE9C;;;;OAIG;IACH,MAAM,EAAE,OAAO,cAAc,GAAG,MAAM,CAAA;CACvC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CACL,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAAA;CACzB"}
@@ -1,75 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.IdentityResolver = void 0;
4
- const syntax_1 = require("@atproto/syntax");
5
- const handle_resolver_1 = require("@atproto-labs/handle-resolver");
6
- class IdentityResolver {
7
- constructor(didResolver, handleResolver) {
8
- Object.defineProperty(this, "didResolver", {
9
- enumerable: true,
10
- configurable: true,
11
- writable: true,
12
- value: didResolver
13
- });
14
- Object.defineProperty(this, "handleResolver", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: handleResolver
19
- });
20
- }
21
- async resolve(input, options) {
22
- const document = (0, handle_resolver_1.isResolvedHandle)(input)
23
- ? await this.getDocumentFromDid(input, options)
24
- : await this.getDocumentFromHandle(input, options);
25
- const service = document.service?.find((isAtprotoPersonalDataServerService), document);
26
- if (!service) {
27
- throw new TypeError(`No valid "AtprotoPersonalDataServer" service found in "${document.id}" DID document`);
28
- }
29
- return {
30
- did: document.id,
31
- pds: new URL(service.serviceEndpoint),
32
- handle: extractHandle(document),
33
- };
34
- }
35
- async getDocumentFromDid(did, options) {
36
- return this.didResolver.resolve(did, options);
37
- }
38
- async getDocumentFromHandle(input, options) {
39
- const handle = (0, syntax_1.normalizeAndEnsureValidHandle)(input);
40
- const did = await this.handleResolver.resolve(handle, options);
41
- if (!did) {
42
- throw new TypeError(`Handle "${handle}" does not resolve to a DID`);
43
- }
44
- options?.signal?.throwIfAborted();
45
- // Note: Not using "return this.resolveDid(did, options)" to make the extra
46
- // check for the handle in the DID document:
47
- const document = await this.didResolver.resolve(did, options);
48
- // Ensure that the handle is included in the document
49
- if (!document.alsoKnownAs?.includes(`at://${handle}`)) {
50
- throw new TypeError(`Did document for "${did}" does not include the handle "${handle}"`);
51
- }
52
- return document;
53
- }
54
- }
55
- exports.IdentityResolver = IdentityResolver;
56
- function extractHandle(document) {
57
- if (document.alsoKnownAs) {
58
- for (const h of document.alsoKnownAs) {
59
- if (h.startsWith('at://')) {
60
- const handle = h.slice(5);
61
- if ((0, syntax_1.isValidHandle)(handle))
62
- return handle;
63
- }
64
- }
65
- }
66
- return undefined;
67
- }
68
- function isAtprotoPersonalDataServerService(s) {
69
- return (typeof s.serviceEndpoint === 'string' &&
70
- s.type === 'AtprotoPersonalDataServer' &&
71
- (s.id.startsWith('#')
72
- ? s.id === '#atproto_pds'
73
- : s.id === `${this.id}#atproto_pds`));
74
- }
75
3
  //# sourceMappingURL=identity-resolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity-resolver.js","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":";;;AAAA,4CAA8E;AAQ9E,mEAMsC;AAUtC,MAAa,gBAAgB;IAC3B,YACW,WAAmD,EACnD,cAA8B;QADvC;;;;mBAAS,WAAW;WAAwC;QAC5D;;;;mBAAS,cAAc;WAAgB;IACtC,CAAC;IAEG,KAAK,CAAC,OAAO,CAClB,KAAa,EACb,OAAgC;QAEhC,MAAM,QAAQ,GAAG,IAAA,kCAAgB,EAAC,KAAK,CAAC;YACtC,CAAC,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC;YAC/C,CAAC,CAAC,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAEpD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,CACpC,CAAA,kCAA6D,CAAA,EAC7D,QAAQ,CACT,CAAA;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,SAAS,CACjB,0DAA0D,QAAQ,CAAC,EAAE,gBAAgB,CACtF,CAAA;QACH,CAAC;QAED,OAAO;YACL,GAAG,EAAE,QAAQ,CAAC,EAAE;YAChB,GAAG,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC;YACrC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC;SAChC,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,kBAAkB,CAC7B,GAAgC,EAChC,OAA2B;QAE3B,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAC/C,CAAC;IAEM,KAAK,CAAC,qBAAqB,CAChC,KAAa,EACb,OAA8B;QAE9B,MAAM,MAAM,GAAG,IAAA,sCAA6B,EAAC,KAAK,CAAC,CAAA;QAEnD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAE9D,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,SAAS,CAAC,WAAW,MAAM,6BAA6B,CAAC,CAAA;QACrE,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA;QAEjC,2EAA2E;QAC3E,4CAA4C;QAE5C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAE7D,qDAAqD;QACrD,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,QAAQ,MAAM,EAAE,CAAC,EAAE,CAAC;YACtD,MAAM,IAAI,SAAS,CACjB,qBAAqB,GAAG,kCAAkC,MAAM,GAAG,CACpE,CAAA;QACH,CAAC;QAED,OAAO,QAAQ,CAAA;IACjB,CAAC;CACF;AAnED,4CAmEC;AAED,SAAS,aAAa,CACpB,QAAgD;IAEhD,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBACzB,IAAI,IAAA,sBAAa,EAAC,MAAM,CAAC;oBAAE,OAAO,MAAM,CAAA;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,kCAAkC,CAEzC,CAAa;IAMb,OAAO,CACL,OAAO,CAAC,CAAC,eAAe,KAAK,QAAQ;QACrC,CAAC,CAAC,IAAI,KAAK,2BAA2B;QACtC,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YACnB,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc;YACzB,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,EAAE,cAAc,CAAC,CACvC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"identity-resolver.js","sourceRoot":"","sources":["../src/identity-resolver.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,6 @@
1
+ export * from './atproto-identity-resolver.js';
2
+ export * from './constants.js';
3
+ export * from './identity-resolver-error.js';
1
4
  export * from './identity-resolver.js';
5
+ export * from './util.js';
2
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,8BAA8B,CAAA;AAC5C,cAAc,wBAAwB,CAAA;AACtC,cAAc,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -14,5 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./atproto-identity-resolver.js"), exports);
18
+ __exportStar(require("./constants.js"), exports);
19
+ __exportStar(require("./identity-resolver-error.js"), exports);
17
20
  __exportStar(require("./identity-resolver.js"), exports);
21
+ __exportStar(require("./util.js"), exports);
18
22
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAsC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iEAA8C;AAC9C,iDAA8B;AAC9B,+DAA4C;AAC5C,yDAAsC;AACtC,4CAAyB"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { AtprotoIdentityDidMethods, DidDocument } from '@atproto-labs/did-resolver';
2
+ /**
3
+ * Extract the raw, un-validated, Atproto handle from a DID document.
4
+ */
5
+ export declare function extractAtprotoHandle(document: DidDocument<AtprotoIdentityDidMethods>): string | undefined;
6
+ /**
7
+ * Extracts a validated, normalized Atproto handle from a DID document.
8
+ */
9
+ export declare function extractNormalizedHandle(document: DidDocument<AtprotoIdentityDidMethods>): string | undefined;
10
+ export declare function asNormalizedHandle(input: string): string | undefined;
11
+ export declare function normalizeHandle(handle: string): string;
12
+ export declare function isValidHandle(handle: string): boolean;
13
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,WAAW,EACZ,MAAM,4BAA4B,CAAA;AAEnC;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,WAAW,CAAC,yBAAyB,CAAC,GAC/C,MAAM,GAAG,SAAS,CAUpB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,WAAW,CAAC,yBAAyB,CAAC,GAC/C,MAAM,GAAG,SAAS,CAIpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGpE;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQrD"}
package/dist/util.js ADDED
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractAtprotoHandle = extractAtprotoHandle;
4
+ exports.extractNormalizedHandle = extractNormalizedHandle;
5
+ exports.asNormalizedHandle = asNormalizedHandle;
6
+ exports.normalizeHandle = normalizeHandle;
7
+ exports.isValidHandle = isValidHandle;
8
+ /**
9
+ * Extract the raw, un-validated, Atproto handle from a DID document.
10
+ */
11
+ function extractAtprotoHandle(document) {
12
+ if (document.alsoKnownAs) {
13
+ for (const h of document.alsoKnownAs) {
14
+ if (h.startsWith('at://')) {
15
+ // strip off "at://" prefix
16
+ return h.slice(5);
17
+ }
18
+ }
19
+ }
20
+ return undefined;
21
+ }
22
+ /**
23
+ * Extracts a validated, normalized Atproto handle from a DID document.
24
+ */
25
+ function extractNormalizedHandle(document) {
26
+ const handle = extractAtprotoHandle(document);
27
+ if (!handle)
28
+ return undefined;
29
+ return asNormalizedHandle(handle);
30
+ }
31
+ function asNormalizedHandle(input) {
32
+ const handle = normalizeHandle(input);
33
+ return isValidHandle(handle) ? handle : undefined;
34
+ }
35
+ function normalizeHandle(handle) {
36
+ return handle.toLowerCase();
37
+ }
38
+ function isValidHandle(handle) {
39
+ return (handle.length > 0 &&
40
+ handle.length < 254 &&
41
+ /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(handle));
42
+ }
43
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAQA,oDAYC;AAKD,0DAMC;AAED,gDAGC;AAED,0CAEC;AAED,sCAQC;AA7CD;;GAEG;AACH,SAAgB,oBAAoB,CAClC,QAAgD;IAEhD,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,2BAA2B;gBAC3B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CACrC,QAAgD;IAEhD,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IAC7C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAA;IAC7B,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAA;AACnC,CAAC;AAED,SAAgB,kBAAkB,CAAC,KAAa;IAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IACrC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;AACnD,CAAC;AAED,SAAgB,eAAe,CAAC,MAAc;IAC5C,OAAO,MAAM,CAAC,WAAW,EAAE,CAAA;AAC7B,CAAC;AAED,SAAgB,aAAa,CAAC,MAAc;IAC1C,OAAO,CACL,MAAM,CAAC,MAAM,GAAG,CAAC;QACjB,MAAM,CAAC,MAAM,GAAG,GAAG;QACnB,4FAA4F,CAAC,IAAI,CAC/F,MAAM,CACP,CACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto-labs/identity-resolver",
3
- "version": "0.1.19",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "description": "A library resolving ATPROTO identities",
6
6
  "keywords": [
@@ -26,8 +26,7 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@atproto-labs/did-resolver": "0.2.0",
29
- "@atproto-labs/handle-resolver": "0.2.0",
30
- "@atproto/syntax": "0.4.0"
29
+ "@atproto-labs/handle-resolver": "0.3.0"
31
30
  },
32
31
  "devDependencies": {
33
32
  "typescript": "^5.6.3"
@@ -0,0 +1,126 @@
1
+ import {
2
+ AtprotoDid,
3
+ AtprotoIdentityDidMethods,
4
+ DidDocument,
5
+ DidResolver,
6
+ ResolveDidOptions,
7
+ isAtprotoDid,
8
+ } from '@atproto-labs/did-resolver'
9
+ import {
10
+ HandleResolver,
11
+ ResolveHandleOptions,
12
+ } from '@atproto-labs/handle-resolver'
13
+ import { HANDLE_INVALID } from './constants.js'
14
+ import { IdentityResolverError } from './identity-resolver-error.js'
15
+ import {
16
+ IdentityInfo,
17
+ IdentityResolver,
18
+ ResolveIdentityOptions,
19
+ } from './identity-resolver.js'
20
+ import { asNormalizedHandle, extractNormalizedHandle } from './util.js'
21
+
22
+ // @TODO Move this to its own package as soon as we have a distinct
23
+ // implementation based on XRPC calls to the
24
+ // "com.atproto.identity.resolveIdentity" method.
25
+
26
+ /**
27
+ * Implementation of the official ATPROTO identity resolution strategy.
28
+ * This implementation relies on two primitives:
29
+ * - DID resolution (using the `DidResolver` interface)
30
+ * - Handle resolution (using the `HandleResolver` interface)
31
+ */
32
+ export class AtprotoIdentityResolver implements IdentityResolver {
33
+ constructor(
34
+ protected readonly didResolver: DidResolver<AtprotoIdentityDidMethods>,
35
+ protected readonly handleResolver: HandleResolver,
36
+ ) {}
37
+
38
+ public async resolve(
39
+ input: string,
40
+ options?: ResolveIdentityOptions,
41
+ ): Promise<IdentityInfo> {
42
+ return isAtprotoDid(input)
43
+ ? this.resolveFromDid(input, options)
44
+ : this.resolveFromHandle(input, options)
45
+ }
46
+
47
+ public async resolveFromDid(
48
+ did: AtprotoDid,
49
+ options?: ResolveDidOptions,
50
+ ): Promise<IdentityInfo> {
51
+ const document = await this.getDocumentFromDid(did, options)
52
+
53
+ options?.signal?.throwIfAborted()
54
+
55
+ // We will only return the document's handle alias if it resolves to the
56
+ // same DID as the input.
57
+ const handle = extractNormalizedHandle(document)
58
+ const resolvedDid = handle
59
+ ? await this.handleResolver
60
+ .resolve(handle, options)
61
+ .catch(() => undefined) // Ignore errors (temporarily unavailable)
62
+ : undefined
63
+
64
+ return {
65
+ did: document.id,
66
+ didDoc: document,
67
+ handle: handle && resolvedDid === did ? handle : HANDLE_INVALID,
68
+ }
69
+ }
70
+
71
+ public async resolveFromHandle(
72
+ handle: string,
73
+ options?: ResolveHandleOptions,
74
+ ): Promise<IdentityInfo> {
75
+ const document = await this.getDocumentFromHandle(handle, options)
76
+
77
+ // @NOTE bi-directional resolution enforced in getDocumentFromHandle()
78
+
79
+ return {
80
+ did: document.id,
81
+ didDoc: document,
82
+ handle: extractNormalizedHandle(document) || HANDLE_INVALID,
83
+ }
84
+ }
85
+
86
+ public async getDocumentFromDid(
87
+ did: AtprotoDid,
88
+ options?: ResolveDidOptions,
89
+ ): Promise<DidDocument<AtprotoIdentityDidMethods>> {
90
+ return this.didResolver.resolve(did, options)
91
+ }
92
+
93
+ public async getDocumentFromHandle(
94
+ input: string,
95
+ options?: ResolveHandleOptions,
96
+ ): Promise<DidDocument<AtprotoIdentityDidMethods>> {
97
+ const handle = asNormalizedHandle(input)
98
+ if (!handle) {
99
+ throw new IdentityResolverError(`Invalid handle "${input}" provided.`)
100
+ }
101
+
102
+ const did = await this.handleResolver.resolve(handle, options)
103
+
104
+ if (!did) {
105
+ throw new IdentityResolverError(
106
+ `Handle "${handle}" does not resolve to a DID`,
107
+ )
108
+ }
109
+
110
+ options?.signal?.throwIfAborted()
111
+
112
+ // Note: Not using "return this.resolveDid(did, options)" to make the extra
113
+ // check for the handle in the DID document:
114
+
115
+ const document = await this.didResolver.resolve(did, options)
116
+
117
+ // Enforce bi-directional resolution
118
+ if (handle !== extractNormalizedHandle(document)) {
119
+ throw new IdentityResolverError(
120
+ `Did document for "${did}" does not include the handle "${handle}"`,
121
+ )
122
+ }
123
+
124
+ return document
125
+ }
126
+ }
@@ -0,0 +1 @@
1
+ export const HANDLE_INVALID = 'handle.invalid'
@@ -0,0 +1,3 @@
1
+ export class IdentityResolverError extends Error {
2
+ name = 'IdentityResolverError'
3
+ }
@@ -1,124 +1,33 @@
1
- import { isValidHandle, normalizeAndEnsureValidHandle } from '@atproto/syntax'
2
1
  import {
3
- Did,
2
+ AtprotoDid,
3
+ AtprotoIdentityDidMethods,
4
4
  DidDocument,
5
- DidResolver,
6
- DidService,
7
- ResolveDidOptions,
8
5
  } from '@atproto-labs/did-resolver'
9
- import {
10
- AtprotoIdentityDidMethods,
11
- HandleResolver,
12
- ResolveHandleOptions,
13
- ResolvedHandle,
14
- isResolvedHandle,
15
- } from '@atproto-labs/handle-resolver'
16
-
17
- export type ResolvedIdentity = {
18
- did: NonNullable<ResolvedHandle>
19
- pds: URL
20
- handle?: string
21
- }
22
-
23
- export type ResolveIdentityOptions = ResolveDidOptions & ResolveHandleOptions
24
-
25
- export class IdentityResolver {
26
- constructor(
27
- readonly didResolver: DidResolver<AtprotoIdentityDidMethods>,
28
- readonly handleResolver: HandleResolver,
29
- ) {}
30
-
31
- public async resolve(
32
- input: string,
33
- options?: ResolveIdentityOptions,
34
- ): Promise<ResolvedIdentity> {
35
- const document = isResolvedHandle(input)
36
- ? await this.getDocumentFromDid(input, options)
37
- : await this.getDocumentFromHandle(input, options)
38
-
39
- const service = document.service?.find(
40
- isAtprotoPersonalDataServerService<AtprotoIdentityDidMethods>,
41
- document,
42
- )
6
+ import { HANDLE_INVALID } from './constants'
43
7
 
44
- if (!service) {
45
- throw new TypeError(
46
- `No valid "AtprotoPersonalDataServer" service found in "${document.id}" DID document`,
47
- )
48
- }
8
+ // Consistent with `com.atproto.identity.defs#identityInfo` returned by
9
+ // `com.atproto.identity.resolveIdentity` endpoint.
10
+ export type IdentityInfo = {
11
+ did: AtprotoDid
49
12
 
50
- return {
51
- did: document.id,
52
- pds: new URL(service.serviceEndpoint),
53
- handle: extractHandle(document),
54
- }
55
- }
13
+ didDoc: DidDocument<AtprotoIdentityDidMethods>
56
14
 
57
- public async getDocumentFromDid(
58
- did: NonNullable<ResolvedHandle>,
59
- options?: ResolveDidOptions,
60
- ): Promise<DidDocument<AtprotoIdentityDidMethods>> {
61
- return this.didResolver.resolve(did, options)
62
- }
63
-
64
- public async getDocumentFromHandle(
65
- input: string,
66
- options?: ResolveHandleOptions,
67
- ): Promise<DidDocument<AtprotoIdentityDidMethods>> {
68
- const handle = normalizeAndEnsureValidHandle(input)
69
-
70
- const did = await this.handleResolver.resolve(handle, options)
71
-
72
- if (!did) {
73
- throw new TypeError(`Handle "${handle}" does not resolve to a DID`)
74
- }
75
-
76
- options?.signal?.throwIfAborted()
77
-
78
- // Note: Not using "return this.resolveDid(did, options)" to make the extra
79
- // check for the handle in the DID document:
80
-
81
- const document = await this.didResolver.resolve(did, options)
82
-
83
- // Ensure that the handle is included in the document
84
- if (!document.alsoKnownAs?.includes(`at://${handle}`)) {
85
- throw new TypeError(
86
- `Did document for "${did}" does not include the handle "${handle}"`,
87
- )
88
- }
89
-
90
- return document
91
- }
15
+ /**
16
+ * Will be 'handle.invalid' if the handle does not resolve to the
17
+ * same DID as the input, or if the handle is not present in the DID
18
+ * document.
19
+ */
20
+ handle: typeof HANDLE_INVALID | string
92
21
  }
93
22
 
94
- function extractHandle(
95
- document: DidDocument<AtprotoIdentityDidMethods>,
96
- ): string | undefined {
97
- if (document.alsoKnownAs) {
98
- for (const h of document.alsoKnownAs) {
99
- if (h.startsWith('at://')) {
100
- const handle = h.slice(5)
101
- if (isValidHandle(handle)) return handle
102
- }
103
- }
104
- }
105
-
106
- return undefined
23
+ export type ResolveIdentityOptions = {
24
+ signal?: AbortSignal
25
+ noCache?: boolean
107
26
  }
108
27
 
109
- function isAtprotoPersonalDataServerService<M extends string>(
110
- this: DidDocument<M>,
111
- s: DidService,
112
- ): s is {
113
- id: '#atproto_pds' | `${Did<M>}#atproto_pds`
114
- type: 'AtprotoPersonalDataServer'
115
- serviceEndpoint: string
116
- } {
117
- return (
118
- typeof s.serviceEndpoint === 'string' &&
119
- s.type === 'AtprotoPersonalDataServer' &&
120
- (s.id.startsWith('#')
121
- ? s.id === '#atproto_pds'
122
- : s.id === `${this.id}#atproto_pds`)
123
- )
28
+ export interface IdentityResolver {
29
+ resolve(
30
+ identifier: string,
31
+ options?: ResolveIdentityOptions,
32
+ ): Promise<IdentityInfo>
124
33
  }
package/src/index.ts CHANGED
@@ -1 +1,5 @@
1
+ export * from './atproto-identity-resolver.js'
2
+ export * from './constants.js'
3
+ export * from './identity-resolver-error.js'
1
4
  export * from './identity-resolver.js'
5
+ export * from './util.js'
package/src/util.ts ADDED
@@ -0,0 +1,51 @@
1
+ import {
2
+ AtprotoIdentityDidMethods,
3
+ DidDocument,
4
+ } from '@atproto-labs/did-resolver'
5
+
6
+ /**
7
+ * Extract the raw, un-validated, Atproto handle from a DID document.
8
+ */
9
+ export function extractAtprotoHandle(
10
+ document: DidDocument<AtprotoIdentityDidMethods>,
11
+ ): string | undefined {
12
+ if (document.alsoKnownAs) {
13
+ for (const h of document.alsoKnownAs) {
14
+ if (h.startsWith('at://')) {
15
+ // strip off "at://" prefix
16
+ return h.slice(5)
17
+ }
18
+ }
19
+ }
20
+ return undefined
21
+ }
22
+
23
+ /**
24
+ * Extracts a validated, normalized Atproto handle from a DID document.
25
+ */
26
+ export function extractNormalizedHandle(
27
+ document: DidDocument<AtprotoIdentityDidMethods>,
28
+ ): string | undefined {
29
+ const handle = extractAtprotoHandle(document)
30
+ if (!handle) return undefined
31
+ return asNormalizedHandle(handle)
32
+ }
33
+
34
+ export function asNormalizedHandle(input: string): string | undefined {
35
+ const handle = normalizeHandle(input)
36
+ return isValidHandle(handle) ? handle : undefined
37
+ }
38
+
39
+ export function normalizeHandle(handle: string): string {
40
+ return handle.toLowerCase()
41
+ }
42
+
43
+ export function isValidHandle(handle: string): boolean {
44
+ return (
45
+ handle.length > 0 &&
46
+ handle.length < 254 &&
47
+ /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/.test(
48
+ handle,
49
+ )
50
+ )
51
+ }
@@ -1 +1 @@
1
- {"root":["./src/identity-resolver.ts","./src/index.ts"],"version":"5.8.2"}
1
+ {"root":["./src/atproto-identity-resolver.ts","./src/constants.ts","./src/identity-resolver-error.ts","./src/identity-resolver.ts","./src/index.ts","./src/util.ts"],"version":"5.8.2"}