@atproto/lex-client 0.1.0 → 0.1.2

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 (115) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/client.d.ts +79 -25
  3. package/dist/client.d.ts.map +1 -1
  4. package/dist/client.js +56 -24
  5. package/dist/client.js.map +1 -1
  6. package/dist/lexicons/com/atproto/repo/applyWrites.d.ts +3 -0
  7. package/dist/lexicons/com/atproto/repo/applyWrites.d.ts.map +1 -0
  8. package/dist/lexicons/com/atproto/repo/applyWrites.defs.d.ts +100 -0
  9. package/dist/lexicons/com/atproto/repo/applyWrites.defs.d.ts.map +1 -0
  10. package/dist/lexicons/com/atproto/repo/applyWrites.defs.js +81 -0
  11. package/dist/lexicons/com/atproto/repo/applyWrites.defs.js.map +1 -0
  12. package/dist/lexicons/com/atproto/repo/applyWrites.js +6 -0
  13. package/dist/lexicons/com/atproto/repo/applyWrites.js.map +1 -0
  14. package/dist/lexicons/com/atproto/repo/createRecord.d.ts +1 -1
  15. package/dist/lexicons/com/atproto/repo/createRecord.d.ts.map +1 -1
  16. package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts +16 -13
  17. package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts.map +1 -1
  18. package/dist/lexicons/com/atproto/repo/createRecord.defs.js +10 -10
  19. package/dist/lexicons/com/atproto/repo/createRecord.defs.js.map +1 -1
  20. package/dist/lexicons/com/atproto/repo/createRecord.js +1 -1
  21. package/dist/lexicons/com/atproto/repo/createRecord.js.map +1 -1
  22. package/dist/lexicons/com/atproto/repo/defs.d.ts +0 -1
  23. package/dist/lexicons/com/atproto/repo/defs.d.ts.map +1 -1
  24. package/dist/lexicons/com/atproto/repo/defs.js +0 -1
  25. package/dist/lexicons/com/atproto/repo/defs.js.map +1 -1
  26. package/dist/lexicons/com/atproto/repo/deleteRecord.d.ts +1 -1
  27. package/dist/lexicons/com/atproto/repo/deleteRecord.d.ts.map +1 -1
  28. package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts +16 -13
  29. package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts.map +1 -1
  30. package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js +10 -10
  31. package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js.map +1 -1
  32. package/dist/lexicons/com/atproto/repo/deleteRecord.js +1 -1
  33. package/dist/lexicons/com/atproto/repo/deleteRecord.js.map +1 -1
  34. package/dist/lexicons/com/atproto/repo/getRecord.d.ts +1 -1
  35. package/dist/lexicons/com/atproto/repo/getRecord.d.ts.map +1 -1
  36. package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts +13 -11
  37. package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts.map +1 -1
  38. package/dist/lexicons/com/atproto/repo/getRecord.defs.js +7 -9
  39. package/dist/lexicons/com/atproto/repo/getRecord.defs.js.map +1 -1
  40. package/dist/lexicons/com/atproto/repo/getRecord.js +1 -1
  41. package/dist/lexicons/com/atproto/repo/getRecord.js.map +1 -1
  42. package/dist/lexicons/com/atproto/repo/listRecords.d.ts +1 -1
  43. package/dist/lexicons/com/atproto/repo/listRecords.d.ts.map +1 -1
  44. package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts +13 -11
  45. package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts.map +1 -1
  46. package/dist/lexicons/com/atproto/repo/listRecords.defs.js +7 -9
  47. package/dist/lexicons/com/atproto/repo/listRecords.defs.js.map +1 -1
  48. package/dist/lexicons/com/atproto/repo/listRecords.js +1 -1
  49. package/dist/lexicons/com/atproto/repo/listRecords.js.map +1 -1
  50. package/dist/lexicons/com/atproto/repo/putRecord.d.ts +1 -1
  51. package/dist/lexicons/com/atproto/repo/putRecord.d.ts.map +1 -1
  52. package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts +16 -13
  53. package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts.map +1 -1
  54. package/dist/lexicons/com/atproto/repo/putRecord.defs.js +10 -10
  55. package/dist/lexicons/com/atproto/repo/putRecord.defs.js.map +1 -1
  56. package/dist/lexicons/com/atproto/repo/putRecord.js +1 -1
  57. package/dist/lexicons/com/atproto/repo/putRecord.js.map +1 -1
  58. package/dist/lexicons/com/atproto/repo/uploadBlob.d.ts +1 -1
  59. package/dist/lexicons/com/atproto/repo/uploadBlob.d.ts.map +1 -1
  60. package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +11 -8
  61. package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts.map +1 -1
  62. package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js +7 -7
  63. package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
  64. package/dist/lexicons/com/atproto/repo/uploadBlob.js +1 -1
  65. package/dist/lexicons/com/atproto/repo/uploadBlob.js.map +1 -1
  66. package/dist/lexicons/com/atproto/repo.d.ts +2 -1
  67. package/dist/lexicons/com/atproto/repo.d.ts.map +1 -1
  68. package/dist/lexicons/com/atproto/repo.js +2 -1
  69. package/dist/lexicons/com/atproto/repo.js.map +1 -1
  70. package/dist/lexicons/com/atproto/sync/getBlob.d.ts +1 -1
  71. package/dist/lexicons/com/atproto/sync/getBlob.d.ts.map +1 -1
  72. package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts +11 -9
  73. package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts.map +1 -1
  74. package/dist/lexicons/com/atproto/sync/getBlob.defs.js +6 -8
  75. package/dist/lexicons/com/atproto/sync/getBlob.defs.js.map +1 -1
  76. package/dist/lexicons/com/atproto/sync/getBlob.js +1 -1
  77. package/dist/lexicons/com/atproto/sync/getBlob.js.map +1 -1
  78. package/dist/types.d.ts +2 -6
  79. package/dist/types.d.ts.map +1 -1
  80. package/dist/types.js.map +1 -1
  81. package/dist/util.d.ts +9 -0
  82. package/dist/util.d.ts.map +1 -1
  83. package/dist/util.js +23 -0
  84. package/dist/util.js.map +1 -1
  85. package/dist/write-operation-builder.d.ts +19 -0
  86. package/dist/write-operation-builder.d.ts.map +1 -0
  87. package/dist/write-operation-builder.js +35 -0
  88. package/dist/write-operation-builder.js.map +1 -0
  89. package/dist/xrpc.d.ts.map +1 -1
  90. package/dist/xrpc.js +5 -2
  91. package/dist/xrpc.js.map +1 -1
  92. package/package.json +4 -4
  93. package/src/client.ts +122 -82
  94. package/src/lexicons/com/atproto/repo/applyWrites.defs.ts +201 -0
  95. package/src/lexicons/com/atproto/repo/applyWrites.ts +6 -0
  96. package/src/lexicons/com/atproto/repo/createRecord.defs.ts +43 -46
  97. package/src/lexicons/com/atproto/repo/createRecord.ts +1 -1
  98. package/src/lexicons/com/atproto/repo/defs.ts +0 -1
  99. package/src/lexicons/com/atproto/repo/deleteRecord.defs.ts +37 -40
  100. package/src/lexicons/com/atproto/repo/deleteRecord.ts +1 -1
  101. package/src/lexicons/com/atproto/repo/getRecord.defs.ts +23 -26
  102. package/src/lexicons/com/atproto/repo/getRecord.ts +1 -1
  103. package/src/lexicons/com/atproto/repo/listRecords.defs.ts +30 -32
  104. package/src/lexicons/com/atproto/repo/listRecords.ts +1 -1
  105. package/src/lexicons/com/atproto/repo/putRecord.defs.ts +44 -47
  106. package/src/lexicons/com/atproto/repo/putRecord.ts +1 -1
  107. package/src/lexicons/com/atproto/repo/uploadBlob.defs.ts +21 -23
  108. package/src/lexicons/com/atproto/repo/uploadBlob.ts +1 -1
  109. package/src/lexicons/com/atproto/repo.ts +2 -1
  110. package/src/lexicons/com/atproto/sync/getBlob.defs.ts +23 -26
  111. package/src/lexicons/com/atproto/sync/getBlob.ts +1 -1
  112. package/src/types.ts +6 -10
  113. package/src/util.ts +48 -1
  114. package/src/write-operation-builder.ts +110 -0
  115. package/src/xrpc.ts +5 -5
