@atproto/lexicon-resolver 0.1.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE.txt +7 -0
  3. package/README.md +79 -0
  4. package/dist/client/index.d.ts +28 -0
  5. package/dist/client/index.d.ts.map +1 -0
  6. package/dist/client/index.js +118 -0
  7. package/dist/client/index.js.map +1 -0
  8. package/dist/client/lexicons.d.ts +105 -0
  9. package/dist/client/lexicons.d.ts.map +1 -0
  10. package/dist/client/lexicons.js +75 -0
  11. package/dist/client/lexicons.js.map +1 -0
  12. package/dist/client/types/com/atproto/sync/getRecord.d.ts +38 -0
  13. package/dist/client/types/com/atproto/sync/getRecord.d.ts.map +1 -0
  14. package/dist/client/types/com/atproto/sync/getRecord.js +58 -0
  15. package/dist/client/types/com/atproto/sync/getRecord.js.map +1 -0
  16. package/dist/client/util.d.ts +37 -0
  17. package/dist/client/util.d.ts.map +1 -0
  18. package/dist/client/util.js +38 -0
  19. package/dist/client/util.js.map +1 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +19 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/lexicon.d.ts +43 -0
  25. package/dist/lexicon.d.ts.map +1 -0
  26. package/dist/lexicon.js +98 -0
  27. package/dist/lexicon.js.map +1 -0
  28. package/dist/record.d.ts +37 -0
  29. package/dist/record.d.ts.map +1 -0
  30. package/dist/record.js +100 -0
  31. package/dist/record.js.map +1 -0
  32. package/dist/util.d.ts +2 -0
  33. package/dist/util.d.ts.map +1 -0
  34. package/dist/util.js +14 -0
  35. package/dist/util.js.map +1 -0
  36. package/jest.config.js +7 -0
  37. package/package.json +46 -0
  38. package/src/client/index.ts +67 -0
  39. package/src/client/lexicons.ts +98 -0
  40. package/src/client/types/com/atproto/sync/getRecord.ts +78 -0
  41. package/src/client/util.ts +82 -0
  42. package/src/index.ts +2 -0
  43. package/src/lexicon.ts +147 -0
  44. package/src/record.ts +156 -0
  45. package/src/util.ts +10 -0
  46. package/tests/lexicon.test.ts +266 -0
  47. package/tests/record.test.ts +98 -0
  48. package/tsconfig.build.json +9 -0
  49. package/tsconfig.build.tsbuildinfo +1 -0
  50. package/tsconfig.json +7 -0
  51. package/tsconfig.tests.json +8 -0
  52. package/tsconfig.tests.tsbuildinfo +1 -0
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./record.js"), exports);
18
+ __exportStar(require("./lexicon.js"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,+CAA4B"}
@@ -0,0 +1,43 @@
1
+ import { CID } from 'multiformats/cid';
2
+ import { LexiconDoc } from '@atproto/lexicon';
3
+ import { Commit } from '@atproto/repo';
4
+ import { AtUri, NSID } from '@atproto/syntax';
5
+ import { BuildRecordResolverOptions, ResolveRecordOptions } from './record.js';
6
+ export declare const LEXICON_SCHEMA_NSID = "com.atproto.lexicon.schema";
7
+ /**
8
+ * Resolve Lexicon from an NSID
9
+ */
10
+ export type LexiconResolver = (nsid: NSID | string) => Promise<LexiconResolution>;
11
+ /**
12
+ * Resolve Lexicon from an NSID using Lexicon DID authority and record resolution
13
+ */
14
+ export type AtprotoLexiconResolver = (nsid: NSID | string, options?: ResolveLexiconOptions) => Promise<LexiconResolution>;
15
+ export type BuildLexiconResolverOptions = BuildRecordResolverOptions;
16
+ export type ResolveLexiconOptions = ResolveRecordOptions & {
17
+ didAuthority?: string;
18
+ };
19
+ export type LexiconResolution = {
20
+ commit: Commit;
21
+ uri: AtUri;
22
+ cid: CID;
23
+ nsid: NSID;
24
+ lexicon: LexiconDoc & LexiconSchemaRecord;
25
+ };
26
+ /**
27
+ * Build a Lexicon resolver function.
28
+ */
29
+ export declare function buildLexiconResolver(options?: BuildLexiconResolverOptions): AtprotoLexiconResolver;
30
+ export declare const resolveLexicon: AtprotoLexiconResolver;
31
+ /**
32
+ * Resolve the DID authority for a Lexicon from the network using DNS, based on its NSID.
33
+ * @param nsidStr NSID or string representing one for which to lookup its Lexicon DID authority.
34
+ */
35
+ export declare function resolveLexiconDidAuthority(nsidStr: NSID | string): Promise<string | undefined>;
36
+ export declare class LexiconResolutionError extends Error {
37
+ constructor(message?: string, options?: ErrorOptions);
38
+ }
39
+ type LexiconSchemaRecord = {
40
+ $type: typeof LEXICON_SCHEMA_NSID;
41
+ };
42
+ export {};
43
+ //# sourceMappingURL=lexicon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexicon.d.ts","sourceRoot":"","sources":["../src/lexicon.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAkB,MAAM,iBAAiB,CAAA;AAC7D,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EAErB,MAAM,aAAa,CAAA;AAKpB,eAAO,MAAM,mBAAmB,+BAA+B,CAAA;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAC5B,IAAI,EAAE,IAAI,GAAG,MAAM,KAChB,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE/B;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,CACnC,IAAI,EAAE,IAAI,GAAG,MAAM,EACnB,OAAO,CAAC,EAAE,qBAAqB,KAC5B,OAAO,CAAC,iBAAiB,CAAC,CAAA;AAE/B,MAAM,MAAM,2BAA2B,GAAG,0BAA0B,CAAA;AAEpE,MAAM,MAAM,qBAAqB,GAAG,oBAAoB,GAAG;IACzD,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,KAAK,CAAA;IACV,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,EAAE,UAAU,GAAG,mBAAmB,CAAA;CAC1C,CAAA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC,GACxC,sBAAsB,CAoCxB;AAED,eAAO,MAAM,cAAc,wBAAyB,CAAA;AAEpD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,IAAI,GAAG,MAAM,GACrB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK7B;AAED,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIrD;AAmCD,KAAK,mBAAmB,GAAG;IAAE,KAAK,EAAE,OAAO,mBAAmB,CAAA;CAAE,CAAA"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LexiconResolutionError = exports.resolveLexicon = exports.LEXICON_SCHEMA_NSID = void 0;
7
+ exports.buildLexiconResolver = buildLexiconResolver;
8
+ exports.resolveLexiconDidAuthority = resolveLexiconDidAuthority;
9
+ const promises_1 = __importDefault(require("node:dns/promises"));
10
+ const lexicon_1 = require("@atproto/lexicon");
11
+ const syntax_1 = require("@atproto/syntax");
12
+ const record_js_1 = require("./record.js");
13
+ const util_js_1 = require("./util.js");
14
+ const DNS_SUBDOMAIN = '_lexicon';
15
+ const DNS_PREFIX = 'did=';
16
+ exports.LEXICON_SCHEMA_NSID = 'com.atproto.lexicon.schema';
17
+ /**
18
+ * Build a Lexicon resolver function.
19
+ */
20
+ function buildLexiconResolver(options = {}) {
21
+ const resolveRecord = (0, record_js_1.buildRecordResolver)(options);
22
+ return async function (nsidStr, opts = {}) {
23
+ const nsid = typeof nsidStr === 'string' ? syntax_1.NSID.parse(nsidStr) : nsidStr;
24
+ const didAuthority = await getDidAuthority(nsid, opts);
25
+ const verified = await resolveRecord(syntax_1.AtUri.make(didAuthority, exports.LEXICON_SCHEMA_NSID, nsid.toString()), { forceRefresh: opts.forceRefresh }).catch((err) => {
26
+ throw new LexiconResolutionError('Could not resolve Lexicon schema record', { cause: err });
27
+ });
28
+ let lexicon;
29
+ try {
30
+ lexicon = (0, lexicon_1.parseLexiconDoc)(verified.record);
31
+ }
32
+ catch (err) {
33
+ throw new LexiconResolutionError('Invalid Lexicon document', {
34
+ cause: err,
35
+ });
36
+ }
37
+ if (!isLexiconSchemaRecord(lexicon)) {
38
+ throw new LexiconResolutionError('Invalid Lexicon schema record');
39
+ }
40
+ if (lexicon.id !== nsid.toString()) {
41
+ throw new LexiconResolutionError(`Lexicon schema record id does not match NSID: ${lexicon.id}`);
42
+ }
43
+ const { uri, cid, commit } = verified;
44
+ return { commit, uri, cid, nsid, lexicon };
45
+ };
46
+ }
47
+ exports.resolveLexicon = buildLexiconResolver();
48
+ /**
49
+ * Resolve the DID authority for a Lexicon from the network using DNS, based on its NSID.
50
+ * @param nsidStr NSID or string representing one for which to lookup its Lexicon DID authority.
51
+ */
52
+ async function resolveLexiconDidAuthority(nsidStr) {
53
+ const nsid = typeof nsidStr === 'string' ? syntax_1.NSID.parse(nsidStr) : nsidStr;
54
+ const did = await resolveDns(nsid.authority);
55
+ if (did == null || !(0, util_js_1.isValidDid)(did))
56
+ return;
57
+ return did;
58
+ }
59
+ class LexiconResolutionError extends Error {
60
+ constructor(message, options) {
61
+ super(message, options);
62
+ this.name = 'LexiconResolutionError';
63
+ }
64
+ }
65
+ exports.LexiconResolutionError = LexiconResolutionError;
66
+ async function getDidAuthority(nsid, options) {
67
+ if (options.didAuthority) {
68
+ (0, syntax_1.ensureValidDid)(options.didAuthority);
69
+ return options.didAuthority;
70
+ }
71
+ const did = await resolveLexiconDidAuthority(nsid);
72
+ if (!did) {
73
+ throw new LexiconResolutionError(`Could not resolve a DID authority for NSID: ${nsid}`);
74
+ }
75
+ return did;
76
+ }
77
+ async function resolveDns(authority) {
78
+ let chunkedResults;
79
+ try {
80
+ chunkedResults = await promises_1.default.resolveTxt(`${DNS_SUBDOMAIN}.${authority}`);
81
+ }
82
+ catch (err) {
83
+ return undefined;
84
+ }
85
+ return parseDnsResult(chunkedResults);
86
+ }
87
+ function parseDnsResult(chunkedResults) {
88
+ const results = chunkedResults.map((chunks) => chunks.join(''));
89
+ const found = results.filter((i) => i.startsWith(DNS_PREFIX));
90
+ if (found.length !== 1) {
91
+ return undefined;
92
+ }
93
+ return found[0].slice(DNS_PREFIX.length);
94
+ }
95
+ function isLexiconSchemaRecord(v) {
96
+ return v?.['$type'] === exports.LEXICON_SCHEMA_NSID;
97
+ }
98
+ //# sourceMappingURL=lexicon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexicon.js","sourceRoot":"","sources":["../src/lexicon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import { CID } from 'multiformats/cid';
2
+ import { IdResolver } from '@atproto/identity';
3
+ import { RepoRecord } from '@atproto/lexicon';
4
+ import { Commit } from '@atproto/repo';
5
+ import { AtUri } from '@atproto/syntax';
6
+ import { BuildFetchHandlerOptions, FetchHandler } from '@atproto/xrpc';
7
+ /**
8
+ * Resolve a record from the network.
9
+ */
10
+ export type RecordResolver = (uriStr: AtUri | string) => Promise<RecordResolution>;
11
+ /**
12
+ * Resolve a record from the network, verifying its authenticity.
13
+ */
14
+ export type AtprotoRecordResolver = (uriStr: AtUri | string, options?: ResolveRecordOptions) => Promise<RecordResolution>;
15
+ export type BuildRecordResolverOptions = {
16
+ idResolver?: IdResolver;
17
+ rpc?: Partial<BuildFetchHandlerOptions> | FetchHandler;
18
+ };
19
+ export type ResolveRecordOptions = {
20
+ forceRefresh?: boolean;
21
+ };
22
+ export type RecordResolution = {
23
+ commit: Commit;
24
+ uri: AtUri;
25
+ cid: CID;
26
+ record: RepoRecord;
27
+ };
28
+ /**
29
+ * Build a record resolver function.
30
+ */
31
+ export declare function buildRecordResolver(options?: BuildRecordResolverOptions): AtprotoRecordResolver;
32
+ export declare const resolveRecord: AtprotoRecordResolver;
33
+ export declare const safeFetch: (input: string | URL | Request, init?: RequestInit | undefined) => Promise<Response>;
34
+ export declare class RecordResolutionError extends Error {
35
+ constructor(message?: string, options?: ErrorOptions);
36
+ }
37
+ //# sourceMappingURL=record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EACL,MAAM,EAMP,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,KAAK,EAAkB,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAKtE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,KAAK,GAAG,MAAM,KACnB,OAAO,CAAC,gBAAgB,CAAC,CAAA;AAE9B;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,MAAM,EAAE,KAAK,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,oBAAoB,KAC3B,OAAO,CAAC,gBAAgB,CAAC,CAAA;AAE9B,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,GAAG,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,YAAY,CAAA;CACvD,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,KAAK,CAAA;IACV,GAAG,EAAE,GAAG,CAAA;IACR,MAAM,EAAE,UAAU,CAAA;CACnB,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,qBAAqB,CAyCvB;AAED,eAAO,MAAM,aAAa,uBAAwB,CAAA;AAElD,eAAO,MAAM,SAAS,sFAIpB,CAAA;AAEF,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIrD"}
package/dist/record.js ADDED
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RecordResolutionError = exports.safeFetch = exports.resolveRecord = void 0;
4
+ exports.buildRecordResolver = buildRecordResolver;
5
+ const identity_1 = require("@atproto/identity");
6
+ const repo_1 = require("@atproto/repo");
7
+ const syntax_1 = require("@atproto/syntax");
8
+ const fetch_node_1 = require("@atproto-labs/fetch-node");
9
+ const index_js_1 = require("./client/index.js");
10
+ const util_js_1 = require("./util.js");
11
+ /**
12
+ * Build a record resolver function.
13
+ */
14
+ function buildRecordResolver(options = {}) {
15
+ const { idResolver = new identity_1.IdResolver(), rpc } = options;
16
+ return async function resolveRecord(uriStr, opts = {}) {
17
+ const uri = typeof uriStr === 'string' ? new syntax_1.AtUri(uriStr) : uriStr;
18
+ const did = await getDidFromUri(uri, { idResolver });
19
+ const identity = await idResolver.did
20
+ .resolveAtprotoData(did, opts.forceRefresh)
21
+ .catch((err) => {
22
+ throw new RecordResolutionError('Could not resolve DID identity data', {
23
+ cause: err,
24
+ });
25
+ });
26
+ const client = new index_js_1.AtpBaseClient(typeof rpc === 'function'
27
+ ? rpc
28
+ : {
29
+ ...rpc,
30
+ service: rpc?.service ?? identity.pds,
31
+ fetch: rpc?.fetch ?? exports.safeFetch,
32
+ });
33
+ const { data: proofBytes } = await client.com.atproto.sync
34
+ .getRecord({
35
+ did,
36
+ collection: uri.collection,
37
+ rkey: uri.rkey,
38
+ })
39
+ .catch((err) => {
40
+ throw new RecordResolutionError('Could not fetch record proof', {
41
+ cause: err,
42
+ });
43
+ });
44
+ const verified = await verifyRecordProof(proofBytes, {
45
+ uri: syntax_1.AtUri.make(did, uri.collection, uri.rkey),
46
+ signingKey: identity.signingKey,
47
+ });
48
+ return verified;
49
+ };
50
+ }
51
+ exports.resolveRecord = buildRecordResolver();
52
+ exports.safeFetch = (0, fetch_node_1.safeFetchWrap)({
53
+ allowIpHost: false,
54
+ allowImplicitRedirect: true,
55
+ responseMaxSize: (1024 + 10) * 1024, // 1MB + 10kB, just a bit larger than max record size
56
+ });
57
+ class RecordResolutionError extends Error {
58
+ constructor(message, options) {
59
+ super(message, options);
60
+ this.name = 'RecordResolutionError';
61
+ }
62
+ }
63
+ exports.RecordResolutionError = RecordResolutionError;
64
+ async function getDidFromUri(uri, { idResolver }) {
65
+ if (uri.host.startsWith('did:')) {
66
+ (0, syntax_1.ensureValidDid)(uri.host);
67
+ return uri.host;
68
+ }
69
+ const resolved = await idResolver.handle.resolve(uri.host);
70
+ if (!resolved || !(0, util_js_1.isValidDid)(resolved)) {
71
+ throw new RecordResolutionError('Could not resolve handle found in AT-URI');
72
+ }
73
+ return resolved;
74
+ }
75
+ async function verifyRecordProof(proofBytes, { uri, signingKey }) {
76
+ const { root, blocks } = await (0, repo_1.readCarWithRoot)(proofBytes).catch((err) => {
77
+ throw new RecordResolutionError('Malformed record proof', { cause: err });
78
+ });
79
+ const blockstore = new repo_1.MemoryBlockstore(blocks);
80
+ const commit = await blockstore.readObj(root, repo_1.def.commit).catch((err) => {
81
+ throw new RecordResolutionError('Invalid commit in record proof', {
82
+ cause: err,
83
+ });
84
+ });
85
+ if (commit.did !== uri.host) {
86
+ throw new RecordResolutionError(`Invalid repo did: ${commit.did}`);
87
+ }
88
+ const validSig = await (0, repo_1.verifyCommitSig)(commit, signingKey);
89
+ if (!validSig) {
90
+ throw new RecordResolutionError(`Invalid signature on commit: ${root.toString()}`);
91
+ }
92
+ const mst = repo_1.MST.load(blockstore, commit.data);
93
+ const cid = await mst.get(`${uri.collection}/${uri.rkey}`);
94
+ if (!cid) {
95
+ throw new RecordResolutionError('Record not found in proof');
96
+ }
97
+ const record = await blockstore.readRecord(cid);
98
+ return { commit, uri, cid, record };
99
+ }
100
+ //# sourceMappingURL=record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.js","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"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"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function isValidDid(did: string): boolean;
2
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,WAOrC"}
package/dist/util.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isValidDid = isValidDid;
4
+ const syntax_1 = require("@atproto/syntax");
5
+ function isValidDid(did) {
6
+ try {
7
+ (0, syntax_1.ensureValidDid)(did);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAEA,gCAOC;AATD,4CAAgD;AAEhD,SAAgB,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,IAAA,uBAAc,EAAC,GAAG,CAAC,CAAA;QACnB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
package/jest.config.js ADDED
@@ -0,0 +1,7 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ displayName: 'Lexicon Resolver',
4
+ transform: { '^.+\\.(t|j)s$': '@swc/jest' },
5
+ setupFiles: ['<rootDir>/../../jest.setup.ts'],
6
+ moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] },
7
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@atproto/lexicon-resolver",
3
+ "version": "0.1.0",
4
+ "type": "commonjs",
5
+ "license": "MIT",
6
+ "description": "ATProto Lexicon resolution",
7
+ "keywords": [
8
+ "atproto",
9
+ "lexicon"
10
+ ],
11
+ "homepage": "https://atproto.com",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/bluesky-social/atproto",
15
+ "directory": "packages/lexicon-resolver"
16
+ },
17
+ "main": "dist/index.js",
18
+ "types": "dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "default": "./dist/index.js"
23
+ }
24
+ },
25
+ "dependencies": {
26
+ "multiformats": "^9.9.0",
27
+ "@atproto-labs/fetch-node": "^0.1.9",
28
+ "@atproto/identity": "^0.4.8",
29
+ "@atproto/lexicon": "^0.4.13",
30
+ "@atproto/repo": "^0.8.6",
31
+ "@atproto/syntax": "^0.4.0",
32
+ "@atproto/xrpc": "^0.7.2"
33
+ },
34
+ "devDependencies": {
35
+ "jest": "^28.1.2",
36
+ "typescript": "^5.6.3",
37
+ "@atproto/common": "^0.4.11",
38
+ "@atproto/lex-cli": "^0.9.2",
39
+ "@atproto/dev-env": "^0.3.165"
40
+ },
41
+ "scripts": {
42
+ "test": "jest",
43
+ "build": "tsc --build tsconfig.json",
44
+ "codegen": "lex gen-api --yes ./src/client ../../lexicons/com/atproto/sync/getRecord.json"
45
+ }
46
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import {
5
+ XrpcClient,
6
+ type FetchHandler,
7
+ type FetchHandlerOptions,
8
+ } from '@atproto/xrpc'
9
+ import { schemas } from './lexicons.js'
10
+ import { CID } from 'multiformats/cid'
11
+ import { type OmitKey, type Un$Typed } from './util.js'
12
+ import * as ComAtprotoSyncGetRecord from './types/com/atproto/sync/getRecord.js'
13
+
14
+ export * as ComAtprotoSyncGetRecord from './types/com/atproto/sync/getRecord.js'
15
+
16
+ export class AtpBaseClient extends XrpcClient {
17
+ com: ComNS
18
+
19
+ constructor(options: FetchHandler | FetchHandlerOptions) {
20
+ super(options, schemas)
21
+ this.com = new ComNS(this)
22
+ }
23
+
24
+ /** @deprecated use `this` instead */
25
+ get xrpc(): XrpcClient {
26
+ return this
27
+ }
28
+ }
29
+
30
+ export class ComNS {
31
+ _client: XrpcClient
32
+ atproto: ComAtprotoNS
33
+
34
+ constructor(client: XrpcClient) {
35
+ this._client = client
36
+ this.atproto = new ComAtprotoNS(client)
37
+ }
38
+ }
39
+
40
+ export class ComAtprotoNS {
41
+ _client: XrpcClient
42
+ sync: ComAtprotoSyncNS
43
+
44
+ constructor(client: XrpcClient) {
45
+ this._client = client
46
+ this.sync = new ComAtprotoSyncNS(client)
47
+ }
48
+ }
49
+
50
+ export class ComAtprotoSyncNS {
51
+ _client: XrpcClient
52
+
53
+ constructor(client: XrpcClient) {
54
+ this._client = client
55
+ }
56
+
57
+ getRecord(
58
+ params?: ComAtprotoSyncGetRecord.QueryParams,
59
+ opts?: ComAtprotoSyncGetRecord.CallOptions,
60
+ ): Promise<ComAtprotoSyncGetRecord.Response> {
61
+ return this._client
62
+ .call('com.atproto.sync.getRecord', params, undefined, opts)
63
+ .catch((e) => {
64
+ throw ComAtprotoSyncGetRecord.toKnownErr(e)
65
+ })
66
+ }
67
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import {
5
+ type LexiconDoc,
6
+ Lexicons,
7
+ ValidationError,
8
+ type ValidationResult,
9
+ } from '@atproto/lexicon'
10
+ import { type $Typed, is$typed, maybe$typed } from './util.js'
11
+
12
+ export const schemaDict = {
13
+ ComAtprotoSyncGetRecord: {
14
+ lexicon: 1,
15
+ id: 'com.atproto.sync.getRecord',
16
+ defs: {
17
+ main: {
18
+ type: 'query',
19
+ description:
20
+ 'Get data blocks needed to prove the existence or non-existence of record in the current version of repo. Does not require auth.',
21
+ parameters: {
22
+ type: 'params',
23
+ required: ['did', 'collection', 'rkey'],
24
+ properties: {
25
+ did: {
26
+ type: 'string',
27
+ format: 'did',
28
+ description: 'The DID of the repo.',
29
+ },
30
+ collection: {
31
+ type: 'string',
32
+ format: 'nsid',
33
+ },
34
+ rkey: {
35
+ type: 'string',
36
+ description: 'Record Key',
37
+ format: 'record-key',
38
+ },
39
+ },
40
+ },
41
+ output: {
42
+ encoding: 'application/vnd.ipld.car',
43
+ },
44
+ errors: [
45
+ {
46
+ name: 'RecordNotFound',
47
+ },
48
+ {
49
+ name: 'RepoNotFound',
50
+ },
51
+ {
52
+ name: 'RepoTakendown',
53
+ },
54
+ {
55
+ name: 'RepoSuspended',
56
+ },
57
+ {
58
+ name: 'RepoDeactivated',
59
+ },
60
+ ],
61
+ },
62
+ },
63
+ },
64
+ } as const satisfies Record<string, LexiconDoc>
65
+ export const schemas = Object.values(schemaDict) satisfies LexiconDoc[]
66
+ export const lexicons: Lexicons = new Lexicons(schemas)
67
+
68
+ export function validate<T extends { $type: string }>(
69
+ v: unknown,
70
+ id: string,
71
+ hash: string,
72
+ requiredType: true,
73
+ ): ValidationResult<T>
74
+ export function validate<T extends { $type?: string }>(
75
+ v: unknown,
76
+ id: string,
77
+ hash: string,
78
+ requiredType?: false,
79
+ ): ValidationResult<T>
80
+ export function validate(
81
+ v: unknown,
82
+ id: string,
83
+ hash: string,
84
+ requiredType?: boolean,
85
+ ): ValidationResult {
86
+ return (requiredType ? is$typed : maybe$typed)(v, id, hash)
87
+ ? lexicons.validate(`${id}#${hash}`, v)
88
+ : {
89
+ success: false,
90
+ error: new ValidationError(
91
+ `Must be an object with "${hash === 'main' ? id : `${id}#${hash}`}" $type property`,
92
+ ),
93
+ }
94
+ }
95
+
96
+ export const ids = {
97
+ ComAtprotoSyncGetRecord: 'com.atproto.sync.getRecord',
98
+ } as const
@@ -0,0 +1,78 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import { HeadersMap, XRPCError } from '@atproto/xrpc'
5
+ import { type ValidationResult, BlobRef } from '@atproto/lexicon'
6
+ import { CID } from 'multiformats/cid'
7
+ import { validate as _validate } from '../../../../lexicons'
8
+ import {
9
+ type $Typed,
10
+ is$typed as _is$typed,
11
+ type OmitKey,
12
+ } from '../../../../util'
13
+
14
+ const is$typed = _is$typed,
15
+ validate = _validate
16
+ const id = 'com.atproto.sync.getRecord'
17
+
18
+ export type QueryParams = {
19
+ /** The DID of the repo. */
20
+ did: string
21
+ collection: string
22
+ /** Record Key */
23
+ rkey: string
24
+ }
25
+ export type InputSchema = undefined
26
+
27
+ export interface CallOptions {
28
+ signal?: AbortSignal
29
+ headers?: HeadersMap
30
+ }
31
+
32
+ export interface Response {
33
+ success: boolean
34
+ headers: HeadersMap
35
+ data: Uint8Array
36
+ }
37
+
38
+ export class RecordNotFoundError extends XRPCError {
39
+ constructor(src: XRPCError) {
40
+ super(src.status, src.error, src.message, src.headers, { cause: src })
41
+ }
42
+ }
43
+
44
+ export class RepoNotFoundError extends XRPCError {
45
+ constructor(src: XRPCError) {
46
+ super(src.status, src.error, src.message, src.headers, { cause: src })
47
+ }
48
+ }
49
+
50
+ export class RepoTakendownError extends XRPCError {
51
+ constructor(src: XRPCError) {
52
+ super(src.status, src.error, src.message, src.headers, { cause: src })
53
+ }
54
+ }
55
+
56
+ export class RepoSuspendedError extends XRPCError {
57
+ constructor(src: XRPCError) {
58
+ super(src.status, src.error, src.message, src.headers, { cause: src })
59
+ }
60
+ }
61
+
62
+ export class RepoDeactivatedError extends XRPCError {
63
+ constructor(src: XRPCError) {
64
+ super(src.status, src.error, src.message, src.headers, { cause: src })
65
+ }
66
+ }
67
+
68
+ export function toKnownErr(e: any) {
69
+ if (e instanceof XRPCError) {
70
+ if (e.error === 'RecordNotFound') return new RecordNotFoundError(e)
71
+ if (e.error === 'RepoNotFound') return new RepoNotFoundError(e)
72
+ if (e.error === 'RepoTakendown') return new RepoTakendownError(e)
73
+ if (e.error === 'RepoSuspended') return new RepoSuspendedError(e)
74
+ if (e.error === 'RepoDeactivated') return new RepoDeactivatedError(e)
75
+ }
76
+
77
+ return e
78
+ }