@atproto/lex-client 0.0.22 → 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 (67) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/agent.js +2 -6
  3. package/dist/agent.js.map +1 -1
  4. package/dist/client.js +26 -39
  5. package/dist/client.js.map +1 -1
  6. package/dist/errors.js +32 -47
  7. package/dist/errors.js.map +1 -1
  8. package/dist/index.js +6 -9
  9. package/dist/index.js.map +1 -1
  10. package/dist/lexicons/com/atproto/repo/createRecord.defs.js +23 -27
  11. package/dist/lexicons/com/atproto/repo/createRecord.defs.js.map +1 -1
  12. package/dist/lexicons/com/atproto/repo/createRecord.js +2 -6
  13. package/dist/lexicons/com/atproto/repo/createRecord.js.map +1 -1
  14. package/dist/lexicons/com/atproto/repo/defs.defs.js +7 -10
  15. package/dist/lexicons/com/atproto/repo/defs.defs.js.map +1 -1
  16. package/dist/lexicons/com/atproto/repo/defs.js +2 -6
  17. package/dist/lexicons/com/atproto/repo/defs.js.map +1 -1
  18. package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js +18 -22
  19. package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js.map +1 -1
  20. package/dist/lexicons/com/atproto/repo/deleteRecord.js +2 -6
  21. package/dist/lexicons/com/atproto/repo/deleteRecord.js.map +1 -1
  22. package/dist/lexicons/com/atproto/repo/getRecord.defs.js +14 -17
  23. package/dist/lexicons/com/atproto/repo/getRecord.defs.js.map +1 -1
  24. package/dist/lexicons/com/atproto/repo/getRecord.js +2 -6
  25. package/dist/lexicons/com/atproto/repo/getRecord.js.map +1 -1
  26. package/dist/lexicons/com/atproto/repo/listRecords.defs.js +23 -26
  27. package/dist/lexicons/com/atproto/repo/listRecords.defs.js.map +1 -1
  28. package/dist/lexicons/com/atproto/repo/listRecords.js +2 -6
  29. package/dist/lexicons/com/atproto/repo/listRecords.js.map +1 -1
  30. package/dist/lexicons/com/atproto/repo/putRecord.defs.js +24 -28
  31. package/dist/lexicons/com/atproto/repo/putRecord.defs.js.map +1 -1
  32. package/dist/lexicons/com/atproto/repo/putRecord.js +2 -6
  33. package/dist/lexicons/com/atproto/repo/putRecord.js.map +1 -1
  34. package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js +8 -11
  35. package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
  36. package/dist/lexicons/com/atproto/repo/uploadBlob.js +2 -6
  37. package/dist/lexicons/com/atproto/repo/uploadBlob.js.map +1 -1
  38. package/dist/lexicons/com/atproto/repo.js +7 -11
  39. package/dist/lexicons/com/atproto/repo.js.map +1 -1
  40. package/dist/lexicons/com/atproto/sync/getBlob.defs.js +9 -12
  41. package/dist/lexicons/com/atproto/sync/getBlob.defs.js.map +1 -1
  42. package/dist/lexicons/com/atproto/sync/getBlob.js +2 -6
  43. package/dist/lexicons/com/atproto/sync/getBlob.js.map +1 -1
  44. package/dist/lexicons/com/atproto/sync.js +1 -5
  45. package/dist/lexicons/com/atproto/sync.js.map +1 -1
  46. package/dist/lexicons/com/atproto.js +2 -6
  47. package/dist/lexicons/com/atproto.js.map +1 -1
  48. package/dist/lexicons/com.js +1 -5
  49. package/dist/lexicons/com.js.map +1 -1
  50. package/dist/lexicons/index.js +1 -5
  51. package/dist/lexicons/index.js.map +1 -1
  52. package/dist/response.js +14 -22
  53. package/dist/response.js.map +1 -1
  54. package/dist/types.d.ts +6 -2
  55. package/dist/types.d.ts.map +1 -1
  56. package/dist/types.js +1 -4
  57. package/dist/types.js.map +1 -1
  58. package/dist/util.js +6 -14
  59. package/dist/util.js.map +1 -1
  60. package/dist/www-authenticate.js +1 -4
  61. package/dist/www-authenticate.js.map +1 -1
  62. package/dist/xrpc.d.ts.map +1 -1
  63. package/dist/xrpc.js +25 -28
  64. package/dist/xrpc.js.map +1 -1
  65. package/package.json +10 -11
  66. package/src/types.ts +8 -4
  67. package/src/xrpc.ts +7 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atproto/lex-client
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#4929](https://github.com/bluesky-social/atproto/pull/4929) [`f01c59f`](https://github.com/bluesky-social/atproto/commit/f01c59f5bd3f75fb8b47a9eecd4858b84033fb7c) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Drop support for Node.js 18 and 20. Node.js 22 is now the minimum supported version. Docker images now use Node.js 24.
8
+
9
+ - [#4943](https://github.com/bluesky-social/atproto/pull/4943) [`c459153`](https://github.com/bluesky-social/atproto/commit/c459153395a30ce89e050892c8fab7dc98e019b9) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Convert to pure ESM. All packages now ship `"type": "module"` with ES module output and Node16 module resolution.
10
+
11
+ Node.js 22's `require()` compatibility layer can still load these packages in CommonJS code.
12
+
13
+ - [`affb50c`](https://github.com/bluesky-social/atproto/commit/affb50c040b497a12631df99a6310f8e78cab557) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** `BinaryBodyInit` (used for binary request bodies and unknown response payloads) now uses `Uint8Array<ArrayBuffer>` rather than `Uint8Array`, matching the buffer-backed (not shared-memory) byte arrays expected by Web APIs. Most callers can pass values through unchanged; in the rare case of a `SharedArrayBuffer`-backed `Uint8Array`, copy into a regular `Uint8Array` first.
14
+
15
+ - [#4930](https://github.com/bluesky-social/atproto/pull/4930) [`908bece`](https://github.com/bluesky-social/atproto/commit/908bece169258bff5ad121e5eec157d6ded6f705) Thanks [@devinivy](https://github.com/devinivy)! - Build with TypeScript 6.0.
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [[`f01c59f`](https://github.com/bluesky-social/atproto/commit/f01c59f5bd3f75fb8b47a9eecd4858b84033fb7c), [`c459153`](https://github.com/bluesky-social/atproto/commit/c459153395a30ce89e050892c8fab7dc98e019b9), [`908bece`](https://github.com/bluesky-social/atproto/commit/908bece169258bff5ad121e5eec157d6ded6f705)]:
20
+ - @atproto/lex-data@0.1.0
21
+ - @atproto/lex-json@0.1.0
22
+ - @atproto/lex-schema@0.1.0
23
+
3
24
  ## 0.0.22
4
25
 
5
26
  ### Patch Changes
package/dist/agent.js CHANGED
@@ -1,8 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isAgent = isAgent;
4
- exports.buildAgent = buildAgent;
5
- function isAgent(value) {
1
+ export function isAgent(value) {
6
2
  return (typeof value === 'object' &&
7
3
  value !== null &&
8
4
  'fetchHandler' in value &&
@@ -11,7 +7,7 @@ function isAgent(value) {
11
7
  value.did === undefined ||
12
8
  typeof value.did === 'string'));
13
9
  }
14
- function buildAgent(options) {
10
+ export function buildAgent(options) {
15
11
  const config = typeof options === 'function'
16
12
  ? { did: undefined, fetchHandler: options }
17
13
  : typeof options === 'string' || options instanceof URL
package/dist/agent.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";;AA0DA,0BAUC;AAiED,gCAiCC;AA5GD,SAAgB,OAAO,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,cAAc,IAAI,KAAK;QACvB,OAAO,KAAK,CAAC,YAAY,KAAK,UAAU;QACxC,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC;YAChB,KAAK,CAAC,GAAG,KAAK,SAAS;YACvB,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CACjC,CAAA;AACH,CAAC;AAiED,SAAgB,UAAU,CAAC,OAA6B;IACtD,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,UAAU;QAC3B,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE;QAC3C,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,YAAY,GAAG;YACrD,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;YACtC,CAAC,CAAC,OAAO,CAAA;IAEf,IAAI,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAA;IAElC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,GAAG,MAAM,CAAA;IAEpD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAA;IACrE,CAAC;IAED,OAAO;QACL,IAAI,GAAG;YACL,OAAO,MAAM,CAAC,GAAG,CAAA;QACnB,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI;YAC3B,MAAM,OAAO,GACX,MAAM,CAAC,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI;gBAC5C,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC;gBAC5C,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAA;YAEpC,OAAO,KAAK,CACV,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,EACtB,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CACvD,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CACnB,cAA2B,EAC3B,cAA2B;IAE3B,8EAA8E;IAC9E,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC,CAAA;IAE1C,MAAM,SAAS,GACb,cAAc,YAAY,OAAO;QAC/B,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,CAAA;IAEjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { DidString } from '@atproto/lex-schema'\n\n/**\n * A function that performs HTTP requests towards a service endpoint.\n *\n * The handler is responsible for adding the origin (protocol, hostname, and\n * port) to the provided path, typically based on authentication or service\n * configuration. The handler can also be responsible for adding any necessary\n * headers, such as authorization tokens.\n *\n * @param path - The URL path (pathname + query parameters) without the origin\n * @param init - Standard fetch RequestInit options\n * @returns A Promise resolving to the HTTP Response\n */\nexport type FetchHandler = (\n /**\n * The URL (pathname + query parameters) to make the request to, without the\n * origin. The origin (protocol, hostname, and port) must be added by this\n * {@link FetchHandler}, typically based on authentication or other factors.\n */\n path: `/${string}`,\n init: RequestInit,\n) => Promise<Response>\n\n/**\n * Core interface for making XRPC requests towards a specific service.\n *\n * An {@link Agent} encapsulates an identity and request handling for AT\n * Protocol operations. Agents will typically handle authentication, service URL\n * resolution, and other request configuration, allowing client code to make\n * requests without needing to manage these details directly. The key component\n * of an Agent is the {@link FetchHandler}, which is responsible for\n * constructing the full request URL and adding any necessary headers or\n * authentication tokens. The Agent's `did` property represents the\n * authenticated user's DID, if available, and can be used for operations that\n * require knowledge of the user's identity (such as creating AT Protocol\n * records).\n *\n * @see {@link buildAgent} for creating (simple) Agent instances.\n *\n * @example\n * ```typescript\n * const agent: Agent = {\n * did: 'did:plc:example123',\n * fetchHandler: async (path, init) => {\n * const url = new URL(path, 'https://bsky.social')\n * return fetch(url, init)\n * }\n * }\n * ```\n */\nexport interface Agent {\n /** The DID of the authenticated user, or `undefined` if unauthenticated. */\n readonly did?: DidString\n /** The fetch handler used to make HTTP requests. */\n fetchHandler: FetchHandler\n}\n\nexport function isAgent(value: unknown): value is Agent {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'fetchHandler' in value &&\n typeof value.fetchHandler === 'function' &&\n (!('did' in value) ||\n value.did === undefined ||\n typeof value.did === 'string')\n )\n}\n\nexport type AgentConfig = {\n /**\n * The identifier (DID) of the user represented by this agent.\n */\n did?: DidString\n\n /**\n * The service URL to make requests to. This can be a string, URL, or a\n * function that returns a string or URL. This is useful for dynamic URLs,\n * such as a service URL that changes based on authentication.\n */\n service: string | URL\n\n /**\n * Optional headers to include with every request made by this agent, unless\n * overridden by the request-specific headers provided to the fetch handler.\n */\n headers?: HeadersInit\n\n /**\n * Bring your own fetch implementation. Typically useful for testing, logging,\n * mocking, or adding retries, session management, signatures, proof of\n * possession (DPoP), SSRF protection, etc. Defaults to the global `fetch`\n * function.\n */\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Options for creating an Agent.\n *\n * Can be a full {@link AgentConfig} object, or a simple service URL string/{@link URL}.\n */\nexport type AgentOptions = AgentConfig | FetchHandler | string | URL\n\n/**\n * Creates an {@link Agent} from various input types.\n *\n * This factory function accepts an existing Agent (returned as-is), a service\n * URL, or a full configuration object. It handles the common case of creating\n * an unauthenticated agent from just a service URL.\n *\n * @param options - Agent instance, configuration object, or service URL\n * @returns A configured Agent ready for making requests\n * @throws {TypeError} If fetch() is not available in the environment\n *\n * @example // From URL string\n * ```typescript\n * const agent = buildAgent('https://public.api.bsky.app')\n * ```\n *\n * @example // From configuration\n * ```typescript\n * const agent = buildAgent({\n * did: 'did:plc:example',\n * service: 'https://bsky.social',\n * headers: { 'Authorization': 'Bearer ...' }\n * })\n * ```\n */\nexport function buildAgent<O extends Agent | AgentOptions>(\n options: O,\n): O extends Agent ? O : Agent\nexport function buildAgent(options: Agent | AgentOptions): Agent {\n const config: Agent | AgentConfig =\n typeof options === 'function'\n ? { did: undefined, fetchHandler: options }\n : typeof options === 'string' || options instanceof URL\n ? { did: undefined, service: options }\n : options\n\n if (isAgent(config)) return config\n\n const { service, fetch = globalThis.fetch } = config\n\n if (typeof fetch !== 'function') {\n throw new TypeError('fetch() is not available in this environment')\n }\n\n return {\n get did() {\n return config.did\n },\n\n async fetchHandler(path, init) {\n const headers =\n config.headers != null && init.headers != null\n ? mergeHeaders(config.headers, init.headers)\n : config.headers || init.headers\n\n return fetch(\n new URL(path, service),\n headers !== init.headers ? { ...init, headers } : init,\n )\n },\n }\n}\n\nfunction mergeHeaders(\n defaultHeaders: HeadersInit,\n requestHeaders: HeadersInit,\n): Headers {\n // We don't want to alter the original Headers objects, so we create a new one\n const result = new Headers(defaultHeaders)\n\n const overrides =\n requestHeaders instanceof Headers\n ? requestHeaders\n : new Headers(requestHeaders)\n\n for (const [key, value] of overrides.entries()) {\n result.set(key, value)\n }\n\n return result\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AA0DA,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,cAAc,IAAI,KAAK;QACvB,OAAO,KAAK,CAAC,YAAY,KAAK,UAAU;QACxC,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC;YAChB,KAAK,CAAC,GAAG,KAAK,SAAS;YACvB,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CACjC,CAAA;AACH,CAAC;AAiED,MAAM,UAAU,UAAU,CAAC,OAA6B;IACtD,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,UAAU;QAC3B,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE;QAC3C,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,YAAY,GAAG;YACrD,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE;YACtC,CAAC,CAAC,OAAO,CAAA;IAEf,IAAI,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAA;IAElC,MAAM,EAAE,OAAO,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,GAAG,MAAM,CAAA;IAEpD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAA;IACrE,CAAC;IAED,OAAO;QACL,IAAI,GAAG;YACL,OAAO,MAAM,CAAC,GAAG,CAAA;QACnB,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI;YAC3B,MAAM,OAAO,GACX,MAAM,CAAC,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI;gBAC5C,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC;gBAC5C,CAAC,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAA;YAEpC,OAAO,KAAK,CACV,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,EACtB,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CACvD,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CACnB,cAA2B,EAC3B,cAA2B;IAE3B,8EAA8E;IAC9E,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC,CAAA;IAE1C,MAAM,SAAS,GACb,cAAc,YAAY,OAAO;QAC/B,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,CAAA;IAEjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import { DidString } from '@atproto/lex-schema'\n\n/**\n * A function that performs HTTP requests towards a service endpoint.\n *\n * The handler is responsible for adding the origin (protocol, hostname, and\n * port) to the provided path, typically based on authentication or service\n * configuration. The handler can also be responsible for adding any necessary\n * headers, such as authorization tokens.\n *\n * @param path - The URL path (pathname + query parameters) without the origin\n * @param init - Standard fetch RequestInit options\n * @returns A Promise resolving to the HTTP Response\n */\nexport type FetchHandler = (\n /**\n * The URL (pathname + query parameters) to make the request to, without the\n * origin. The origin (protocol, hostname, and port) must be added by this\n * {@link FetchHandler}, typically based on authentication or other factors.\n */\n path: `/${string}`,\n init: RequestInit,\n) => Promise<Response>\n\n/**\n * Core interface for making XRPC requests towards a specific service.\n *\n * An {@link Agent} encapsulates an identity and request handling for AT\n * Protocol operations. Agents will typically handle authentication, service URL\n * resolution, and other request configuration, allowing client code to make\n * requests without needing to manage these details directly. The key component\n * of an Agent is the {@link FetchHandler}, which is responsible for\n * constructing the full request URL and adding any necessary headers or\n * authentication tokens. The Agent's `did` property represents the\n * authenticated user's DID, if available, and can be used for operations that\n * require knowledge of the user's identity (such as creating AT Protocol\n * records).\n *\n * @see {@link buildAgent} for creating (simple) Agent instances.\n *\n * @example\n * ```typescript\n * const agent: Agent = {\n * did: 'did:plc:example123',\n * fetchHandler: async (path, init) => {\n * const url = new URL(path, 'https://bsky.social')\n * return fetch(url, init)\n * }\n * }\n * ```\n */\nexport interface Agent {\n /** The DID of the authenticated user, or `undefined` if unauthenticated. */\n readonly did?: DidString\n /** The fetch handler used to make HTTP requests. */\n fetchHandler: FetchHandler\n}\n\nexport function isAgent(value: unknown): value is Agent {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'fetchHandler' in value &&\n typeof value.fetchHandler === 'function' &&\n (!('did' in value) ||\n value.did === undefined ||\n typeof value.did === 'string')\n )\n}\n\nexport type AgentConfig = {\n /**\n * The identifier (DID) of the user represented by this agent.\n */\n did?: DidString\n\n /**\n * The service URL to make requests to. This can be a string, URL, or a\n * function that returns a string or URL. This is useful for dynamic URLs,\n * such as a service URL that changes based on authentication.\n */\n service: string | URL\n\n /**\n * Optional headers to include with every request made by this agent, unless\n * overridden by the request-specific headers provided to the fetch handler.\n */\n headers?: HeadersInit\n\n /**\n * Bring your own fetch implementation. Typically useful for testing, logging,\n * mocking, or adding retries, session management, signatures, proof of\n * possession (DPoP), SSRF protection, etc. Defaults to the global `fetch`\n * function.\n */\n fetch?: typeof globalThis.fetch\n}\n\n/**\n * Options for creating an Agent.\n *\n * Can be a full {@link AgentConfig} object, or a simple service URL string/{@link URL}.\n */\nexport type AgentOptions = AgentConfig | FetchHandler | string | URL\n\n/**\n * Creates an {@link Agent} from various input types.\n *\n * This factory function accepts an existing Agent (returned as-is), a service\n * URL, or a full configuration object. It handles the common case of creating\n * an unauthenticated agent from just a service URL.\n *\n * @param options - Agent instance, configuration object, or service URL\n * @returns A configured Agent ready for making requests\n * @throws {TypeError} If fetch() is not available in the environment\n *\n * @example // From URL string\n * ```typescript\n * const agent = buildAgent('https://public.api.bsky.app')\n * ```\n *\n * @example // From configuration\n * ```typescript\n * const agent = buildAgent({\n * did: 'did:plc:example',\n * service: 'https://bsky.social',\n * headers: { 'Authorization': 'Bearer ...' }\n * })\n * ```\n */\nexport function buildAgent<O extends Agent | AgentOptions>(\n options: O,\n): O extends Agent ? O : Agent\nexport function buildAgent(options: Agent | AgentOptions): Agent {\n const config: Agent | AgentConfig =\n typeof options === 'function'\n ? { did: undefined, fetchHandler: options }\n : typeof options === 'string' || options instanceof URL\n ? { did: undefined, service: options }\n : options\n\n if (isAgent(config)) return config\n\n const { service, fetch = globalThis.fetch } = config\n\n if (typeof fetch !== 'function') {\n throw new TypeError('fetch() is not available in this environment')\n }\n\n return {\n get did() {\n return config.did\n },\n\n async fetchHandler(path, init) {\n const headers =\n config.headers != null && init.headers != null\n ? mergeHeaders(config.headers, init.headers)\n : config.headers || init.headers\n\n return fetch(\n new URL(path, service),\n headers !== init.headers ? { ...init, headers } : init,\n )\n },\n }\n}\n\nfunction mergeHeaders(\n defaultHeaders: HeadersInit,\n requestHeaders: HeadersInit,\n): Headers {\n // We don't want to alter the original Headers objects, so we create a new one\n const result = new Headers(defaultHeaders)\n\n const overrides =\n requestHeaders instanceof Headers\n ? requestHeaders\n : new Headers(requestHeaders)\n\n for (const [key, value] of overrides.entries()) {\n result.set(key, value)\n }\n\n return result\n}\n"]}
package/dist/client.js CHANGED
@@ -1,11 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Client = void 0;
4
- const lex_schema_1 = require("@atproto/lex-schema");
5
- const agent_js_1 = require("./agent.js");
6
- const index_js_1 = require("./lexicons/index.js");
7
- const util_js_1 = require("./util.js");
8
- const xrpc_js_1 = require("./xrpc.js");
1
+ import { Procedure, Query, getMain, } from '@atproto/lex-schema';
2
+ import { buildAgent } from './agent.js';
3
+ import { com } from './lexicons/index.js';
4
+ import { applyDefaults, buildXrpcRequestHeaders, } from './util.js';
5
+ import { xrpc, xrpcSafe, } from './xrpc.js';
9
6
  /**
10
7
  * The Client class is the primary interface for interacting with AT Protocol
11
8
  * services. It provides type-safe methods for XRPC calls, record operations,
@@ -23,8 +20,8 @@ const xrpc_js_1 = require("./xrpc.js");
23
20
  * })
24
21
  * ```
25
22
  */
26
- class Client {
27
- static appLabelers = [];
23
+ export class Client {
24
+ static { this.appLabelers = []; }
28
25
  /**
29
26
  * Configures the Client (or its sub classes) globally.
30
27
  */
@@ -32,17 +29,8 @@ class Client {
32
29
  if (opts.appLabelers)
33
30
  this.appLabelers = [...opts.appLabelers];
34
31
  }
35
- /** The underlying agent used for making requests. */
36
- agent;
37
- /** Custom headers included in all requests. */
38
- headers;
39
- /** Optional service identifier for routing requests. */
40
- service;
41
- /** Set of labeler DIDs specific to this client instance. */
42
- labelers;
43
- xrpcDefaults;
44
32
  constructor(agent, options = {}) {
45
- this.agent = (0, agent_js_1.buildAgent)(agent);
33
+ this.agent = buildAgent(agent);
46
34
  this.service = options.service;
47
35
  this.labelers = new Set(options.labelers);
48
36
  this.headers = new Headers(options.headers);
@@ -115,7 +103,7 @@ class Client {
115
103
  * @param init - Request initialization options
116
104
  */
117
105
  fetchHandler(path, init) {
118
- const headers = (0, util_js_1.buildXrpcRequestHeaders)({
106
+ const headers = buildXrpcRequestHeaders({
119
107
  headers: init.headers,
120
108
  service: this.service,
121
109
  labelers: [
@@ -132,10 +120,10 @@ class Client {
132
120
  return this.agent.fetchHandler(path, { ...init, headers });
133
121
  }
134
122
  async xrpc(ns, options = {}) {
135
- return (0, xrpc_js_1.xrpc)(this, ns, (0, util_js_1.applyDefaults)(options, this.xrpcDefaults));
123
+ return xrpc(this, ns, applyDefaults(options, this.xrpcDefaults));
136
124
  }
137
125
  async xrpcSafe(ns, options = {}) {
138
- return (0, xrpc_js_1.xrpcSafe)(this, ns, (0, util_js_1.applyDefaults)(options, this.xrpcDefaults));
126
+ return xrpcSafe(this, ns, applyDefaults(options, this.xrpcDefaults));
139
127
  }
140
128
  /**
141
129
  * Creates a new record in an AT Protocol repository.
@@ -158,7 +146,7 @@ class Client {
158
146
  * @see {@link create} for a higher-level typed alternative
159
147
  */
160
148
  async createRecord(record, rkey, options) {
161
- return this.xrpc(index_js_1.com.atproto.repo.createRecord.main, {
149
+ return this.xrpc(com.atproto.repo.createRecord.main, {
162
150
  ...options,
163
151
  body: {
164
152
  repo: options?.repo ?? this.assertDid,
@@ -180,7 +168,7 @@ class Client {
180
168
  * @see {@link delete} for a higher-level typed alternative
181
169
  */
182
170
  async deleteRecord(collection, rkey, options) {
183
- return this.xrpc(index_js_1.com.atproto.repo.deleteRecord.main, {
171
+ return this.xrpc(com.atproto.repo.deleteRecord.main, {
184
172
  ...options,
185
173
  body: {
186
174
  repo: options?.repo ?? this.assertDid,
@@ -201,7 +189,7 @@ class Client {
201
189
  * @see {@link get} for a higher-level typed alternative
202
190
  */
203
191
  async getRecord(collection, rkey, options) {
204
- return this.xrpc(index_js_1.com.atproto.repo.getRecord.main, {
192
+ return this.xrpc(com.atproto.repo.getRecord.main, {
205
193
  ...options,
206
194
  params: {
207
195
  repo: options?.repo ?? this.assertDid,
@@ -220,7 +208,7 @@ class Client {
220
208
  * @see {@link put} for a higher-level typed alternative
221
209
  */
222
210
  async putRecord(record, rkey, options) {
223
- return this.xrpc(index_js_1.com.atproto.repo.putRecord.main, {
211
+ return this.xrpc(com.atproto.repo.putRecord.main, {
224
212
  ...options,
225
213
  body: {
226
214
  repo: options?.repo ?? this.assertDid,
@@ -242,7 +230,7 @@ class Client {
242
230
  * @see {@link list} for a higher-level typed alternative
243
231
  */
244
232
  async listRecords(nsid, options) {
245
- return this.xrpc(index_js_1.com.atproto.repo.listRecords.main, {
233
+ return this.xrpc(com.atproto.repo.listRecords.main, {
246
234
  ...options,
247
235
  params: {
248
236
  repo: options?.repo ?? this.assertDid,
@@ -270,7 +258,7 @@ class Client {
270
258
  * ```
271
259
  */
272
260
  async uploadBlob(body, options) {
273
- return this.xrpc(index_js_1.com.atproto.repo.uploadBlob.main, { ...options, body });
261
+ return this.xrpc(com.atproto.repo.uploadBlob.main, { ...options, body });
274
262
  }
275
263
  /**
276
264
  * Retrieves a blob by DID and CID.
@@ -280,21 +268,21 @@ class Client {
280
268
  * @param options - Call options
281
269
  */
282
270
  async getBlob(did, cid, options) {
283
- return this.xrpc(index_js_1.com.atproto.sync.getBlob.main, {
271
+ return this.xrpc(com.atproto.sync.getBlob.main, {
284
272
  ...options,
285
273
  params: { did, cid },
286
274
  });
287
275
  }
288
276
  async call(ns, arg, options = {}) {
289
- const method = (0, lex_schema_1.getMain)(ns);
277
+ const method = getMain(ns);
290
278
  if (typeof method === 'function') {
291
279
  return method(this, arg, options);
292
280
  }
293
- if (method instanceof lex_schema_1.Procedure) {
281
+ if (method instanceof Procedure) {
294
282
  const result = await this.xrpc(method, { ...options, body: arg });
295
283
  return result.body;
296
284
  }
297
- else if (method instanceof lex_schema_1.Query) {
285
+ else if (method instanceof Query) {
298
286
  const result = await this.xrpc(method, { ...options, params: arg });
299
287
  return result.body;
300
288
  }
@@ -303,7 +291,7 @@ class Client {
303
291
  }
304
292
  }
305
293
  async create(ns, input, options = {}) {
306
- const schema = (0, lex_schema_1.getMain)(ns);
294
+ const schema = getMain(ns);
307
295
  const record = schema.build(input);
308
296
  if (options?.validateRequest)
309
297
  schema.validate(record);
@@ -314,20 +302,20 @@ class Client {
314
302
  return response.body;
315
303
  }
316
304
  async delete(ns, options = {}) {
317
- const schema = (0, lex_schema_1.getMain)(ns);
305
+ const schema = getMain(ns);
318
306
  const rkey = schema.keySchema.parse(options.rkey ?? getLiteralRecordKey(schema));
319
307
  const response = await this.deleteRecord(schema.$type, rkey, options);
320
308
  return response.body;
321
309
  }
322
310
  async get(ns, options = {}) {
323
- const schema = (0, lex_schema_1.getMain)(ns);
311
+ const schema = getMain(ns);
324
312
  const rkey = schema.keySchema.parse(options.rkey ?? getLiteralRecordKey(schema));
325
313
  const response = await this.getRecord(schema.$type, rkey, options);
326
314
  const value = schema.validate(response.body.value);
327
315
  return { ...response.body, value };
328
316
  }
329
317
  async put(ns, input, options = {}) {
330
- const schema = (0, lex_schema_1.getMain)(ns);
318
+ const schema = getMain(ns);
331
319
  const record = schema.build(input);
332
320
  if (options?.validateRequest)
333
321
  schema.validate(record);
@@ -350,7 +338,7 @@ class Client {
350
338
  * ```
351
339
  */
352
340
  async list(ns, options) {
353
- const schema = (0, lex_schema_1.getMain)(ns);
341
+ const schema = getMain(ns);
354
342
  const { body } = await this.listRecords(schema.$type, options);
355
343
  const records = [];
356
344
  const invalid = [];
@@ -366,7 +354,6 @@ class Client {
366
354
  return { ...body, records, invalid };
367
355
  }
368
356
  }
369
- exports.Client = Client;
370
357
  function getDefaultRecordKey(schema) {
371
358
  // Let the server generate the TID
372
359
  if (schema.key === 'tid')
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexMap, LexValue, TypedLexMap } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n CidString,\n DidString,\n Infer,\n InferMethodInputBody,\n InferMethodOutputBody,\n InferRecordKey,\n LexiconRecordKey,\n Main,\n NsidString,\n Params,\n Procedure,\n Query,\n RecordSchema,\n Restricted,\n getMain,\n} from '@atproto/lex-schema'\nimport { Agent, AgentOptions, buildAgent } from './agent.js'\nimport { XrpcFailure } from './errors.js'\nimport { com } from './lexicons/index.js'\nimport {\n XrpcResponse,\n XrpcResponseBody,\n XrpcResponseOptions,\n} from './response.js'\nimport { BinaryBodyInit, Service } from './types.js'\nimport {\n XrpcRequestHeadersOptions,\n applyDefaults,\n buildXrpcRequestHeaders,\n} from './util.js'\nimport {\n XrpcOptions,\n XrpcRequestParams,\n XrpcRequestProcessingOptions,\n xrpc,\n xrpcSafe,\n} from './xrpc.js'\n\nexport type {\n AtIdentifierString,\n CidString,\n DidString,\n Infer,\n InferMethodInputBody,\n InferMethodOutputBody,\n InferRecordKey,\n LexMap,\n LexValue,\n LexiconRecordKey,\n Main,\n NsidString,\n Params,\n Procedure,\n Query,\n RecordSchema,\n Restricted,\n TypedLexMap,\n}\n\n/**\n * Configuration options for creating a {@link Client}.\n *\n * @property {@link ClientOptions.labelers} - An iterable of labeler DIDs to include in requests. These will be combined with any global app labelers configured via {@link Client.configure}.\n * @property {@link ClientOptions.service} - An optional service identifier (DID or URL) for routing requests with service proxying.\n * @property {@link ClientOptions.headers} - Custom headers to include in all requests made by this client instance.\n * @property {@link ClientOptions.validateRequest} - If true, validates request bodies against their lexicon schemas before sending. Defaults to false for performance.\n * @property {@link ClientOptions.validateResponse} - If false, skips validation of response bodies against their lexicon schemas. Defaults to true to catch errors, but can be disabled for performance if you trust the server responses. Note that defaults will not be applied if validation is disabled, which can cause typing inconsistencies, so use with caution.\n * @property {@link ClientOptions.strictResponseProcessing} - If false, relaxes certain validation rules during response processing (e.g., allowing floats, deeper nesting, etc.). Defaults to true for strict compliance with {@link https://atproto.com/specs/data-model lexicon data model}, but can be disabled to handle non-compliant responses.\n *\n * @see {@link XrpcRequestHeadersOptions}\n * @see {@link XrpcRequestProcessingOptions}\n * @see {@link XrpcResponseOptions}\n *\n * @example\n * ```typescript\n * const options: ClientOptions = {\n * labelers: ['did:plc:labeler1'],\n * service: 'did:web:api.bsky.app#bsky_appview',\n * headers: { 'X-Custom-Header': 'value' },\n * validateRequest: false,\n * validateResponse: true,\n * strictResponseProcessing: false,\n * }\n * ```\n */\nexport type ClientOptions = XrpcRequestHeadersOptions &\n Pick<XrpcRequestProcessingOptions, 'validateRequest'> &\n XrpcResponseOptions\n\nexport type ActionOptions = {\n /** AbortSignal to cancel the request. */\n signal?: AbortSignal\n}\n\n/**\n * A composable action that can be invoked via {@link Client.call}.\n *\n * Actions provide a way to define custom operations that integrate with the\n * Client's call interface, enabling type-safe, reusable business logic.\n *\n * @typeParam I - The input type for the action\n * @typeParam O - The output type for the action\n *\n * @example\n * ```typescript\n * const myAction: Action<{ userId: string }, { profile: Profile }> = async (client, input, options) => {\n * const response = await client.xrpc(someMethod, { params: { actor: input.userId }, ...options })\n * return { profile: response.body }\n * }\n * ```\n */\nexport type Action<I = any, O = any> = (\n client: Client,\n input: I,\n options: ActionOptions,\n) => O | Promise<O>\n\n/**\n * Extracts the input type from an {@link Action}.\n * @typeParam A - The Action type to extract from\n */\nexport type InferActionInput<A extends Action> =\n A extends Action<infer I, any> ? I : never\n\n/**\n * Extracts the output type from an {@link Action}.\n * @typeParam A - The Action type to extract from\n */\nexport type InferActionOutput<A extends Action> =\n A extends Action<any, infer O> ? O : never\n\n/**\n * Options for creating a record in an AT Protocol repository.\n *\n * @see {@link Client.createRecord}\n */\nexport type CreateRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.createRecord.main>,\n 'body'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Compare-and-swap on the repo commit. If specified, must match current commit. */\n swapCommit?: string\n /** Whether to validate the record against its lexicon schema. */\n validate?: boolean\n}\n\n/**\n * Options for deleting a record from an AT Protocol repository.\n *\n * @see {@link Client.deleteRecord}\n */\nexport type DeleteRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.deleteRecord.main>,\n 'body'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Compare-and-swap on the repo commit. If specified, must match current commit. */\n swapCommit?: string\n /** Compare-and-swap on the record CID. If specified, must match current record. */\n swapRecord?: string\n}\n\n/**\n * Options for retrieving a record from an AT Protocol repository.\n *\n * @see {@link Client.getRecord}\n */\nexport type GetRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.getRecord.main>,\n 'params'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n}\n\n/**\n * Options for creating or updating a record in an AT Protocol repository.\n *\n * @see {@link Client.putRecord}\n */\nexport type PutRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.putRecord.main>,\n 'body'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Compare-and-swap on the repo commit. If specified, must match current commit. */\n swapCommit?: string\n /** Compare-and-swap on the record CID. If specified, must match current record. */\n swapRecord?: string\n /** Whether to validate the record against its lexicon schema. */\n validate?: boolean\n}\n\n/**\n * Options for listing records in an AT Protocol repository collection.\n *\n * @see {@link Client.listRecords}\n */\nexport type ListRecordsOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.listRecords.main>,\n 'params'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Maximum number of records to return. */\n limit?: number\n /** Pagination cursor from a previous response. */\n cursor?: string\n /** If true, returns records in reverse chronological order. */\n reverse?: boolean\n}\n\nexport type UploadBlobOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.uploadBlob.main>,\n 'body'\n>\n\nexport type GetBlobOptions = Omit<\n XrpcOptions<typeof com.atproto.sync.getBlob.main>,\n 'params'\n>\n\nexport type RecordKeyOptions<\n T extends RecordSchema,\n AlsoOptionalWhenRecordKeyIs extends LexiconRecordKey = never,\n> = T['key'] extends `literal:${string}` | AlsoOptionalWhenRecordKeyIs\n ? { rkey?: InferRecordKey<T> }\n : { rkey: InferRecordKey<T> }\n\n/**\n * Type-safe options for {@link Client.create}, combining record options with key requirements.\n * @typeParam T - The record schema type\n * @see {@link CreateRecordOptions}\n */\nexport type CreateOptions<T extends RecordSchema> = CreateRecordOptions &\n RecordKeyOptions<T, 'tid' | 'any'>\n\n/**\n * Output type for record creation operations.\n * Contains the URI and CID of the newly created record.\n */\nexport type CreateOutput = InferMethodOutputBody<\n typeof com.atproto.repo.createRecord.main,\n Uint8Array\n>\n\n/**\n * Type-safe options for {@link Client.delete}, combining delete options with key requirements.\n * @typeParam T - The record schema type\n */\nexport type DeleteOptions<T extends RecordSchema> = DeleteRecordOptions &\n RecordKeyOptions<T>\n\n/**\n * Output type for record deletion operations.\n */\nexport type DeleteOutput = InferMethodOutputBody<\n typeof com.atproto.repo.deleteRecord.main,\n Uint8Array\n>\n\n/**\n * Type-safe options for {@link Client.get}, combining get options with key requirements.\n * @typeParam T - The record schema type\n */\nexport type GetOptions<T extends RecordSchema> = GetRecordOptions &\n RecordKeyOptions<T>\n\n/**\n * Output type for record retrieval operations.\n * Contains the record value validated against the schema type.\n * @typeParam T - The record schema type\n */\nexport type GetOutput<T extends RecordSchema> = Omit<\n InferMethodOutputBody<typeof com.atproto.repo.getRecord.main, Uint8Array>,\n 'value'\n> & { value: Infer<T> }\n\n/**\n * Type-safe options for {@link Client.put}, combining put options with key requirements.\n * @typeParam T - The record schema type\n */\nexport type PutOptions<T extends RecordSchema> = PutRecordOptions &\n RecordKeyOptions<T>\n\n/**\n * Output type for record put (create/update) operations.\n * Contains the URI and CID of the record.\n */\nexport type PutOutput = InferMethodOutputBody<\n typeof com.atproto.repo.putRecord.main,\n Uint8Array\n>\n\n/**\n * Options for {@link Client.list} operations.\n */\nexport type ListOptions = ListRecordsOptions\n\n/**\n * Output type for record listing operations.\n * Contains validated records and any invalid records that failed schema validation.\n * @typeParam T - The record schema type\n */\nexport type ListOutput<T extends RecordSchema> = InferMethodOutputBody<\n typeof com.atproto.repo.listRecords.main,\n Uint8Array\n> & {\n /** Records that successfully validated against the schema. */\n records: ListRecord<Infer<T>>[]\n // @NOTE Because the schema uses \"type\": \"unknown\" instead of an open union,\n // we have to use LexMap instead of Unknown$TypedObject here, which is\n // unfortunate.\n /** Records that failed schema validation. */\n invalid: LexMap[]\n}\n\n/**\n * A record from a list operation with its value typed to the schema.\n * @typeParam Value - The validated record value type\n */\nexport type ListRecord<Value extends LexMap> =\n com.atproto.repo.listRecords.Record & {\n value: Value\n }\n\n/**\n * The Client class is the primary interface for interacting with AT Protocol\n * services. It provides type-safe methods for XRPC calls, record operations,\n * and blob handling.\n *\n * @example\n * ```typescript\n * import { Client } from '@atproto/lex'\n * import { app } from '#/lexicons\n *\n * const client = new Client(oauthSession)\n *\n * const response = await client.xrpc(app.bsky.feed.getTimeline.main, {\n * params: { limit: 50 }\n * })\n * ```\n */\nexport class Client implements Agent {\n static appLabelers: readonly DidString[] = []\n\n /**\n * Configures the Client (or its sub classes) globally.\n */\n static configure(opts: { appLabelers?: Iterable<DidString> }) {\n if (opts.appLabelers) this.appLabelers = [...opts.appLabelers]\n }\n\n /** The underlying agent used for making requests. */\n public readonly agent: Agent\n\n /** Custom headers included in all requests. */\n public readonly headers: Headers\n\n /** Optional service identifier for routing requests. */\n public readonly service?: Service\n\n /** Set of labeler DIDs specific to this client instance. */\n public readonly labelers: Set<DidString>\n\n public readonly xrpcDefaults: {\n readonly validateRequest: boolean\n readonly validateResponse: boolean\n readonly strictResponseProcessing: boolean\n }\n\n constructor(agent: Agent | AgentOptions, options: ClientOptions = {}) {\n this.agent = buildAgent(agent)\n this.service = options.service\n this.labelers = new Set(options.labelers)\n this.headers = new Headers(options.headers)\n this.xrpcDefaults = Object.freeze({\n validateRequest: options.validateRequest ?? false,\n validateResponse: options.validateResponse ?? true,\n strictResponseProcessing: options.strictResponseProcessing ?? true,\n })\n }\n\n /**\n * The DID of the authenticated user, or `undefined` if not authenticated.\n */\n get did(): DidString | undefined {\n return this.agent.did\n }\n\n /**\n * The DID of the authenticated user.\n * @throws {Error} if not authenticated\n */\n get assertDid(): DidString {\n this.assertAuthenticated()\n return this.did\n }\n\n /**\n * Asserts that the client is authenticated.\n * Use as a type guard when you need to ensure authentication.\n *\n * @throws {Error} if not authenticated\n *\n * @example\n * ```typescript\n * client.assertAuthenticated()\n * // TypeScript now knows client.did is defined\n * console.log(client.did)\n * ```\n */\n public assertAuthenticated(): asserts this is { did: DidString } {\n if (!this.did) throw new Error('Client is not authenticated')\n }\n\n /**\n * Replaces all labelers with the given set.\n * @param labelers - Iterable of labeler DIDs\n */\n public setLabelers(labelers: Iterable<DidString> = []) {\n this.clearLabelers()\n this.addLabelers(labelers)\n }\n\n /**\n * Adds labelers to the current set.\n * @param labelers - Iterable of labeler DIDs to add\n */\n public addLabelers(labelers: Iterable<DidString>) {\n for (const labeler of labelers) this.labelers.add(labeler)\n }\n\n /**\n * Removes all labelers from this client instance.\n */\n public clearLabelers() {\n this.labelers.clear()\n }\n\n /**\n * {@link Agent}'s {@link Agent.fetchHandler} implementation, which adds\n * labelers and service proxying headers. This method allow a {@link Client}\n * instance to be used directly as an {@link Agent} for another\n * {@link Client}, enabling composition of headers (labelers, proxying, etc.).\n *\n * @param path - The request path\n * @param init - Request initialization options\n */\n public fetchHandler(\n path: `/${string}`,\n init: RequestInit,\n ): Promise<Response> {\n const headers = buildXrpcRequestHeaders({\n headers: init.headers,\n service: this.service,\n labelers: [\n ...(this.constructor as typeof Client).appLabelers.map(\n (l) => `${l};redact` as const,\n ),\n ...this.labelers,\n ],\n })\n\n // Incoming headers take precedence\n for (const [key, value] of this.headers) {\n if (!headers.has(key)) headers.set(key, value)\n }\n\n // @NOTE The agent here could be another Client instance.\n return this.agent.fetchHandler(path, { ...init, headers })\n }\n\n /**\n * Makes an XRPC request. Throws on failure.\n *\n * @param ns - The lexicon method definition (e.g., `app.bsky.feed.getTimeline`)\n * @param options - Request options including params and body\n * @returns The successful XRPC response\n * @throws {XrpcFailure} when the request fails or returns an error\n *\n * @example Query with parameters\n * ```typescript\n * const response = await client.xrpc(app.bsky.feed.getTimeline, {\n * params: { limit: 50, cursor: 'abc123' }\n * })\n * console.log(response.body.feed)\n * ```\n *\n * @example Procedure with body\n * ```typescript\n * const response = await client.xrpc(com.atproto.repo.createRecord, {\n * body: {\n * repo: client.assertDid,\n * collection: 'app.bsky.feed.post',\n * record: { text: 'Hello!', createdAt: new Date().toISOString() }\n * }\n * })\n * ```\n *\n * @see {@link xrpcSafe} for a non-throwing variant\n */\n async xrpc<const M extends Query | Procedure>(\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n ): Promise<XrpcResponse<M>>\n async xrpc<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M>,\n ): Promise<XrpcResponse<M>>\n async xrpc<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n ): Promise<XrpcResponse<M>> {\n return xrpc(this, ns, applyDefaults(options, this.xrpcDefaults))\n }\n\n /**\n * Makes an XRPC request without throwing on failure.\n * Returns either a successful response or a failure object.\n *\n * @param ns - The lexicon method definition\n * @param options - Request options\n * @returns Either an XrpcResponse on success or XrpcFailure on failure\n *\n * @example\n * ```typescript\n * const result = await client.xrpcSafe(app.bsky.actor.getProfile.main, {\n * params: { actor: 'alice.bsky.social' }\n * })\n *\n * if (result.success) {\n * console.log(result.body.displayName)\n * } else {\n * console.error('Failed:', result.error)\n * }\n * ```\n *\n * @see {@link xrpc} for a throwing variant\n */\n async xrpcSafe<const M extends Query | Procedure>(\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n ): Promise<XrpcResponse<M> | XrpcFailure<M>>\n async xrpcSafe<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M>,\n ): Promise<XrpcResponse<M> | XrpcFailure<M>>\n async xrpcSafe<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n ): Promise<XrpcResponse<M> | XrpcFailure<M>> {\n return xrpcSafe(this, ns, applyDefaults(options, this.xrpcDefaults))\n }\n\n /**\n * Creates a new record in an AT Protocol repository.\n *\n * @param record - The record to create, must include an {@link NsidString} `$type`\n * @param rkey - Optional record key; if omitted, server generates a TID\n * @param options - Create options including repo, swapCommit, validate\n * @returns The XRPC response containing the created record's URI and CID\n *\n * @example\n * ```typescript\n * const response = await client.createRecord(\n * { $type: 'app.bsky.feed.post', text: 'Hello!', createdAt: new Date().toISOString() },\n * undefined, // Let server generate rkey\n * { validate: true }\n * )\n * console.log(response.body.uri)\n * ```\n *\n * @see {@link create} for a higher-level typed alternative\n */\n public async createRecord(\n record: TypedLexMap<NsidString>,\n rkey?: string,\n options?: CreateRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.createRecord.main, {\n ...options,\n body: {\n repo: options?.repo ?? this.assertDid,\n collection: record.$type,\n record,\n rkey,\n validate: options?.validate,\n swapCommit: options?.swapCommit,\n },\n })\n }\n\n /**\n * Deletes a record from an AT Protocol repository.\n *\n * @param collection - The collection NSID\n * @param rkey - The record key\n * @param options - Delete options including repo, swapCommit, swapRecord\n *\n * @see {@link delete} for a higher-level typed alternative\n */\n async deleteRecord(\n collection: NsidString,\n rkey: string,\n options?: DeleteRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.deleteRecord.main, {\n ...options,\n body: {\n repo: options?.repo ?? this.assertDid,\n collection,\n rkey,\n swapCommit: options?.swapCommit,\n swapRecord: options?.swapRecord,\n },\n })\n }\n\n /**\n * Retrieves a record from an AT Protocol repository.\n *\n * @param collection - The collection NSID\n * @param rkey - The record key\n * @param options - Get options including repo\n *\n * @see {@link get} for a higher-level typed alternative\n */\n public async getRecord(\n collection: NsidString,\n rkey: string,\n options?: GetRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.getRecord.main, {\n ...options,\n params: {\n repo: options?.repo ?? this.assertDid,\n collection,\n rkey,\n },\n })\n }\n\n /**\n * Creates or updates a record in a repository.\n *\n * @param record - The record to put, must include an {@link NsidString} `$type`\n * @param rkey - The record key\n * @param options - Put options including repo, swapCommit, swapRecord, validate\n *\n * @see {@link put} for a higher-level typed alternative\n */\n async putRecord(\n record: TypedLexMap<NsidString>,\n rkey: string,\n options?: PutRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.putRecord.main, {\n ...options,\n body: {\n repo: options?.repo ?? this.assertDid,\n collection: record.$type,\n rkey,\n record,\n validate: options?.validate,\n swapCommit: options?.swapCommit,\n swapRecord: options?.swapRecord,\n },\n })\n }\n\n /**\n * Lists records in a collection.\n *\n * @param nsid - The collection NSID\n * @param options - List options including repo, limit, cursor, reverse\n *\n * @see {@link list} for a higher-level typed alternative\n */\n async listRecords(nsid: NsidString, options?: ListRecordsOptions) {\n return this.xrpc(com.atproto.repo.listRecords.main, {\n ...options,\n params: {\n repo: options?.repo ?? this.assertDid,\n collection: nsid,\n cursor: options?.cursor,\n limit: options?.limit,\n reverse: options?.reverse,\n },\n })\n }\n\n /**\n * Uploads a blob to an AT Protocol repository.\n *\n * @param body - The blob data (Uint8Array, ReadableStream, Blob, etc.)\n * @param options - Upload options including encoding hint\n * @returns Response containing the blob reference\n *\n * @example\n * ```typescript\n * const imageData = await fetch('image.png').then(r => r.arrayBuffer())\n * const response = await client.uploadBlob(new Uint8Array(imageData), {\n * encoding: 'image/png'\n * })\n * console.log(response.body.blob) // Use this ref in records\n * ```\n */\n async uploadBlob(body: BinaryBodyInit, options?: UploadBlobOptions) {\n return this.xrpc(com.atproto.repo.uploadBlob.main, { ...options, body })\n }\n\n /**\n * Retrieves a blob by DID and CID.\n *\n * @param did - The DID of the repository containing the blob\n * @param cid - The CID of the blob\n * @param options - Call options\n */\n async getBlob(did: DidString, cid: CidString, options?: GetBlobOptions) {\n return this.xrpc(com.atproto.sync.getBlob.main, {\n ...options,\n params: { did, cid },\n })\n }\n\n /**\n * Universal call method for queries, procedures, and custom actions.\n * Automatically determines the call type based on the lexicon definition.\n *\n * @param ns - The lexicon method or action definition\n * @param arg - The input argument (params for queries, body for procedures, input for actions)\n * @param options - Call options\n * @returns The method response body or action output\n * @see {@link xrpc} if you need access to the full response object\n *\n * @example Query\n * ```typescript\n * const profile = await client.call(app.bsky.actor.getProfile.main, {\n * actor: 'alice.bsky.social'\n * })\n * ```\n *\n * @example Procedure\n * ```typescript\n * const result = await client.call(com.atproto.repo.createRecord.main, {\n * repo: did,\n * collection: 'app.bsky.feed.post',\n * record: { text: 'Hello!' }\n * })\n * ```\n */\n public async call<const T extends Query>(\n ns: NonNullable<unknown> extends XrpcRequestParams<T>\n ? Main<T>\n : Restricted<'This query type requires a \"params\" argument'>,\n ): Promise<XrpcResponseBody<T>>\n public async call<const T extends Procedure>(\n ns: undefined extends InferMethodInputBody<T, Uint8Array>\n ? Main<T>\n : Restricted<'This procedure type requires an \"input\" argument'>,\n ): Promise<XrpcResponseBody<T>>\n public async call<const T extends Action>(\n ns: void extends InferActionInput<T>\n ? Main<T>\n : Restricted<'This action type requires an \"input\" argument'>,\n ): Promise<InferActionOutput<T>>\n public async call<const T extends Action | Procedure | Query>(\n ns: Main<T>,\n arg: T extends Action\n ? InferActionInput<T>\n : T extends Procedure\n ? InferMethodInputBody<T, Uint8Array>\n : T extends Query\n ? XrpcRequestParams<T>\n : never,\n options?: T extends Action\n ? ActionOptions\n : T extends Procedure\n ? Omit<XrpcOptions<T>, 'body'>\n : T extends Query\n ? Omit<XrpcOptions<T>, 'params'>\n : never,\n ): Promise<\n T extends Action\n ? InferActionOutput<T>\n : T extends Procedure\n ? XrpcResponseBody<T>\n : T extends Query\n ? XrpcResponseBody<T>\n : never\n >\n public async call(\n ns: Main<Action> | Main<Procedure> | Main<Query>,\n arg?: LexValue | Params,\n options: ActionOptions = {},\n ): Promise<unknown> {\n const method = getMain(ns)\n\n if (typeof method === 'function') {\n return method(this, arg, options)\n }\n\n if (method instanceof Procedure) {\n const result = await this.xrpc(method, { ...options, body: arg as any })\n return result.body\n } else if (method instanceof Query) {\n const result = await this.xrpc(method, { ...options, params: arg as any })\n return result.body\n } else {\n throw new TypeError('Invalid lexicon')\n }\n }\n\n /**\n * Creates a new record with full type safety based on the schema.\n *\n * @param ns - The record schema definition\n * @param input - The record data (without `$type`, which is added automatically)\n * @param options - Create options including rkey (required for some record types)\n * @returns The create output including URI and CID\n *\n * @example Creating a post\n * ```typescript\n * const result = await client.create(app.bsky.feed.post.main, {\n * text: 'Hello, world!',\n * createdAt: new Date().toISOString()\n * })\n * console.log(result.uri)\n * ```\n *\n * @example Creating a record with explicit rkey\n * ```typescript\n * const result = await client.create(app.bsky.actor.profile.main, {\n * displayName: 'Alice'\n * }, { rkey: 'self' })\n * ```\n */\n public async create<const T extends RecordSchema>(\n ns: NonNullable<unknown> extends CreateOptions<T>\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n input: Omit<Infer<T>, '$type'>,\n ): Promise<CreateOutput>\n public async create<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: CreateOptions<T>,\n ): Promise<CreateOutput>\n public async create<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: CreateOptions<T> = {} as CreateOptions<T>,\n ): Promise<CreateOutput> {\n const schema: T = getMain(ns)\n const record = schema.build(input) as TypedLexMap<NsidString>\n if (options?.validateRequest) schema.validate(record)\n const rkey = options.rkey ?? getDefaultRecordKey(schema)\n if (rkey !== undefined) schema.keySchema.assert(rkey)\n const response = await this.createRecord(record, rkey, options)\n return response.body\n }\n\n /**\n * Deletes a record with type-safe options.\n *\n * @param ns - The record schema definition\n * @param options - Delete options (rkey required for non-literal keys)\n * @returns The delete output\n */\n public async delete<const T extends RecordSchema>(\n ns: NonNullable<unknown> extends DeleteOptions<T>\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n ): Promise<DeleteOutput>\n public async delete<const T extends RecordSchema>(\n ns: Main<T>,\n options?: DeleteOptions<T>,\n ): Promise<DeleteOutput>\n public async delete<const T extends RecordSchema>(\n ns: Main<T>,\n options: DeleteOptions<T> = {} as DeleteOptions<T>,\n ): Promise<DeleteOutput> {\n const schema = getMain(ns)\n const rkey = schema.keySchema.parse(\n options.rkey ?? getLiteralRecordKey(schema),\n )\n const response = await this.deleteRecord(schema.$type, rkey, options)\n return response.body\n }\n\n /**\n * Retrieves a record with type-safe validation.\n *\n * @param ns - The record schema definition\n * @param options - Get options (rkey required for non-literal keys)\n * @returns The record data validated against the schema\n *\n * @example\n * ```typescript\n * const profile = await client.get(app.bsky.actor.profile.main)\n * // profile.value is typed as app.bsky.actor.profile.Record\n * console.log(profile.value.displayName)\n * ```\n */\n public async get<const T extends RecordSchema>(\n ns: T['key'] extends `literal:${string}`\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n ): Promise<GetOutput<T>>\n public async get<const T extends RecordSchema>(\n ns: Main<T>,\n options: GetOptions<T>,\n ): Promise<GetOutput<T>>\n public async get<const T extends RecordSchema>(\n ns: Main<T>,\n options: GetOptions<T> = {} as GetOptions<T>,\n ): Promise<GetOutput<T>> {\n const schema = getMain(ns)\n const rkey = schema.keySchema.parse(\n options.rkey ?? getLiteralRecordKey(schema),\n )\n const response = await this.getRecord(schema.$type, rkey, options)\n const value = schema.validate(response.body.value)\n return { ...response.body, value }\n }\n\n /**\n * Creates or updates a record with full type safety.\n *\n * @param ns - The record schema definition\n * @param input - The record data\n * @param options - Put options (rkey required for non-literal keys)\n * @returns The put output including URI and CID\n */\n public async put<const T extends RecordSchema>(\n ns: NonNullable<unknown> extends PutOptions<T>\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n input: Omit<Infer<T>, '$type'>,\n ): Promise<PutOutput>\n public async put<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: PutOptions<T>,\n ): Promise<PutOutput>\n public async put<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: PutOptions<T> = {} as PutOptions<T>,\n ): Promise<PutOutput> {\n const schema: T = getMain(ns)\n const record = schema.build(input) as TypedLexMap<NsidString>\n if (options?.validateRequest) schema.validate(record)\n const rkey = options.rkey ?? getLiteralRecordKey(schema)\n const response = await this.putRecord(record, rkey, options)\n return response.body\n }\n\n /**\n * Lists records with type-safe validation and separation of valid/invalid records.\n *\n * @param ns - The record schema definition\n * @param options - List options\n * @returns Records split into valid (matching schema) and invalid arrays\n *\n * @example\n * ```typescript\n * const result = await client.list(app.bsky.feed.post.main, { limit: 100 })\n * console.log(`Found ${result.records.length} valid posts`)\n * console.log(`Found ${result.invalid.length} invalid records`)\n * ```\n */\n async list<const T extends RecordSchema>(\n ns: Main<T>,\n options?: ListOptions,\n ): Promise<ListOutput<T>> {\n const schema = getMain(ns)\n const { body } = await this.listRecords(schema.$type, options)\n\n const records: ListRecord<Infer<T>>[] = []\n const invalid: LexMap[] = []\n\n for (const record of body.records) {\n const parsed = schema.safeValidate(record.value)\n if (parsed.success) {\n records.push({ ...record, value: parsed.value })\n } else {\n invalid.push(record.value)\n }\n }\n\n return { ...body, records, invalid }\n }\n}\n\nfunction getDefaultRecordKey<const T extends RecordSchema>(\n schema: T,\n): undefined | InferRecordKey<T> {\n // Let the server generate the TID\n if (schema.key === 'tid') return undefined\n if (schema.key === 'any') return undefined\n\n return getLiteralRecordKey(schema)\n}\n\nfunction getLiteralRecordKey<const T extends RecordSchema>(\n schema: T,\n): InferRecordKey<T> {\n if (schema.key.startsWith('literal:')) {\n return schema.key.slice(8) as InferRecordKey<T>\n }\n\n throw new TypeError(\n `An \"rkey\" must be provided for record key type \"${schema.key}\" (${schema.$type})`,\n )\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexMap, LexValue, TypedLexMap } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n CidString,\n DidString,\n Infer,\n InferMethodInputBody,\n InferMethodOutputBody,\n InferRecordKey,\n LexiconRecordKey,\n Main,\n NsidString,\n Params,\n Procedure,\n Query,\n RecordSchema,\n Restricted,\n getMain,\n} from '@atproto/lex-schema'\nimport { Agent, AgentOptions, buildAgent } from './agent.js'\nimport { XrpcFailure } from './errors.js'\nimport { com } from './lexicons/index.js'\nimport {\n XrpcResponse,\n XrpcResponseBody,\n XrpcResponseOptions,\n} from './response.js'\nimport { BinaryBodyInit, Service } from './types.js'\nimport {\n XrpcRequestHeadersOptions,\n applyDefaults,\n buildXrpcRequestHeaders,\n} from './util.js'\nimport {\n XrpcOptions,\n XrpcRequestParams,\n XrpcRequestProcessingOptions,\n xrpc,\n xrpcSafe,\n} from './xrpc.js'\n\nexport type {\n AtIdentifierString,\n CidString,\n DidString,\n Infer,\n InferMethodInputBody,\n InferMethodOutputBody,\n InferRecordKey,\n LexMap,\n LexValue,\n LexiconRecordKey,\n Main,\n NsidString,\n Params,\n Procedure,\n Query,\n RecordSchema,\n Restricted,\n TypedLexMap,\n}\n\n/**\n * Configuration options for creating a {@link Client}.\n *\n * @property {@link ClientOptions.labelers} - An iterable of labeler DIDs to include in requests. These will be combined with any global app labelers configured via {@link Client.configure}.\n * @property {@link ClientOptions.service} - An optional service identifier (DID or URL) for routing requests with service proxying.\n * @property {@link ClientOptions.headers} - Custom headers to include in all requests made by this client instance.\n * @property {@link ClientOptions.validateRequest} - If true, validates request bodies against their lexicon schemas before sending. Defaults to false for performance.\n * @property {@link ClientOptions.validateResponse} - If false, skips validation of response bodies against their lexicon schemas. Defaults to true to catch errors, but can be disabled for performance if you trust the server responses. Note that defaults will not be applied if validation is disabled, which can cause typing inconsistencies, so use with caution.\n * @property {@link ClientOptions.strictResponseProcessing} - If false, relaxes certain validation rules during response processing (e.g., allowing floats, deeper nesting, etc.). Defaults to true for strict compliance with {@link https://atproto.com/specs/data-model lexicon data model}, but can be disabled to handle non-compliant responses.\n *\n * @see {@link XrpcRequestHeadersOptions}\n * @see {@link XrpcRequestProcessingOptions}\n * @see {@link XrpcResponseOptions}\n *\n * @example\n * ```typescript\n * const options: ClientOptions = {\n * labelers: ['did:plc:labeler1'],\n * service: 'did:web:api.bsky.app#bsky_appview',\n * headers: { 'X-Custom-Header': 'value' },\n * validateRequest: false,\n * validateResponse: true,\n * strictResponseProcessing: false,\n * }\n * ```\n */\nexport type ClientOptions = XrpcRequestHeadersOptions &\n Pick<XrpcRequestProcessingOptions, 'validateRequest'> &\n XrpcResponseOptions\n\nexport type ActionOptions = {\n /** AbortSignal to cancel the request. */\n signal?: AbortSignal\n}\n\n/**\n * A composable action that can be invoked via {@link Client.call}.\n *\n * Actions provide a way to define custom operations that integrate with the\n * Client's call interface, enabling type-safe, reusable business logic.\n *\n * @typeParam I - The input type for the action\n * @typeParam O - The output type for the action\n *\n * @example\n * ```typescript\n * const myAction: Action<{ userId: string }, { profile: Profile }> = async (client, input, options) => {\n * const response = await client.xrpc(someMethod, { params: { actor: input.userId }, ...options })\n * return { profile: response.body }\n * }\n * ```\n */\nexport type Action<I = any, O = any> = (\n client: Client,\n input: I,\n options: ActionOptions,\n) => O | Promise<O>\n\n/**\n * Extracts the input type from an {@link Action}.\n * @typeParam A - The Action type to extract from\n */\nexport type InferActionInput<A extends Action> =\n A extends Action<infer I, any> ? I : never\n\n/**\n * Extracts the output type from an {@link Action}.\n * @typeParam A - The Action type to extract from\n */\nexport type InferActionOutput<A extends Action> =\n A extends Action<any, infer O> ? O : never\n\n/**\n * Options for creating a record in an AT Protocol repository.\n *\n * @see {@link Client.createRecord}\n */\nexport type CreateRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.createRecord.main>,\n 'body'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Compare-and-swap on the repo commit. If specified, must match current commit. */\n swapCommit?: string\n /** Whether to validate the record against its lexicon schema. */\n validate?: boolean\n}\n\n/**\n * Options for deleting a record from an AT Protocol repository.\n *\n * @see {@link Client.deleteRecord}\n */\nexport type DeleteRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.deleteRecord.main>,\n 'body'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Compare-and-swap on the repo commit. If specified, must match current commit. */\n swapCommit?: string\n /** Compare-and-swap on the record CID. If specified, must match current record. */\n swapRecord?: string\n}\n\n/**\n * Options for retrieving a record from an AT Protocol repository.\n *\n * @see {@link Client.getRecord}\n */\nexport type GetRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.getRecord.main>,\n 'params'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n}\n\n/**\n * Options for creating or updating a record in an AT Protocol repository.\n *\n * @see {@link Client.putRecord}\n */\nexport type PutRecordOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.putRecord.main>,\n 'body'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Compare-and-swap on the repo commit. If specified, must match current commit. */\n swapCommit?: string\n /** Compare-and-swap on the record CID. If specified, must match current record. */\n swapRecord?: string\n /** Whether to validate the record against its lexicon schema. */\n validate?: boolean\n}\n\n/**\n * Options for listing records in an AT Protocol repository collection.\n *\n * @see {@link Client.listRecords}\n */\nexport type ListRecordsOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.listRecords.main>,\n 'params'\n> & {\n /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */\n repo?: AtIdentifierString\n /** Maximum number of records to return. */\n limit?: number\n /** Pagination cursor from a previous response. */\n cursor?: string\n /** If true, returns records in reverse chronological order. */\n reverse?: boolean\n}\n\nexport type UploadBlobOptions = Omit<\n XrpcOptions<typeof com.atproto.repo.uploadBlob.main>,\n 'body'\n>\n\nexport type GetBlobOptions = Omit<\n XrpcOptions<typeof com.atproto.sync.getBlob.main>,\n 'params'\n>\n\nexport type RecordKeyOptions<\n T extends RecordSchema,\n AlsoOptionalWhenRecordKeyIs extends LexiconRecordKey = never,\n> = T['key'] extends `literal:${string}` | AlsoOptionalWhenRecordKeyIs\n ? { rkey?: InferRecordKey<T> }\n : { rkey: InferRecordKey<T> }\n\n/**\n * Type-safe options for {@link Client.create}, combining record options with key requirements.\n * @typeParam T - The record schema type\n * @see {@link CreateRecordOptions}\n */\nexport type CreateOptions<T extends RecordSchema> = CreateRecordOptions &\n RecordKeyOptions<T, 'tid' | 'any'>\n\n/**\n * Output type for record creation operations.\n * Contains the URI and CID of the newly created record.\n */\nexport type CreateOutput = InferMethodOutputBody<\n typeof com.atproto.repo.createRecord.main,\n Uint8Array\n>\n\n/**\n * Type-safe options for {@link Client.delete}, combining delete options with key requirements.\n * @typeParam T - The record schema type\n */\nexport type DeleteOptions<T extends RecordSchema> = DeleteRecordOptions &\n RecordKeyOptions<T>\n\n/**\n * Output type for record deletion operations.\n */\nexport type DeleteOutput = InferMethodOutputBody<\n typeof com.atproto.repo.deleteRecord.main,\n Uint8Array\n>\n\n/**\n * Type-safe options for {@link Client.get}, combining get options with key requirements.\n * @typeParam T - The record schema type\n */\nexport type GetOptions<T extends RecordSchema> = GetRecordOptions &\n RecordKeyOptions<T>\n\n/**\n * Output type for record retrieval operations.\n * Contains the record value validated against the schema type.\n * @typeParam T - The record schema type\n */\nexport type GetOutput<T extends RecordSchema> = Omit<\n InferMethodOutputBody<typeof com.atproto.repo.getRecord.main, Uint8Array>,\n 'value'\n> & { value: Infer<T> }\n\n/**\n * Type-safe options for {@link Client.put}, combining put options with key requirements.\n * @typeParam T - The record schema type\n */\nexport type PutOptions<T extends RecordSchema> = PutRecordOptions &\n RecordKeyOptions<T>\n\n/**\n * Output type for record put (create/update) operations.\n * Contains the URI and CID of the record.\n */\nexport type PutOutput = InferMethodOutputBody<\n typeof com.atproto.repo.putRecord.main,\n Uint8Array\n>\n\n/**\n * Options for {@link Client.list} operations.\n */\nexport type ListOptions = ListRecordsOptions\n\n/**\n * Output type for record listing operations.\n * Contains validated records and any invalid records that failed schema validation.\n * @typeParam T - The record schema type\n */\nexport type ListOutput<T extends RecordSchema> = InferMethodOutputBody<\n typeof com.atproto.repo.listRecords.main,\n Uint8Array\n> & {\n /** Records that successfully validated against the schema. */\n records: ListRecord<Infer<T>>[]\n // @NOTE Because the schema uses \"type\": \"unknown\" instead of an open union,\n // we have to use LexMap instead of Unknown$TypedObject here, which is\n // unfortunate.\n /** Records that failed schema validation. */\n invalid: LexMap[]\n}\n\n/**\n * A record from a list operation with its value typed to the schema.\n * @typeParam Value - The validated record value type\n */\nexport type ListRecord<Value extends LexMap> =\n com.atproto.repo.listRecords.Record & {\n value: Value\n }\n\n/**\n * The Client class is the primary interface for interacting with AT Protocol\n * services. It provides type-safe methods for XRPC calls, record operations,\n * and blob handling.\n *\n * @example\n * ```typescript\n * import { Client } from '@atproto/lex'\n * import { app } from '#/lexicons\n *\n * const client = new Client(oauthSession)\n *\n * const response = await client.xrpc(app.bsky.feed.getTimeline.main, {\n * params: { limit: 50 }\n * })\n * ```\n */\nexport class Client implements Agent {\n static appLabelers: readonly DidString[] = []\n\n /**\n * Configures the Client (or its sub classes) globally.\n */\n static configure(opts: { appLabelers?: Iterable<DidString> }) {\n if (opts.appLabelers) this.appLabelers = [...opts.appLabelers]\n }\n\n /** The underlying agent used for making requests. */\n public readonly agent: Agent\n\n /** Custom headers included in all requests. */\n public readonly headers: Headers\n\n /** Optional service identifier for routing requests. */\n public readonly service?: Service\n\n /** Set of labeler DIDs specific to this client instance. */\n public readonly labelers: Set<DidString>\n\n public readonly xrpcDefaults: {\n readonly validateRequest: boolean\n readonly validateResponse: boolean\n readonly strictResponseProcessing: boolean\n }\n\n constructor(agent: Agent | AgentOptions, options: ClientOptions = {}) {\n this.agent = buildAgent(agent)\n this.service = options.service\n this.labelers = new Set(options.labelers)\n this.headers = new Headers(options.headers)\n this.xrpcDefaults = Object.freeze({\n validateRequest: options.validateRequest ?? false,\n validateResponse: options.validateResponse ?? true,\n strictResponseProcessing: options.strictResponseProcessing ?? true,\n })\n }\n\n /**\n * The DID of the authenticated user, or `undefined` if not authenticated.\n */\n get did(): DidString | undefined {\n return this.agent.did\n }\n\n /**\n * The DID of the authenticated user.\n * @throws {Error} if not authenticated\n */\n get assertDid(): DidString {\n this.assertAuthenticated()\n return this.did\n }\n\n /**\n * Asserts that the client is authenticated.\n * Use as a type guard when you need to ensure authentication.\n *\n * @throws {Error} if not authenticated\n *\n * @example\n * ```typescript\n * client.assertAuthenticated()\n * // TypeScript now knows client.did is defined\n * console.log(client.did)\n * ```\n */\n public assertAuthenticated(): asserts this is { did: DidString } {\n if (!this.did) throw new Error('Client is not authenticated')\n }\n\n /**\n * Replaces all labelers with the given set.\n * @param labelers - Iterable of labeler DIDs\n */\n public setLabelers(labelers: Iterable<DidString> = []) {\n this.clearLabelers()\n this.addLabelers(labelers)\n }\n\n /**\n * Adds labelers to the current set.\n * @param labelers - Iterable of labeler DIDs to add\n */\n public addLabelers(labelers: Iterable<DidString>) {\n for (const labeler of labelers) this.labelers.add(labeler)\n }\n\n /**\n * Removes all labelers from this client instance.\n */\n public clearLabelers() {\n this.labelers.clear()\n }\n\n /**\n * {@link Agent}'s {@link Agent.fetchHandler} implementation, which adds\n * labelers and service proxying headers. This method allow a {@link Client}\n * instance to be used directly as an {@link Agent} for another\n * {@link Client}, enabling composition of headers (labelers, proxying, etc.).\n *\n * @param path - The request path\n * @param init - Request initialization options\n */\n public fetchHandler(\n path: `/${string}`,\n init: RequestInit,\n ): Promise<Response> {\n const headers = buildXrpcRequestHeaders({\n headers: init.headers,\n service: this.service,\n labelers: [\n ...(this.constructor as typeof Client).appLabelers.map(\n (l) => `${l};redact` as const,\n ),\n ...this.labelers,\n ],\n })\n\n // Incoming headers take precedence\n for (const [key, value] of this.headers) {\n if (!headers.has(key)) headers.set(key, value)\n }\n\n // @NOTE The agent here could be another Client instance.\n return this.agent.fetchHandler(path, { ...init, headers })\n }\n\n /**\n * Makes an XRPC request. Throws on failure.\n *\n * @param ns - The lexicon method definition (e.g., `app.bsky.feed.getTimeline`)\n * @param options - Request options including params and body\n * @returns The successful XRPC response\n * @throws {XrpcFailure} when the request fails or returns an error\n *\n * @example Query with parameters\n * ```typescript\n * const response = await client.xrpc(app.bsky.feed.getTimeline, {\n * params: { limit: 50, cursor: 'abc123' }\n * })\n * console.log(response.body.feed)\n * ```\n *\n * @example Procedure with body\n * ```typescript\n * const response = await client.xrpc(com.atproto.repo.createRecord, {\n * body: {\n * repo: client.assertDid,\n * collection: 'app.bsky.feed.post',\n * record: { text: 'Hello!', createdAt: new Date().toISOString() }\n * }\n * })\n * ```\n *\n * @see {@link xrpcSafe} for a non-throwing variant\n */\n async xrpc<const M extends Query | Procedure>(\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n ): Promise<XrpcResponse<M>>\n async xrpc<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M>,\n ): Promise<XrpcResponse<M>>\n async xrpc<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n ): Promise<XrpcResponse<M>> {\n return xrpc(this, ns, applyDefaults(options, this.xrpcDefaults))\n }\n\n /**\n * Makes an XRPC request without throwing on failure.\n * Returns either a successful response or a failure object.\n *\n * @param ns - The lexicon method definition\n * @param options - Request options\n * @returns Either an XrpcResponse on success or XrpcFailure on failure\n *\n * @example\n * ```typescript\n * const result = await client.xrpcSafe(app.bsky.actor.getProfile.main, {\n * params: { actor: 'alice.bsky.social' }\n * })\n *\n * if (result.success) {\n * console.log(result.body.displayName)\n * } else {\n * console.error('Failed:', result.error)\n * }\n * ```\n *\n * @see {@link xrpc} for a throwing variant\n */\n async xrpcSafe<const M extends Query | Procedure>(\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n ): Promise<XrpcResponse<M> | XrpcFailure<M>>\n async xrpcSafe<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M>,\n ): Promise<XrpcResponse<M> | XrpcFailure<M>>\n async xrpcSafe<const M extends Query | Procedure>(\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n ): Promise<XrpcResponse<M> | XrpcFailure<M>> {\n return xrpcSafe(this, ns, applyDefaults(options, this.xrpcDefaults))\n }\n\n /**\n * Creates a new record in an AT Protocol repository.\n *\n * @param record - The record to create, must include an {@link NsidString} `$type`\n * @param rkey - Optional record key; if omitted, server generates a TID\n * @param options - Create options including repo, swapCommit, validate\n * @returns The XRPC response containing the created record's URI and CID\n *\n * @example\n * ```typescript\n * const response = await client.createRecord(\n * { $type: 'app.bsky.feed.post', text: 'Hello!', createdAt: new Date().toISOString() },\n * undefined, // Let server generate rkey\n * { validate: true }\n * )\n * console.log(response.body.uri)\n * ```\n *\n * @see {@link create} for a higher-level typed alternative\n */\n public async createRecord(\n record: TypedLexMap<NsidString>,\n rkey?: string,\n options?: CreateRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.createRecord.main, {\n ...options,\n body: {\n repo: options?.repo ?? this.assertDid,\n collection: record.$type,\n record,\n rkey,\n validate: options?.validate,\n swapCommit: options?.swapCommit,\n },\n })\n }\n\n /**\n * Deletes a record from an AT Protocol repository.\n *\n * @param collection - The collection NSID\n * @param rkey - The record key\n * @param options - Delete options including repo, swapCommit, swapRecord\n *\n * @see {@link delete} for a higher-level typed alternative\n */\n async deleteRecord(\n collection: NsidString,\n rkey: string,\n options?: DeleteRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.deleteRecord.main, {\n ...options,\n body: {\n repo: options?.repo ?? this.assertDid,\n collection,\n rkey,\n swapCommit: options?.swapCommit,\n swapRecord: options?.swapRecord,\n },\n })\n }\n\n /**\n * Retrieves a record from an AT Protocol repository.\n *\n * @param collection - The collection NSID\n * @param rkey - The record key\n * @param options - Get options including repo\n *\n * @see {@link get} for a higher-level typed alternative\n */\n public async getRecord(\n collection: NsidString,\n rkey: string,\n options?: GetRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.getRecord.main, {\n ...options,\n params: {\n repo: options?.repo ?? this.assertDid,\n collection,\n rkey,\n },\n })\n }\n\n /**\n * Creates or updates a record in a repository.\n *\n * @param record - The record to put, must include an {@link NsidString} `$type`\n * @param rkey - The record key\n * @param options - Put options including repo, swapCommit, swapRecord, validate\n *\n * @see {@link put} for a higher-level typed alternative\n */\n async putRecord(\n record: TypedLexMap<NsidString>,\n rkey: string,\n options?: PutRecordOptions,\n ) {\n return this.xrpc(com.atproto.repo.putRecord.main, {\n ...options,\n body: {\n repo: options?.repo ?? this.assertDid,\n collection: record.$type,\n rkey,\n record,\n validate: options?.validate,\n swapCommit: options?.swapCommit,\n swapRecord: options?.swapRecord,\n },\n })\n }\n\n /**\n * Lists records in a collection.\n *\n * @param nsid - The collection NSID\n * @param options - List options including repo, limit, cursor, reverse\n *\n * @see {@link list} for a higher-level typed alternative\n */\n async listRecords(nsid: NsidString, options?: ListRecordsOptions) {\n return this.xrpc(com.atproto.repo.listRecords.main, {\n ...options,\n params: {\n repo: options?.repo ?? this.assertDid,\n collection: nsid,\n cursor: options?.cursor,\n limit: options?.limit,\n reverse: options?.reverse,\n },\n })\n }\n\n /**\n * Uploads a blob to an AT Protocol repository.\n *\n * @param body - The blob data (Uint8Array, ReadableStream, Blob, etc.)\n * @param options - Upload options including encoding hint\n * @returns Response containing the blob reference\n *\n * @example\n * ```typescript\n * const imageData = await fetch('image.png').then(r => r.arrayBuffer())\n * const response = await client.uploadBlob(new Uint8Array(imageData), {\n * encoding: 'image/png'\n * })\n * console.log(response.body.blob) // Use this ref in records\n * ```\n */\n async uploadBlob(body: BinaryBodyInit, options?: UploadBlobOptions) {\n return this.xrpc(com.atproto.repo.uploadBlob.main, { ...options, body })\n }\n\n /**\n * Retrieves a blob by DID and CID.\n *\n * @param did - The DID of the repository containing the blob\n * @param cid - The CID of the blob\n * @param options - Call options\n */\n async getBlob(did: DidString, cid: CidString, options?: GetBlobOptions) {\n return this.xrpc(com.atproto.sync.getBlob.main, {\n ...options,\n params: { did, cid },\n })\n }\n\n /**\n * Universal call method for queries, procedures, and custom actions.\n * Automatically determines the call type based on the lexicon definition.\n *\n * @param ns - The lexicon method or action definition\n * @param arg - The input argument (params for queries, body for procedures, input for actions)\n * @param options - Call options\n * @returns The method response body or action output\n * @see {@link xrpc} if you need access to the full response object\n *\n * @example Query\n * ```typescript\n * const profile = await client.call(app.bsky.actor.getProfile.main, {\n * actor: 'alice.bsky.social'\n * })\n * ```\n *\n * @example Procedure\n * ```typescript\n * const result = await client.call(com.atproto.repo.createRecord.main, {\n * repo: did,\n * collection: 'app.bsky.feed.post',\n * record: { text: 'Hello!' }\n * })\n * ```\n */\n public async call<const T extends Query>(\n ns: NonNullable<unknown> extends XrpcRequestParams<T>\n ? Main<T>\n : Restricted<'This query type requires a \"params\" argument'>,\n ): Promise<XrpcResponseBody<T>>\n public async call<const T extends Procedure>(\n ns: undefined extends InferMethodInputBody<T, Uint8Array>\n ? Main<T>\n : Restricted<'This procedure type requires an \"input\" argument'>,\n ): Promise<XrpcResponseBody<T>>\n public async call<const T extends Action>(\n ns: void extends InferActionInput<T>\n ? Main<T>\n : Restricted<'This action type requires an \"input\" argument'>,\n ): Promise<InferActionOutput<T>>\n public async call<const T extends Action | Procedure | Query>(\n ns: Main<T>,\n arg: T extends Action\n ? InferActionInput<T>\n : T extends Procedure\n ? InferMethodInputBody<T, Uint8Array>\n : T extends Query\n ? XrpcRequestParams<T>\n : never,\n options?: T extends Action\n ? ActionOptions\n : T extends Procedure\n ? Omit<XrpcOptions<T>, 'body'>\n : T extends Query\n ? Omit<XrpcOptions<T>, 'params'>\n : never,\n ): Promise<\n T extends Action\n ? InferActionOutput<T>\n : T extends Procedure\n ? XrpcResponseBody<T>\n : T extends Query\n ? XrpcResponseBody<T>\n : never\n >\n public async call(\n ns: Main<Action> | Main<Procedure> | Main<Query>,\n arg?: LexValue | Params,\n options: ActionOptions = {},\n ): Promise<unknown> {\n const method = getMain(ns)\n\n if (typeof method === 'function') {\n return method(this, arg, options)\n }\n\n if (method instanceof Procedure) {\n const result = await this.xrpc(method, { ...options, body: arg as any })\n return result.body\n } else if (method instanceof Query) {\n const result = await this.xrpc(method, { ...options, params: arg as any })\n return result.body\n } else {\n throw new TypeError('Invalid lexicon')\n }\n }\n\n /**\n * Creates a new record with full type safety based on the schema.\n *\n * @param ns - The record schema definition\n * @param input - The record data (without `$type`, which is added automatically)\n * @param options - Create options including rkey (required for some record types)\n * @returns The create output including URI and CID\n *\n * @example Creating a post\n * ```typescript\n * const result = await client.create(app.bsky.feed.post.main, {\n * text: 'Hello, world!',\n * createdAt: new Date().toISOString()\n * })\n * console.log(result.uri)\n * ```\n *\n * @example Creating a record with explicit rkey\n * ```typescript\n * const result = await client.create(app.bsky.actor.profile.main, {\n * displayName: 'Alice'\n * }, { rkey: 'self' })\n * ```\n */\n public async create<const T extends RecordSchema>(\n ns: NonNullable<unknown> extends CreateOptions<T>\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n input: Omit<Infer<T>, '$type'>,\n ): Promise<CreateOutput>\n public async create<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: CreateOptions<T>,\n ): Promise<CreateOutput>\n public async create<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: CreateOptions<T> = {} as CreateOptions<T>,\n ): Promise<CreateOutput> {\n const schema: T = getMain(ns)\n const record = schema.build(input) as TypedLexMap<NsidString>\n if (options?.validateRequest) schema.validate(record)\n const rkey = options.rkey ?? getDefaultRecordKey(schema)\n if (rkey !== undefined) schema.keySchema.assert(rkey)\n const response = await this.createRecord(record, rkey, options)\n return response.body\n }\n\n /**\n * Deletes a record with type-safe options.\n *\n * @param ns - The record schema definition\n * @param options - Delete options (rkey required for non-literal keys)\n * @returns The delete output\n */\n public async delete<const T extends RecordSchema>(\n ns: NonNullable<unknown> extends DeleteOptions<T>\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n ): Promise<DeleteOutput>\n public async delete<const T extends RecordSchema>(\n ns: Main<T>,\n options?: DeleteOptions<T>,\n ): Promise<DeleteOutput>\n public async delete<const T extends RecordSchema>(\n ns: Main<T>,\n options: DeleteOptions<T> = {} as DeleteOptions<T>,\n ): Promise<DeleteOutput> {\n const schema = getMain(ns)\n const rkey = schema.keySchema.parse(\n options.rkey ?? getLiteralRecordKey(schema),\n )\n const response = await this.deleteRecord(schema.$type, rkey, options)\n return response.body\n }\n\n /**\n * Retrieves a record with type-safe validation.\n *\n * @param ns - The record schema definition\n * @param options - Get options (rkey required for non-literal keys)\n * @returns The record data validated against the schema\n *\n * @example\n * ```typescript\n * const profile = await client.get(app.bsky.actor.profile.main)\n * // profile.value is typed as app.bsky.actor.profile.Record\n * console.log(profile.value.displayName)\n * ```\n */\n public async get<const T extends RecordSchema>(\n ns: T['key'] extends `literal:${string}`\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n ): Promise<GetOutput<T>>\n public async get<const T extends RecordSchema>(\n ns: Main<T>,\n options: GetOptions<T>,\n ): Promise<GetOutput<T>>\n public async get<const T extends RecordSchema>(\n ns: Main<T>,\n options: GetOptions<T> = {} as GetOptions<T>,\n ): Promise<GetOutput<T>> {\n const schema = getMain(ns)\n const rkey = schema.keySchema.parse(\n options.rkey ?? getLiteralRecordKey(schema),\n )\n const response = await this.getRecord(schema.$type, rkey, options)\n const value = schema.validate(response.body.value)\n return { ...response.body, value }\n }\n\n /**\n * Creates or updates a record with full type safety.\n *\n * @param ns - The record schema definition\n * @param input - The record data\n * @param options - Put options (rkey required for non-literal keys)\n * @returns The put output including URI and CID\n */\n public async put<const T extends RecordSchema>(\n ns: NonNullable<unknown> extends PutOptions<T>\n ? Main<T>\n : Restricted<'This record type requires an \"options\" argument'>,\n input: Omit<Infer<T>, '$type'>,\n ): Promise<PutOutput>\n public async put<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: PutOptions<T>,\n ): Promise<PutOutput>\n public async put<const T extends RecordSchema>(\n ns: Main<T>,\n input: Omit<Infer<T>, '$type'>,\n options: PutOptions<T> = {} as PutOptions<T>,\n ): Promise<PutOutput> {\n const schema: T = getMain(ns)\n const record = schema.build(input) as TypedLexMap<NsidString>\n if (options?.validateRequest) schema.validate(record)\n const rkey = options.rkey ?? getLiteralRecordKey(schema)\n const response = await this.putRecord(record, rkey, options)\n return response.body\n }\n\n /**\n * Lists records with type-safe validation and separation of valid/invalid records.\n *\n * @param ns - The record schema definition\n * @param options - List options\n * @returns Records split into valid (matching schema) and invalid arrays\n *\n * @example\n * ```typescript\n * const result = await client.list(app.bsky.feed.post.main, { limit: 100 })\n * console.log(`Found ${result.records.length} valid posts`)\n * console.log(`Found ${result.invalid.length} invalid records`)\n * ```\n */\n async list<const T extends RecordSchema>(\n ns: Main<T>,\n options?: ListOptions,\n ): Promise<ListOutput<T>> {\n const schema = getMain(ns)\n const { body } = await this.listRecords(schema.$type, options)\n\n const records: ListRecord<Infer<T>>[] = []\n const invalid: LexMap[] = []\n\n for (const record of body.records) {\n const parsed = schema.safeValidate(record.value)\n if (parsed.success) {\n records.push({ ...record, value: parsed.value })\n } else {\n invalid.push(record.value)\n }\n }\n\n return { ...body, records, invalid }\n }\n}\n\nfunction getDefaultRecordKey<const T extends RecordSchema>(\n schema: T,\n): undefined | InferRecordKey<T> {\n // Let the server generate the TID\n if (schema.key === 'tid') return undefined\n if (schema.key === 'any') return undefined\n\n return getLiteralRecordKey(schema)\n}\n\nfunction getLiteralRecordKey<const T extends RecordSchema>(\n schema: T,\n): InferRecordKey<T> {\n if (schema.key.startsWith('literal:')) {\n return schema.key.slice(8) as InferRecordKey<T>\n }\n\n throw new TypeError(\n `An \"rkey\" must be provided for record key type \"${schema.key}\" (${schema.$type})`,\n )\n}\n"]}