package/dist/xrpc.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"xrpc.js","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexValue, isLexScalar, isPlainObject } from '@atproto/lex-data'\nimport { lexStringify } from '@atproto/lex-json'\nimport {\n InferInput,\n InferPayload,\n Main,\n NsidString,\n Params,\n Payload,\n Procedure,\n Query,\n Restricted,\n Subscription,\n getMain,\n} from '@atproto/lex-schema'\nimport { Agent, AgentOptions, buildAgent } from './agent.js'\nimport { XrpcFailure, XrpcFetchError, asXrpcFailure } from './errors.js'\nimport { XrpcResponse, XrpcResponseOptions } from './response.js'\nimport { BinaryBodyInit } from './types.js'\nimport {\n XrpcRequestHeadersOptions,\n buildXrpcRequestHeaders,\n isAsyncIterable,\n isBlobLike,\n toReadableStream,\n} from './util.js'\n\n/**\n * The query/path parameters type for an XRPC method, inferred from its schema.\n *\n * @typeParam M - The XRPC method type (Procedure, Query, or Subscription)\n */\nexport type XrpcRequestParams<M extends Procedure | Query | Subscription> =\n InferInput<M['parameters']>\n\n// If all params are optional, allow omitting the params object\ntype XrpcRequestParamsOptions<P extends Params> =\n NonNullable<unknown> extends P ? { params?: P } : { params: P }\n\ntype XrpcRequestPayload<M extends Procedure | Query> = M extends Procedure\n ? InferPayload<M['input'], BinaryBodyInit>\n : undefined\n\ntype XrpcRequestPayloadOptions<TPayload> = TPayload extends {\n body: infer B\n encoding: infer E\n}\n ? {\n body: B\n\n /**\n * mime type hint for binary bodies\n *\n * Only needed for endpoints that accept binary input (e.g. file uploads)\n * when the body is a Blob-like object without a type (e.g. fetch-blob's\n * Blob). If the body is a Blob-like object with a type, that type will be\n * used as the content-type header instead of this option.\n *\n * @default \"application/octet-stream\"\n */\n encoding?: E\n }\n : { body?: undefined; encoding?: undefined }\n\n/**\n * Options for making an XRPC request, based on the method schema.\n *\n * Combines {@link XrpcRequestOptions} and {@link XrpcResponseOptions} with\n * method-specific params and body requirements. The type system ensures\n * required params/body are provided based on the method schema.\n *\n * @typeParam M - The XRPC method type (Procedure or Query)\n *\n * @example Query with params\n * ```typescript\n * const options: XrpcOptions<typeof app.bsky.feed.getTimeline.main> = {\n * params: { limit: 50 }\n * }\n * ```\n *\n * @example Procedure with body\n * ```typescript\n * const options: XrpcOptions<typeof com.atproto.repo.createRecord.main> = {\n * body: { repo: did, collection: 'app.bsky.feed.post', record: { ... } }\n * }\n * ```\n */\nexport type XrpcOptions<M extends Procedure | Query = Procedure | Query> =\n XrpcRequestOptions<M> & XrpcResponseOptions\n\nexport type XrpcRequestOptions<\n M extends Procedure | Query = Procedure | Query,\n> = XrpcRequestProcessingOptions &\n XrpcRequestHeadersOptions &\n XrpcRequestPayloadOptions<XrpcRequestPayload<M>> &\n XrpcRequestParamsOptions<XrpcRequestParams<M>>\n\nexport type XrpcRequestProcessingOptions = {\n /**\n * AbortSignal to cancel the request.\n */\n signal?: AbortSignal\n\n /**\n * Whether to validate the request against the method's input schema. Enabling\n * this can help catch errors early but may have a performance cost. This\n * would typically only be set to `true` in development or debugging\n * scenarios.\n *\n * @default false\n */\n validateRequest?: boolean\n}\n\n/**\n * Makes an XRPC request and throws on failure.\n *\n * This is the low-level function for making XRPC calls.\n *\n * @param agent - The {@link Agent} to use for making the request\n * @param ns - The lexicon method definition\n * @param options - Request {@link XrpcOptions options} (params, body, headers, etc.)\n * @returns The successful {@link XrpcResponse}\n * @throws {XrpcFailure} When the request fails\n *\n * @example\n * ```typescript\n * const response = await xrpc('https://bsky.network', com.atproto.identity.resolveHandle, {\n * params: { handle: \"atproto.com\" }\n * })\n * ```\n *\n * @example\n * ```typescript\n * const response = await xrpc(agent, app.bsky.feed.getTimeline.main, {\n * params: { limit: 50 }\n * })\n * ```\n */\nexport async function xrpc<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n): Promise<XrpcResponse<M>> {\n const response = await xrpcSafe<M>(agentOpts, ns, options)\n if (response.success) return response\n else throw response\n}\n\n/**\n * Union type representing either a successful response or a failure.\n *\n * Both {@link XrpcResponse} and {@link XrpcFailure} have a `success` property\n * that can be used to discriminate between them.\n *\n * @typeParam M - The XRPC method type\n */\nexport type XrpcResult<M extends Procedure | Query> =\n | XrpcResponse<M>\n | XrpcFailure<M>\n\n/**\n * Makes an XRPC request without throwing on failure.\n *\n * Returns a discriminated union that can be checked via the `success` property.\n * This is useful for handling errors without try/catch blocks. This also allow\n * failure results to be typed with the method schema, which can provide better\n * type safety when handling errors (e.g. checking for specific error codes).\n *\n * @param agent - The {@link Agent} to use for making the request\n * @param ns - The lexicon method definition\n * @param options - Request {@link XrpcOptions options} (params, body, headers, etc.)\n * @returns Either a successful {@link XrpcResponse} or an {@link XrpcFailure}\n *\n * @example\n * ```typescript\n * const result = await xrpcSafe('https://example.com', app.bsky.actor.getProfile, {\n * params: { actor: 'alice.bsky.social' }\n * })\n *\n * if (result.success) {\n * console.log(result.body.displayName)\n * } else {\n * console.error('Request failed:', result.error)\n * }\n * ```\n */\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<XrpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n): Promise<XrpcResult<M>> {\n options.signal?.throwIfAborted()\n const method: M = getMain(ns)\n try {\n const agent = buildAgent(agentOpts)\n const url = xrpcRequestUrl(method, options)\n const request = xrpcRequestInit(method, options)\n const response = await agent.fetchHandler(url, request).catch((err) => {\n const cause = extractFetchErrorCause(err)\n throw new XrpcFetchError(method, cause)\n })\n return await XrpcResponse.fromFetchResponse<M>(method, response, options)\n } catch (cause) {\n return asXrpcFailure(method, cause)\n }\n}\n\nfunction xrpcRequestUrl<M extends Procedure | Query | Subscription>(\n method: M,\n options: { params?: Params },\n): `/xrpc/${NsidString}${'' | `?${string}`}` {\n const path = `/xrpc/${method.nsid}` as const\n\n // @NOTE param.toURLSearchParams() will always validate the params in order to\n // apply default values, so we can't disable it with options.validateRequest\n\n const queryString = method.parameters\n ?.toURLSearchParams(options.params ?? {})\n .toString()\n\n return queryString ? (`${path}?${queryString}` as const) : path\n}\n\nfunction xrpcRequestInit<T extends Procedure | Query>(\n schema: T,\n options: XrpcRequestProcessingOptions &\n XrpcRequestHeadersOptions &\n XrpcProcedureInputOptions & {\n encoding?: string\n },\n): RequestInit & { duplex?: 'half' } {\n const headers = buildXrpcRequestHeaders(options)\n\n // Tell the server what type of response we're expecting\n if (schema.output.encoding) {\n headers.set('accept', schema.output.encoding)\n }\n\n // Caller should not set content-type header\n if (headers.has('content-type')) {\n const contentType = headers.get('content-type')\n throw new TypeError(`Unexpected content-type header (${contentType})`)\n }\n\n // Requests with body\n if ('input' in schema) {\n const encodingHint = options.encoding\n const input = xrpcProcedureInput(schema, options, encodingHint)\n\n if (input) {\n headers.set('content-type', input.encoding)\n } else if (encodingHint != null) {\n throw new TypeError(`Unexpected encoding hint (${encodingHint})`)\n }\n\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'POST',\n headers,\n body: input?.body,\n }\n }\n\n // Requests without body\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'GET',\n headers,\n }\n}\n\ntype XrpcProcedureInputOptions = {\n body?: LexValue | BinaryBodyInit\n validateRequest?: boolean\n}\n\nfunction xrpcProcedureInput(\n method: Procedure,\n options: XrpcProcedureInputOptions,\n encodingHint?: string,\n): null | { body: BodyInit; encoding: string } {\n const { input } = method\n const { body } = options\n\n if (options.validateRequest) {\n input.schema?.check(body)\n }\n\n // Special handling for endpoints expecting application/json input\n if (input.encoding === 'application/json') {\n // @NOTE **NOT** using isLexValue here to avoid deep checks in order to\n // distinguish between LexValue and BinaryBodyInit.\n if (!isLexScalar(body) && !isPlainObject(body) && !Array.isArray(body)) {\n throw new TypeError(`Expected LexValue body, got ${typeof body}`)\n }\n\n return buildPayload(input, lexStringify(body), encodingHint)\n }\n\n // Other encodings will be sent unaltered (ie. as binary data)\n switch (typeof body) {\n case 'undefined':\n case 'string':\n return buildPayload(input, body, encodingHint)\n case 'object': {\n if (body === null) break\n if (ArrayBuffer.isView(body)) {\n return buildPayload(\n input,\n body as Uint8Array<ArrayBuffer>,\n encodingHint,\n )\n } else if (\n body instanceof ArrayBuffer ||\n body instanceof ReadableStream\n ) {\n return buildPayload(input, body, encodingHint)\n } else if (isAsyncIterable(body)) {\n return buildPayload(input, toReadableStream(body), encodingHint)\n } else if (isBlobLike(body)) {\n return buildPayload(input, body, encodingHint || body.type)\n }\n }\n }\n\n throw new TypeError(\n `Invalid ${typeof body} body for ${input.encoding} encoding`,\n )\n}\n\nfunction buildPayload(\n schema: Payload,\n body: undefined | BodyInit,\n encodingHint?: string,\n): null | { body: BodyInit; encoding: string } {\n if (schema.encoding === undefined) {\n if (body !== undefined) {\n throw new TypeError(`Endpoint expects no payload`)\n }\n\n return null\n }\n\n if (body === undefined) {\n // This error would be returned by the server, but we can catch it earlier\n // to avoid un-necessary requests. Note that a content-length of 0 does not\n // necessary mean that the body is \"empty\" (e.g. an empty txt file).\n throw new TypeError(`A request body is expected but none was provided`)\n }\n\n const encoding = buildEncoding(schema, encodingHint)\n return { encoding, body }\n}\n\nfunction buildEncoding(schema: Payload, encodingHint?: string): string {\n // Should never happen (required for type safety)\n if (!schema.encoding) {\n throw new TypeError('Unexpected payload')\n }\n\n if (encodingHint?.length) {\n if (!schema.matchesEncoding(encodingHint)) {\n throw new TypeError(\n `Cannot send a body with content-type \"${encodingHint}\" for \"${schema.encoding}\" encoding`,\n )\n }\n return encodingHint\n }\n\n // Fallback\n\n if (schema.encoding === '*/*') {\n return 'application/octet-stream'\n }\n\n if (schema.encoding.startsWith('text/')) {\n return schema.encoding.includes('*')\n ? 'text/plain; charset=utf-8'\n : `${schema.encoding}; charset=utf-8`\n }\n\n if (!schema.encoding.includes('*')) {\n return schema.encoding\n }\n\n throw new TypeError(\n `Unable to determine payload encoding. Please provide a 'content-type' header matching ${schema.encoding}.`,\n )\n}\n\n/**\n * Extracts the root cause from an error, unwrapping common fetch-related errors\n * such as those from undici (Node's internal fetch implementation).\n *\n * @param err - The error to extract the root cause from\n * @returns The root cause error, or the original error if no specific pattern is matched\n * @remarks This is useful for getting more specific error information from fetch-related failures, especially in Node environments using undici.\n */\nexport function extractFetchErrorCause(err: unknown): unknown {\n // Unwrap the Network error from undici (i.e. Node's internal fetch() implementation)\n // https://github.com/nodejs/undici/blob/04cb77327f7ada95c2e5b67424cddcb22d7bf882/lib/web/fetch/index.js#L234-L239\n if (\n err instanceof TypeError &&\n err.message === 'fetch failed' &&\n err.cause !== undefined\n ) {\n return err.cause\n }\n\n // @TODO Add other unwrap patterns here as needed (e.g. for other fetch\n // implementations or common network libraries, like \"node:http\", or in other\n // environments like React Native, Deno, Bun, Browser, etc.)\n\n return err\n}\n"]}
1
+ {"version":3,"file":"xrpc.js","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexValue, isLexScalar, isPlainObject } from '@atproto/lex-data'\nimport { lexStringify } from '@atproto/lex-json'\nimport {\n InferInput,\n InferPayload,\n Main,\n NsidString,\n Params,\n Payload,\n Procedure,\n Query,\n Restricted,\n Subscription,\n getMain,\n} from '@atproto/lex-schema'\nimport { Agent, AgentOptions, buildAgent } from './agent.js'\nimport { XrpcFailure, XrpcFetchError, asXrpcFailure } from './errors.js'\nimport { XrpcResponse, XrpcResponseOptions } from './response.js'\nimport { BinaryBodyInit } from './types.js'\nimport {\n XrpcRequestHeadersOptions,\n asUint8ArrayArrayBuffer,\n buildXrpcRequestHeaders,\n isAsyncIterable,\n isBlobLike,\n toReadableStream,\n} from './util.js'\n\n/**\n * The query/path parameters type for an XRPC method, inferred from its schema.\n *\n * @typeParam M - The XRPC method type (Procedure, Query, or Subscription)\n */\nexport type XrpcRequestParams<M extends Procedure | Query | Subscription> =\n InferInput<M['parameters']>\n\n// If all params are optional, allow omitting the params object\ntype XrpcRequestParamsOptions<P extends Params> =\n NonNullable<unknown> extends P ? { params?: P } : { params: P }\n\ntype XrpcRequestPayload<M extends Procedure | Query> = M extends Procedure\n ? InferPayload<M['input'], BinaryBodyInit>\n : undefined\n\ntype XrpcRequestPayloadOptions<TPayload> = TPayload extends {\n body: infer B\n encoding: infer E\n}\n ? {\n body: B\n\n /**\n * mime type hint for binary bodies\n *\n * Only needed for endpoints that accept binary input (e.g. file uploads)\n * when the body is a Blob-like object without a type (e.g. fetch-blob's\n * Blob). If the body is a Blob-like object with a type, that type will be\n * used as the content-type header instead of this option.\n *\n * @default \"application/octet-stream\"\n */\n encoding?: E\n }\n : { body?: undefined; encoding?: undefined }\n\n/**\n * Options for making an XRPC request, based on the method schema.\n *\n * Combines {@link XrpcRequestOptions} and {@link XrpcResponseOptions} with\n * method-specific params and body requirements. The type system ensures\n * required params/body are provided based on the method schema.\n *\n * @typeParam M - The XRPC method type (Procedure or Query)\n *\n * @example Query with params\n * ```typescript\n * const options: XrpcOptions<typeof app.bsky.feed.getTimeline.main> = {\n * params: { limit: 50 }\n * }\n * ```\n *\n * @example Procedure with body\n * ```typescript\n * const options: XrpcOptions<typeof com.atproto.repo.createRecord.main> = {\n * body: { repo: did, collection: 'app.bsky.feed.post', record: { ... } }\n * }\n * ```\n */\nexport type XrpcOptions<M extends Procedure | Query = Procedure | Query> =\n XrpcRequestOptions<M> & XrpcResponseOptions\n\nexport type XrpcRequestOptions<\n M extends Procedure | Query = Procedure | Query,\n> = XrpcRequestProcessingOptions &\n XrpcRequestHeadersOptions &\n XrpcRequestPayloadOptions<XrpcRequestPayload<M>> &\n XrpcRequestParamsOptions<XrpcRequestParams<M>>\n\nexport type XrpcRequestProcessingOptions = {\n /**\n * AbortSignal to cancel the request.\n */\n signal?: AbortSignal\n\n /**\n * Whether to validate the request against the method's input schema. Enabling\n * this can help catch errors early but may have a performance cost. This\n * would typically only be set to `true` in development or debugging\n * scenarios.\n *\n * @default false\n */\n validateRequest?: boolean\n}\n\n/**\n * Makes an XRPC request and throws on failure.\n *\n * This is the low-level function for making XRPC calls.\n *\n * @param agent - The {@link Agent} to use for making the request\n * @param ns - The lexicon method definition\n * @param options - Request {@link XrpcOptions options} (params, body, headers, etc.)\n * @returns The successful {@link XrpcResponse}\n * @throws {XrpcFailure} When the request fails\n *\n * @example\n * ```typescript\n * const response = await xrpc('https://bsky.network', com.atproto.identity.resolveHandle, {\n * params: { handle: \"atproto.com\" }\n * })\n * ```\n *\n * @example\n * ```typescript\n * const response = await xrpc(agent, app.bsky.feed.getTimeline.main, {\n * params: { limit: 50 }\n * })\n * ```\n */\nexport async function xrpc<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n): Promise<XrpcResponse<M>> {\n const response = await xrpcSafe<M>(agentOpts, ns, options)\n if (response.success) return response\n else throw response\n}\n\n/**\n * Union type representing either a successful response or a failure.\n *\n * Both {@link XrpcResponse} and {@link XrpcFailure} have a `success` property\n * that can be used to discriminate between them.\n *\n * @typeParam M - The XRPC method type\n */\nexport type XrpcResult<M extends Procedure | Query> =\n | XrpcResponse<M>\n | XrpcFailure<M>\n\n/**\n * Makes an XRPC request without throwing on failure.\n *\n * Returns a discriminated union that can be checked via the `success` property.\n * This is useful for handling errors without try/catch blocks. This also allow\n * failure results to be typed with the method schema, which can provide better\n * type safety when handling errors (e.g. checking for specific error codes).\n *\n * @param agent - The {@link Agent} to use for making the request\n * @param ns - The lexicon method definition\n * @param options - Request {@link XrpcOptions options} (params, body, headers, etc.)\n * @returns Either a successful {@link XrpcResponse} or an {@link XrpcFailure}\n *\n * @example\n * ```typescript\n * const result = await xrpcSafe('https://example.com', app.bsky.actor.getProfile, {\n * params: { actor: 'alice.bsky.social' }\n * })\n *\n * if (result.success) {\n * console.log(result.body.displayName)\n * } else {\n * console.error('Request failed:', result.error)\n * }\n * ```\n */\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<XrpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agentOpts: Agent | AgentOptions,\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n): Promise<XrpcResult<M>> {\n options.signal?.throwIfAborted()\n const method: M = getMain(ns)\n try {\n const agent = buildAgent(agentOpts)\n const url = xrpcRequestUrl(method, options)\n const request = xrpcRequestInit(method, options)\n const response = await agent.fetchHandler(url, request).catch((err) => {\n const cause = extractFetchErrorCause(err)\n throw new XrpcFetchError(method, cause)\n })\n return await XrpcResponse.fromFetchResponse<M>(method, response, options)\n } catch (cause) {\n return asXrpcFailure(method, cause)\n }\n}\n\nfunction xrpcRequestUrl<M extends Procedure | Query | Subscription>(\n method: M,\n options: { params?: Params },\n): `/xrpc/${NsidString}${'' | `?${string}`}` {\n const path = `/xrpc/${method.nsid}` as const\n\n // @NOTE param.toURLSearchParams() will always validate the params in order to\n // apply default values, so we can't disable it with options.validateRequest\n\n const queryString = method.parameters\n ?.toURLSearchParams(options.params ?? {})\n .toString()\n\n return queryString ? (`${path}?${queryString}` as const) : path\n}\n\nfunction xrpcRequestInit<T extends Procedure | Query>(\n schema: T,\n options: XrpcRequestProcessingOptions &\n XrpcRequestHeadersOptions &\n XrpcProcedureInputOptions & {\n encoding?: string\n },\n): RequestInit & { duplex?: 'half' } {\n const headers = buildXrpcRequestHeaders(options)\n\n // Tell the server what type of response we're expecting\n if (schema.output.encoding) {\n headers.set('accept', schema.output.encoding)\n }\n\n // Caller should not set content-type header\n if (headers.has('content-type')) {\n const contentType = headers.get('content-type')\n throw new TypeError(`Unexpected content-type header (${contentType})`)\n }\n\n // Requests with body\n if ('input' in schema) {\n const encodingHint = options.encoding\n const input = xrpcProcedureInput(schema, options, encodingHint)\n\n if (input) {\n headers.set('content-type', input.encoding)\n } else if (encodingHint != null) {\n throw new TypeError(`Unexpected encoding hint (${encodingHint})`)\n }\n\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'POST',\n headers,\n body: input?.body,\n }\n }\n\n // Requests without body\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'GET',\n headers,\n }\n}\n\ntype XrpcProcedureInputOptions = {\n body?: LexValue | BinaryBodyInit\n validateRequest?: boolean\n}\n\nfunction xrpcProcedureInput(\n method: Procedure,\n options: XrpcProcedureInputOptions,\n encodingHint?: string,\n): null | { body: BodyInit; encoding: string } {\n const { input } = method\n const { body } = options\n\n if (options.validateRequest) {\n input.schema?.check(body)\n }\n\n // Special handling for endpoints expecting application/json input\n if (input.encoding === 'application/json') {\n // @NOTE **NOT** using isLexValue here to avoid deep checks in order to\n // distinguish between LexValue and BinaryBodyInit.\n if (!isLexScalar(body) && !isPlainObject(body) && !Array.isArray(body)) {\n throw new TypeError(`Expected LexValue body, got ${typeof body}`)\n }\n\n return buildPayload(input, lexStringify(body), encodingHint)\n }\n\n // Other encodings will be sent unaltered (ie. as binary data)\n switch (typeof body) {\n case 'undefined':\n case 'string':\n return buildPayload(input, body, encodingHint)\n case 'object': {\n if (body === null) break\n if (ArrayBuffer.isView(body)) {\n return buildPayload(input, asUint8ArrayArrayBuffer(body), encodingHint)\n } else if (\n body instanceof ArrayBuffer ||\n body instanceof ReadableStream\n ) {\n return buildPayload(input, body, encodingHint)\n } else if (isAsyncIterable(body)) {\n // @NOTE While fetch() does not allow SharedArrayBuffer-backed\n // Uint8Arrays as \"body\", it **does** allow using ReadableStreams made\n // of Uint8Arrays<SharedArrayBuffer> (tested on NodeJS 22) as \"body\".\n return buildPayload(input, toReadableStream(body), encodingHint)\n } else if (isBlobLike(body)) {\n return buildPayload(input, body, encodingHint || body.type)\n }\n }\n }\n\n throw new TypeError(\n `Invalid ${typeof body} body for ${input.encoding} encoding`,\n )\n}\n\nfunction buildPayload(\n schema: Payload,\n body: undefined | BodyInit,\n encodingHint?: string,\n): null | { body: BodyInit; encoding: string } {\n if (schema.encoding === undefined) {\n if (body !== undefined) {\n throw new TypeError(`Endpoint expects no payload`)\n }\n\n return null\n }\n\n if (body === undefined) {\n // This error would be returned by the server, but we can catch it earlier\n // to avoid un-necessary requests. Note that a content-length of 0 does not\n // necessary mean that the body is \"empty\" (e.g. an empty txt file).\n throw new TypeError(`A request body is expected but none was provided`)\n }\n\n const encoding = buildEncoding(schema, encodingHint)\n return { encoding, body }\n}\n\nfunction buildEncoding(schema: Payload, encodingHint?: string): string {\n // Should never happen (required for type safety)\n if (!schema.encoding) {\n throw new TypeError('Unexpected payload')\n }\n\n if (encodingHint?.length) {\n if (!schema.matchesEncoding(encodingHint)) {\n throw new TypeError(\n `Cannot send a body with content-type \"${encodingHint}\" for \"${schema.encoding}\" encoding`,\n )\n }\n return encodingHint\n }\n\n // Fallback\n\n if (schema.encoding === '*/*') {\n return 'application/octet-stream'\n }\n\n if (schema.encoding.startsWith('text/')) {\n return schema.encoding.includes('*')\n ? 'text/plain; charset=utf-8'\n : `${schema.encoding}; charset=utf-8`\n }\n\n if (!schema.encoding.includes('*')) {\n return schema.encoding\n }\n\n throw new TypeError(\n `Unable to determine payload encoding. Please provide a 'content-type' header matching ${schema.encoding}.`,\n )\n}\n\n/**\n * Extracts the root cause from an error, unwrapping common fetch-related errors\n * such as those from undici (Node's internal fetch implementation).\n *\n * @param err - The error to extract the root cause from\n * @returns The root cause error, or the original error if no specific pattern is matched\n * @remarks This is useful for getting more specific error information from fetch-related failures, especially in Node environments using undici.\n */\nexport function extractFetchErrorCause(err: unknown): unknown {\n // Unwrap the Network error from undici (i.e. Node's internal fetch() implementation)\n // https://github.com/nodejs/undici/blob/04cb77327f7ada95c2e5b67424cddcb22d7bf882/lib/web/fetch/index.js#L234-L239\n if (\n err instanceof TypeError &&\n err.message === 'fetch failed' &&\n err.cause !== undefined\n ) {\n return err.cause\n }\n\n // @TODO Add other unwrap patterns here as needed (e.g. for other fetch\n // implementations or common network libraries, like \"node:http\", or in other\n // environments like React Native, Deno, Bun, Browser, etc.)\n\n return err\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex-client",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },
@@ -36,14 +36,14 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "tslib": "^2.8.1",
39
- "@atproto/lex-data": "^0.1.0",
39
+ "@atproto/lex-data": "^0.1.1",
40
40
  "@atproto/lex-json": "^0.1.0",
41
- "@atproto/lex-schema": "^0.1.0"
41
+ "@atproto/lex-schema": "^0.1.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "vitest": "^4.0.16",
45
45
  "@atproto/lex-cbor": "^0.1.0",
46
- "@atproto/lex-builder": "^0.1.0"
46
+ "@atproto/lex-builder": "^0.1.2"
47
47
  },
48
48
  "scripts": {
49
49
  "prebuild": "node ./scripts/lex-build.mjs",
package/src/client.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { LexMap, LexValue, TypedLexMap } from '@atproto/lex-data'
2
2
  import {
3
3
  AtIdentifierString,
4
+ AtUriString,
4
5
  CidString,
5
6
  DidString,
6
7
  Infer,
@@ -19,7 +20,17 @@ import {
19
20
  } from '@atproto/lex-schema'
20
21
  import { Agent, AgentOptions, buildAgent } from './agent.js'
21
22
  import { XrpcFailure } from './errors.js'
22
- import { com } from './lexicons/index.js'
23
+ // @NOTE We could use import { com } from "./lexicons/index.js" here, but some
24
+ // consumers might not know how to properly tree-shake that, so we import only
25
+ // the needed lexicon schemas directly.
26
+ import applyWrites from './lexicons/com/atproto/repo/applyWrites.js'
27
+ import createRecord from './lexicons/com/atproto/repo/createRecord.js'
28
+ import deleteRecord from './lexicons/com/atproto/repo/deleteRecord.js'
29
+ import getRecord from './lexicons/com/atproto/repo/getRecord.js'
30
+ import listRecords from './lexicons/com/atproto/repo/listRecords.js'
31
+ import putRecord from './lexicons/com/atproto/repo/putRecord.js'
32
+ import uploadBlob from './lexicons/com/atproto/repo/uploadBlob.js'
33
+ import getBlob from './lexicons/com/atproto/sync/getBlob.js'
23
34
  import {
24
35
  XrpcResponse,
25
36
  XrpcResponseBody,
@@ -27,10 +38,21 @@ import {
27
38
  } from './response.js'
28
39
  import { BinaryBodyInit, Service } from './types.js'
29
40
  import {
41
+ RecordKeyOptions,
30
42
  XrpcRequestHeadersOptions,
31
43
  applyDefaults,
32
44
  buildXrpcRequestHeaders,
45
+ getDefaultRecordKey,
46
+ getLiteralRecordKey,
33
47
  } from './util.js'
48
+ import {
49
+ WriteOperation,
50
+ WriteOperationCreateOptions,
51
+ WriteOperationDeleteOptions,
52
+ WriteOperationHelper,
53
+ WriteOperationUpdateOptions,
54
+ WriteOperationsFactory,
55
+ } from './write-operation-builder.js'
34
56
  import {
35
57
  XrpcOptions,
36
58
  XrpcRequestParams,
@@ -39,25 +61,31 @@ import {
39
61
  xrpcSafe,
40
62
  } from './xrpc.js'
41
63
 
42
- export type {
43
- AtIdentifierString,
44
- CidString,
45
- DidString,
46
- Infer,
47
- InferMethodInputBody,
48
- InferMethodOutputBody,
49
- InferRecordKey,
50
- LexMap,
51
- LexValue,
52
- LexiconRecordKey,
53
- Main,
54
- NsidString,
55
- Params,
64
+ export {
65
+ type AtIdentifierString,
66
+ type CidString,
67
+ type DidString,
68
+ type Infer,
69
+ type InferMethodInputBody,
70
+ type InferMethodOutputBody,
71
+ type InferRecordKey,
72
+ type LexMap,
73
+ type LexValue,
74
+ type LexiconRecordKey,
75
+ type Main,
76
+ type NsidString,
77
+ type Params,
56
78
  Procedure,
57
79
  Query,
58
80
  RecordSchema,
59
- Restricted,
60
- TypedLexMap,
81
+ type Restricted,
82
+ type TypedLexMap,
83
+ type WriteOperation,
84
+ type WriteOperationCreateOptions,
85
+ type WriteOperationDeleteOptions,
86
+ WriteOperationHelper,
87
+ type WriteOperationUpdateOptions,
88
+ type WriteOperationsFactory,
61
89
  }
62
90
 
63
91
  /**
@@ -138,7 +166,7 @@ export type InferActionOutput<A extends Action> =
138
166
  * @see {@link Client.createRecord}
139
167
  */
140
168
  export type CreateRecordOptions = Omit<
141
- XrpcOptions<typeof com.atproto.repo.createRecord.main>,
169
+ XrpcOptions<typeof createRecord>,
142
170
  'body'
143
171
  > & {
144
172
  /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
@@ -155,7 +183,7 @@ export type CreateRecordOptions = Omit<
155
183
  * @see {@link Client.deleteRecord}
156
184
  */
157
185
  export type DeleteRecordOptions = Omit<
158
- XrpcOptions<typeof com.atproto.repo.deleteRecord.main>,
186
+ XrpcOptions<typeof deleteRecord>,
159
187
  'body'
160
188
  > & {
161
189
  /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
@@ -171,10 +199,7 @@ export type DeleteRecordOptions = Omit<
171
199
  *
172
200
  * @see {@link Client.getRecord}
173
201
  */
174
- export type GetRecordOptions = Omit<
175
- XrpcOptions<typeof com.atproto.repo.getRecord.main>,
176
- 'params'
177
- > & {
202
+ export type GetRecordOptions = Omit<XrpcOptions<typeof getRecord>, 'params'> & {
178
203
  /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
179
204
  repo?: AtIdentifierString
180
205
  }
@@ -184,10 +209,7 @@ export type GetRecordOptions = Omit<
184
209
  *
185
210
  * @see {@link Client.putRecord}
186
211
  */
187
- export type PutRecordOptions = Omit<
188
- XrpcOptions<typeof com.atproto.repo.putRecord.main>,
189
- 'body'
190
- > & {
212
+ export type PutRecordOptions = Omit<XrpcOptions<typeof putRecord>, 'body'> & {
191
213
  /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
192
214
  repo?: AtIdentifierString
193
215
  /** Compare-and-swap on the repo commit. If specified, must match current commit. */
@@ -204,7 +226,7 @@ export type PutRecordOptions = Omit<
204
226
  * @see {@link Client.listRecords}
205
227
  */
206
228
  export type ListRecordsOptions = Omit<
207
- XrpcOptions<typeof com.atproto.repo.listRecords.main>,
229
+ XrpcOptions<typeof listRecords>,
208
230
  'params'
209
231
  > & {
210
232
  /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
@@ -217,22 +239,26 @@ export type ListRecordsOptions = Omit<
217
239
  reverse?: boolean
218
240
  }
219
241
 
220
- export type UploadBlobOptions = Omit<
221
- XrpcOptions<typeof com.atproto.repo.uploadBlob.main>,
242
+ /**
243
+ * Options for applying a batch of writes (create/update/delete) to an AT Protocol repository.
244
+ *
245
+ * @see {@link Client.applyWrites}
246
+ */
247
+ export type ApplyWritesOptions = Omit<
248
+ XrpcOptions<typeof applyWrites>,
222
249
  'body'
223
- >
250
+ > & {
251
+ /** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
252
+ repo?: AtIdentifierString
253
+ /** Whether the PDS should validate the records against their lexicon schemas. */
254
+ validate?: boolean
255
+ /** Compare-and-swap on the repo commit. If specified, must match current commit. */
256
+ swapCommit?: CidString
257
+ }
224
258
 
225
- export type GetBlobOptions = Omit<
226
- XrpcOptions<typeof com.atproto.sync.getBlob.main>,
227
- 'params'
228
- >
259
+ export type UploadBlobOptions = Omit<XrpcOptions<typeof uploadBlob>, 'body'>
229
260
 
230
- export type RecordKeyOptions<
231
- T extends RecordSchema,
232
- AlsoOptionalWhenRecordKeyIs extends LexiconRecordKey = never,
233
- > = T['key'] extends `literal:${string}` | AlsoOptionalWhenRecordKeyIs
234
- ? { rkey?: InferRecordKey<T> }
235
- : { rkey: InferRecordKey<T> }
261
+ export type GetBlobOptions = Omit<XrpcOptions<typeof getBlob>, 'params'>
236
262
 
237
263
  /**
238
264
  * Type-safe options for {@link Client.create}, combining record options with key requirements.
@@ -247,7 +273,7 @@ export type CreateOptions<T extends RecordSchema> = CreateRecordOptions &
247
273
  * Contains the URI and CID of the newly created record.
248
274
  */
249
275
  export type CreateOutput = InferMethodOutputBody<
250
- typeof com.atproto.repo.createRecord.main,
276
+ typeof createRecord,
251
277
  Uint8Array
252
278
  >
253
279
 
@@ -262,7 +288,7 @@ export type DeleteOptions<T extends RecordSchema> = DeleteRecordOptions &
262
288
  * Output type for record deletion operations.
263
289
  */
264
290
  export type DeleteOutput = InferMethodOutputBody<
265
- typeof com.atproto.repo.deleteRecord.main,
291
+ typeof deleteRecord,
266
292
  Uint8Array
267
293
  >
268
294
 
@@ -279,7 +305,7 @@ export type GetOptions<T extends RecordSchema> = GetRecordOptions &
279
305
  * @typeParam T - The record schema type
280
306
  */
281
307
  export type GetOutput<T extends RecordSchema> = Omit<
282
- InferMethodOutputBody<typeof com.atproto.repo.getRecord.main, Uint8Array>,
308
+ InferMethodOutputBody<typeof getRecord, Uint8Array>,
283
309
  'value'
284
310
  > & { value: Infer<T> }
285
311
 
@@ -294,10 +320,7 @@ export type PutOptions<T extends RecordSchema> = PutRecordOptions &
294
320
  * Output type for record put (create/update) operations.
295
321
  * Contains the URI and CID of the record.
296
322
  */
297
- export type PutOutput = InferMethodOutputBody<
298
- typeof com.atproto.repo.putRecord.main,
299
- Uint8Array
300
- >
323
+ export type PutOutput = InferMethodOutputBody<typeof putRecord, Uint8Array>
301
324
 
302
325
  /**
303
326
  * Options for {@link Client.list} operations.
@@ -310,7 +333,7 @@ export type ListOptions = ListRecordsOptions
310
333
  * @typeParam T - The record schema type
311
334
  */
312
335
  export type ListOutput<T extends RecordSchema> = InferMethodOutputBody<
313
- typeof com.atproto.repo.listRecords.main,
336
+ typeof listRecords,
314
337
  Uint8Array
315
338
  > & {
316
339
  /** Records that successfully validated against the schema. */
@@ -326,10 +349,11 @@ export type ListOutput<T extends RecordSchema> = InferMethodOutputBody<
326
349
  * A record from a list operation with its value typed to the schema.
327
350
  * @typeParam Value - The validated record value type
328
351
  */
329
- export type ListRecord<Value extends LexMap> =
330
- com.atproto.repo.listRecords.Record & {
331
- value: Value
332
- }
352
+ export type ListRecord<Value extends LexMap> = {
353
+ uri: AtUriString
354
+ cid: CidString
355
+ value: Value
356
+ }
333
357
 
334
358
  /**
335
359
  * The Client class is the primary interface for interacting with AT Protocol
@@ -587,7 +611,7 @@ export class Client implements Agent {
587
611
  rkey?: string,
588
612
  options?: CreateRecordOptions,
589
613
  ) {
590
- return this.xrpc(com.atproto.repo.createRecord.main, {
614
+ return this.xrpc(createRecord, {
591
615
  ...options,
592
616
  body: {
593
617
  repo: options?.repo ?? this.assertDid,
@@ -614,7 +638,7 @@ export class Client implements Agent {
614
638
  rkey: string,
615
639
  options?: DeleteRecordOptions,
616
640
  ) {
617
- return this.xrpc(com.atproto.repo.deleteRecord.main, {
641
+ return this.xrpc(deleteRecord, {
618
642
  ...options,
619
643
  body: {
620
644
  repo: options?.repo ?? this.assertDid,
@@ -640,7 +664,7 @@ export class Client implements Agent {
640
664
  rkey: string,
641
665
  options?: GetRecordOptions,
642
666
  ) {
643
- return this.xrpc(com.atproto.repo.getRecord.main, {
667
+ return this.xrpc(getRecord, {
644
668
  ...options,
645
669
  params: {
646
670
  repo: options?.repo ?? this.assertDid,
@@ -664,7 +688,7 @@ export class Client implements Agent {
664
688
  rkey: string,
665
689
  options?: PutRecordOptions,
666
690
  ) {
667
- return this.xrpc(com.atproto.repo.putRecord.main, {
691
+ return this.xrpc(putRecord, {
668
692
  ...options,
669
693
  body: {
670
694
  repo: options?.repo ?? this.assertDid,
@@ -687,7 +711,7 @@ export class Client implements Agent {
687
711
  * @see {@link list} for a higher-level typed alternative
688
712
  */
689
713
  async listRecords(nsid: NsidString, options?: ListRecordsOptions) {
690
- return this.xrpc(com.atproto.repo.listRecords.main, {
714
+ return this.xrpc(listRecords, {
691
715
  ...options,
692
716
  params: {
693
717
  repo: options?.repo ?? this.assertDid,
@@ -699,6 +723,44 @@ export class Client implements Agent {
699
723
  })
700
724
  }
701
725
 
726
+ /**
727
+ * Performs an atomic batch of create, update, and delete operations on records in a repository.
728
+ *
729
+ * @param builder - A function that receives an {@link ApplyWritesOperations} instance to build the operations
730
+ * @param options - ApplyWrites options including repo, validate, swapCommit
731
+ * @returns The XRPC response from the applyWrites call
732
+ *
733
+ * @example
734
+ * ```typescript
735
+ * const response = await client.applyWrites((op) => [
736
+ * op.create(app.bsky.feed.post, { text: 'Hello!' }),
737
+ * op.update(app.bsky.feed.post, { text: 'Updated text' }, { rkey: 'post123' }),
738
+ * op.delete(app.bsky.feed.post, 'post456'),
739
+ * op.update(app.bsky.actor.profile, { displayName: 'Alice' }),
740
+ * ], {
741
+ * validate: true,
742
+ * })
743
+ *
744
+ * for (const result of response.body.results) {
745
+ * console.log(result.uri)
746
+ * }
747
+ * ```
748
+ */
749
+ async applyWrites(
750
+ factory: WriteOperationsFactory,
751
+ options?: ApplyWritesOptions,
752
+ ) {
753
+ return this.xrpc(applyWrites, {
754
+ ...options,
755
+ body: {
756
+ repo: options?.repo ?? this.assertDid,
757
+ writes: WriteOperationHelper.build(factory),
758
+ validate: options?.validate,
759
+ swapCommit: options?.swapCommit,
760
+ },
761
+ })
762
+ }
763
+
702
764
  /**
703
765
  * Uploads a blob to an AT Protocol repository.
704
766
  *
@@ -716,7 +778,7 @@ export class Client implements Agent {
716
778
  * ```
717
779
  */
718
780
  async uploadBlob(body: BinaryBodyInit, options?: UploadBlobOptions) {
719
- return this.xrpc(com.atproto.repo.uploadBlob.main, { ...options, body })
781
+ return this.xrpc(uploadBlob, { ...options, body })
720
782
  }
721
783
 
722
784
  /**
@@ -727,7 +789,7 @@ export class Client implements Agent {
727
789
  * @param options - Call options
728
790
  */
729
791
  async getBlob(did: DidString, cid: CidString, options?: GetBlobOptions) {
730
- return this.xrpc(com.atproto.sync.getBlob.main, {
792
+ return this.xrpc(getBlob, {
731
793
  ...options,
732
794
  params: { did, cid },
733
795
  })
@@ -1002,25 +1064,3 @@ export class Client implements Agent {
1002
1064
  return { ...body, records, invalid }
1003
1065
  }
1004
1066
  }
1005
-
1006
- function getDefaultRecordKey<const T extends RecordSchema>(
1007
- schema: T,
1008
- ): undefined | InferRecordKey<T> {
1009
- // Let the server generate the TID
1010
- if (schema.key === 'tid') return undefined
1011
- if (schema.key === 'any') return undefined
1012
-
1013
- return getLiteralRecordKey(schema)
1014
- }
1015
-
1016
- function getLiteralRecordKey<const T extends RecordSchema>(
1017
- schema: T,
1018
- ): InferRecordKey<T> {
1019
- if (schema.key.startsWith('literal:')) {
1020
- return schema.key.slice(8) as InferRecordKey<T>
1021
- }
1022
-
1023
- throw new TypeError(
1024
- `An "rkey" must be provided for record key type "${schema.key}" (${schema.$type})`,
1025
- )
1026
- }