@atproto/lex-client 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/agent.d.ts +24 -19
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +11 -33
- package/dist/agent.js.map +1 -1
- package/dist/client.d.ts +21 -12
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +8 -3
- package/dist/client.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts +13 -9
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.js +3 -2
- package/dist/lexicons/com/atproto/repo/createRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts +5 -5
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts +5 -5
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.js +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts +6 -6
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.js +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts +13 -9
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/putRecord.defs.js +3 -2
- package/dist/lexicons/com/atproto/repo/putRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +5 -5
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts +3 -3
- package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/sync/getBlob.defs.js.map +1 -1
- package/dist/xrpc.d.ts +14 -8
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +5 -3
- package/dist/xrpc.js.map +1 -1
- package/package.json +6 -6
- package/src/agent.ts +38 -21
- package/src/client.ts +16 -8
- package/src/lexicons/com/atproto/repo/createRecord.defs.ts +15 -7
- package/src/lexicons/com/atproto/repo/deleteRecord.defs.ts +11 -5
- package/src/lexicons/com/atproto/repo/getRecord.defs.ts +7 -4
- package/src/lexicons/com/atproto/repo/listRecords.defs.ts +8 -5
- package/src/lexicons/com/atproto/repo/putRecord.defs.ts +15 -7
- package/src/lexicons/com/atproto/repo/uploadBlob.defs.ts +11 -5
- package/src/lexicons/com/atproto/sync/getBlob.defs.ts +6 -3
- package/src/xrpc.ts +22 -14
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 Params,\n Payload,\n Procedure,\n Query,\n Restricted,\n Subscription,\n getMain,\n} from '@atproto/lex-schema'\nimport { Agent } from './agent.js'\nimport { XrpcFailure, asXrpcFailure } from './errors.js'\nimport { XrpcResponse } from './response.js'\nimport { BinaryBodyInit, CallOptions } from './types.js'\nimport {\n buildAtprotoHeaders,\n isAsyncIterable,\n isBlobLike,\n toReadableStream,\n} from './util.js'\n\n// If all params are optional, allow omitting the params object\ntype XrpcParamsOptions<P extends Params> =\n NonNullable<unknown> extends P ? { params?: P } : { params: P }\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\ntype XrpcRequestPayload<M extends Procedure | Query> = M extends Procedure\n ? InferPayload<M['input'], BinaryBodyInit>\n : undefined\n\ntype XrpcInputOptions<In> = In extends { body: infer B; encoding: infer E }\n ? // encoding will be inferred from the schema at runtime if not provided\n { body: B; encoding?: E }\n : { body?: undefined; encoding?: undefined }\n\n/**\n * Options for making an XRPC request.\n *\n * Combines {@link CallOptions} with method-specific params and body requirements.\n * The type system ensures required params/body are provided based on the method schema.\n *\n * @typeParam M - The XRPC method type (Procedure or Query)\n * @see {@link CallOptions} for general request options like signal and validateRequest\n * @see {@link XrpcParamsOptions} for method-specific query parameters\n * @see {@link XrpcInputOptions} for method-specific body and encoding requirements\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 CallOptions &\n XrpcInputOptions<XrpcRequestPayload<M>> &\n XrpcParamsOptions<XrpcRequestParams<M>>\n\n/**\n * Makes an XRPC request and throws on failure.\n *\n * This is the low-level function for making XRPC calls. For most use cases,\n * prefer using {@link Client.xrpc} which provides a more ergonomic API.\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(agent, app.bsky.feed.getTimeline.main, {\n * params: { limit: 50 }\n * })\n * ```\n */\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\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 agent: Agent,\n ns: Main<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: Main<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n): Promise<XrpcResponse<M>> {\n const response = await xrpcSafe<M>(agent, 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(agent, 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('Request failed:', result.error)\n * }\n * ```\n */\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agent: Agent,\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 agent: Agent,\n ns: Main<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agent: Agent,\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 url = xrpcRequestUrl(method, options)\n const request = xrpcRequestInit(method, options)\n const response = await agent.fetchHandler(url, request)\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: CallOptions & { params?: Params },\n) {\n const path = `/xrpc/${method.nsid}`\n\n const queryString = method.parameters\n ?.toURLSearchParams(options.params ?? {})\n .toString()\n\n return queryString ? `${path}?${queryString}` : path\n}\n\nfunction xrpcRequestInit<T extends Procedure | Query>(\n schema: T,\n options: CallOptions & {\n body?: LexValue | BinaryBodyInit\n encoding?: string\n },\n): RequestInit & { duplex?: 'half' } {\n const headers = buildAtprotoHeaders(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\nfunction xrpcProcedureInput(\n method: Procedure,\n options: CallOptions & { body?: LexValue | BinaryBodyInit },\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 (\n ArrayBuffer.isView(body) ||\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(\n `Cannot send a ${typeof body} body with undefined encoding`,\n )\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"]}
|
|
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, asXrpcFailure } from './errors.js'\nimport { XrpcResponse } from './response.js'\nimport { BinaryBodyInit, CallOptions } from './types.js'\nimport {\n buildAtprotoHeaders,\n isAsyncIterable,\n isBlobLike,\n toReadableStream,\n} from './util.js'\n\n// If all params are optional, allow omitting the params object\ntype XrpcParamsOptions<P extends Params> =\n NonNullable<unknown> extends P ? { params?: P } : { params: P }\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\ntype XrpcRequestPayload<M extends Procedure | Query> = M extends Procedure\n ? InferPayload<M['input'], BinaryBodyInit>\n : undefined\n\ntype XrpcInputOptions<In> = In extends { body: infer B; encoding: infer E }\n ? // encoding will be inferred from the schema at runtime if not provided\n { body: B; encoding?: E }\n : { body?: undefined; encoding?: undefined }\n\n/**\n * Options for making an XRPC request.\n *\n * Combines {@link CallOptions} with method-specific params and body requirements.\n * The type system ensures required params/body are provided based on the method schema.\n *\n * @typeParam M - The XRPC method type (Procedure or Query)\n * @see {@link CallOptions} for general request options like signal and validateRequest\n * @see {@link XrpcParamsOptions} for method-specific query parameters\n * @see {@link XrpcInputOptions} for method-specific body and encoding requirements\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 CallOptions &\n XrpcInputOptions<XrpcRequestPayload<M>> &\n XrpcParamsOptions<XrpcRequestParams<M>>\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)\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: CallOptions & { params?: Params },\n): `/xrpc/${NsidString}${'' | `?${string}`}` {\n const path = `/xrpc/${method.nsid}` as const\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: CallOptions & {\n body?: LexValue | BinaryBodyInit\n encoding?: string\n },\n): RequestInit & { duplex?: 'half' } {\n const headers = buildAtprotoHeaders(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\nfunction xrpcProcedureInput(\n method: Procedure,\n options: CallOptions & { body?: LexValue | BinaryBodyInit },\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 (\n ArrayBuffer.isView(body) ||\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(\n `Cannot send a ${typeof body} body with undefined encoding`,\n )\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "HTTP client for interacting with Lexicon based APIs",
|
|
6
6
|
"keywords": [
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"tslib": "^2.8.1",
|
|
40
|
-
"@atproto/lex-data": "^0.0.
|
|
41
|
-
"@atproto/lex-json": "^0.0.
|
|
42
|
-
"@atproto/lex-schema": "^0.0.
|
|
40
|
+
"@atproto/lex-data": "^0.0.12",
|
|
41
|
+
"@atproto/lex-json": "^0.0.12",
|
|
42
|
+
"@atproto/lex-schema": "^0.0.13"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"vitest": "^4.0.16",
|
|
46
|
-
"@atproto/lex-cbor": "^0.0.
|
|
47
|
-
"@atproto/lex-builder": "^0.0.
|
|
46
|
+
"@atproto/lex-cbor": "^0.0.13",
|
|
47
|
+
"@atproto/lex-builder": "^0.0.16"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"prebuild": "node ./scripts/lex-build.mjs",
|
package/src/agent.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { DidString } from '@atproto/lex-schema'
|
|
|
5
5
|
*
|
|
6
6
|
* The handler is responsible for adding the origin (protocol, hostname, and
|
|
7
7
|
* port) to the provided path, typically based on authentication or service
|
|
8
|
-
* configuration. The handler
|
|
8
|
+
* configuration. The handler can also be responsible for adding any necessary
|
|
9
9
|
* headers, such as authorization tokens.
|
|
10
10
|
*
|
|
11
11
|
* @param path - The URL path (pathname + query parameters) without the origin
|
|
@@ -18,16 +18,23 @@ export type FetchHandler = (
|
|
|
18
18
|
* origin. The origin (protocol, hostname, and port) must be added by this
|
|
19
19
|
* {@link FetchHandler}, typically based on authentication or other factors.
|
|
20
20
|
*/
|
|
21
|
-
path: string
|
|
21
|
+
path: `/${string}`,
|
|
22
22
|
init: RequestInit,
|
|
23
23
|
) => Promise<Response>
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Core interface for making XRPC requests.
|
|
26
|
+
* Core interface for making XRPC requests towards a specific service.
|
|
27
27
|
*
|
|
28
|
-
* An Agent encapsulates an identity and request handling for AT
|
|
29
|
-
* operations.
|
|
30
|
-
*
|
|
28
|
+
* An {@link Agent} encapsulates an identity and request handling for AT
|
|
29
|
+
* Protocol operations. Agents will typically handle authentication, service URL
|
|
30
|
+
* resolution, and other request configuration, allowing client code to make
|
|
31
|
+
* requests without needing to manage these details directly. The key component
|
|
32
|
+
* of an Agent is the {@link FetchHandler}, which is responsible for
|
|
33
|
+
* constructing the full request URL and adding any necessary headers or
|
|
34
|
+
* authentication tokens. The Agent's `did` property represents the
|
|
35
|
+
* authenticated user's DID, if available, and can be used for operations that
|
|
36
|
+
* require knowledge of the user's identity (such as creating AT Protocol
|
|
37
|
+
* records).
|
|
31
38
|
*
|
|
32
39
|
* @see {@link buildAgent} for creating (simple) Agent instances.
|
|
33
40
|
*
|
|
@@ -35,7 +42,10 @@ export type FetchHandler = (
|
|
|
35
42
|
* ```typescript
|
|
36
43
|
* const agent: Agent = {
|
|
37
44
|
* did: 'did:plc:example123',
|
|
38
|
-
* fetchHandler: (path, init) =>
|
|
45
|
+
* fetchHandler: async (path, init) => {
|
|
46
|
+
* const url = new URL(path, 'https://bsky.social')
|
|
47
|
+
* return fetch(url, init)
|
|
48
|
+
* }
|
|
39
49
|
* }
|
|
40
50
|
* ```
|
|
41
51
|
*/
|
|
@@ -46,6 +56,18 @@ export interface Agent {
|
|
|
46
56
|
fetchHandler: FetchHandler
|
|
47
57
|
}
|
|
48
58
|
|
|
59
|
+
export function isAgent(value: unknown): value is Agent {
|
|
60
|
+
return (
|
|
61
|
+
typeof value === 'object' &&
|
|
62
|
+
value !== null &&
|
|
63
|
+
'fetchHandler' in value &&
|
|
64
|
+
typeof value.fetchHandler === 'function' &&
|
|
65
|
+
(!('did' in value) ||
|
|
66
|
+
value.did === undefined ||
|
|
67
|
+
typeof value.did === 'string')
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
49
71
|
export type AgentConfig = {
|
|
50
72
|
/**
|
|
51
73
|
* The identifier (DID) of the user represented by this agent.
|
|
@@ -84,20 +106,20 @@ export type AgentOptions = AgentConfig | string | URL
|
|
|
84
106
|
/**
|
|
85
107
|
* Creates an {@link Agent} from various input types.
|
|
86
108
|
*
|
|
87
|
-
* This factory function accepts an existing Agent (returned as-is), a service
|
|
88
|
-
* or a full configuration object. It handles the common case of creating
|
|
89
|
-
* unauthenticated agent from just a service URL.
|
|
109
|
+
* This factory function accepts an existing Agent (returned as-is), a service
|
|
110
|
+
* URL, or a full configuration object. It handles the common case of creating
|
|
111
|
+
* an unauthenticated agent from just a service URL.
|
|
90
112
|
*
|
|
91
113
|
* @param options - Agent instance, configuration object, or service URL
|
|
92
114
|
* @returns A configured Agent ready for making requests
|
|
93
115
|
* @throws {TypeError} If fetch() is not available in the environment
|
|
94
116
|
*
|
|
95
|
-
* @example From URL string
|
|
117
|
+
* @example // From URL string
|
|
96
118
|
* ```typescript
|
|
97
119
|
* const agent = buildAgent('https://public.api.bsky.app')
|
|
98
120
|
* ```
|
|
99
121
|
*
|
|
100
|
-
* @example From configuration
|
|
122
|
+
* @example // From configuration
|
|
101
123
|
* ```typescript
|
|
102
124
|
* const agent = buildAgent({
|
|
103
125
|
* did: 'did:plc:example',
|
|
@@ -105,17 +127,12 @@ export type AgentOptions = AgentConfig | string | URL
|
|
|
105
127
|
* headers: { 'Authorization': 'Bearer ...' }
|
|
106
128
|
* })
|
|
107
129
|
* ```
|
|
108
|
-
*
|
|
109
|
-
* @example Pass-through existing agent
|
|
110
|
-
* ```typescript
|
|
111
|
-
* const existing: Agent = { ... }
|
|
112
|
-
* const agent = buildAgent(existing) // Returns existing unchanged
|
|
113
|
-
* ```
|
|
114
130
|
*/
|
|
131
|
+
export function buildAgent<O extends Agent | AgentOptions>(
|
|
132
|
+
options: O,
|
|
133
|
+
): O extends Agent ? O : Agent
|
|
115
134
|
export function buildAgent(options: Agent | AgentOptions): Agent {
|
|
116
|
-
if (
|
|
117
|
-
return options
|
|
118
|
-
}
|
|
135
|
+
if (isAgent(options)) return options
|
|
119
136
|
|
|
120
137
|
const config: Agent | AgentConfig =
|
|
121
138
|
typeof options === 'string' || options instanceof URL
|
package/src/client.ts
CHANGED
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
Query,
|
|
16
16
|
RecordSchema,
|
|
17
17
|
Restricted,
|
|
18
|
-
UnknownObject,
|
|
19
18
|
getMain,
|
|
20
19
|
} from '@atproto/lex-schema'
|
|
21
20
|
import { Agent, AgentOptions, buildAgent } from './agent.js'
|
|
@@ -263,9 +262,10 @@ export type ListOutput<T extends RecordSchema> = InferMethodOutputBody<
|
|
|
263
262
|
/** Records that successfully validated against the schema. */
|
|
264
263
|
records: ListRecord<Infer<T>>[]
|
|
265
264
|
// @NOTE Because the schema uses "type": "unknown" instead of an open union,
|
|
266
|
-
// we have to use
|
|
265
|
+
// we have to use LexMap instead of Unknown$TypedObject here, which is
|
|
266
|
+
// unfortunate.
|
|
267
267
|
/** Records that failed schema validation. */
|
|
268
|
-
invalid:
|
|
268
|
+
invalid: LexMap[]
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
/**
|
|
@@ -282,11 +282,12 @@ export type ListRecord<Value extends LexMap> =
|
|
|
282
282
|
* services. It provides type-safe methods for XRPC calls, record operations,
|
|
283
283
|
* and blob handling.
|
|
284
284
|
*
|
|
285
|
-
* @example Basic usage
|
|
285
|
+
* @example // Basic usage
|
|
286
286
|
* ```typescript
|
|
287
287
|
* import { Client } from '@atproto/lex'
|
|
288
288
|
*
|
|
289
|
-
* const client = new Client(
|
|
289
|
+
* const client = new Client(oauthSession)
|
|
290
|
+
*
|
|
290
291
|
* const response = await client.xrpc(app.bsky.feed.getTimeline.main, {
|
|
291
292
|
* params: { limit: 50 }
|
|
292
293
|
* })
|
|
@@ -379,11 +380,18 @@ export class Client implements Agent {
|
|
|
379
380
|
}
|
|
380
381
|
|
|
381
382
|
/**
|
|
382
|
-
*
|
|
383
|
+
* {@link Agent}'s {@link Agent.fetchHandler} implementation, which adds
|
|
384
|
+
* labelers and service proxying headers. This method allow a {@link Client}
|
|
385
|
+
* instance to be used directly as an {@link Agent} for another
|
|
386
|
+
* {@link Client}, enabling composition of headers (labelers, proxying, etc.).
|
|
387
|
+
*
|
|
383
388
|
* @param path - The request path
|
|
384
389
|
* @param init - Request initialization options
|
|
385
390
|
*/
|
|
386
|
-
public fetchHandler(
|
|
391
|
+
public fetchHandler(
|
|
392
|
+
path: `/${string}`,
|
|
393
|
+
init: RequestInit,
|
|
394
|
+
): Promise<Response> {
|
|
387
395
|
const headers = buildAtprotoHeaders({
|
|
388
396
|
headers: init.headers,
|
|
389
397
|
service: this.service,
|
|
@@ -941,7 +949,7 @@ function getLiteralRecordKey<const T extends RecordSchema>(
|
|
|
941
949
|
schema: T,
|
|
942
950
|
): InferRecordKey<T> {
|
|
943
951
|
if (schema.key.startsWith('literal:')) {
|
|
944
|
-
return schema.key.slice(8)
|
|
952
|
+
return schema.key.slice(8) as InferRecordKey<T>
|
|
945
953
|
}
|
|
946
954
|
|
|
947
955
|
throw new TypeError(
|
|
@@ -22,7 +22,7 @@ const main =
|
|
|
22
22
|
/*#__PURE__*/ l.string({ format: 'record-key', maxLength: 512 }),
|
|
23
23
|
),
|
|
24
24
|
validate: /*#__PURE__*/ l.optional(/*#__PURE__*/ l.boolean()),
|
|
25
|
-
record: /*#__PURE__*/ l.
|
|
25
|
+
record: /*#__PURE__*/ l.lexMap(),
|
|
26
26
|
swapCommit: /*#__PURE__*/ l.optional(
|
|
27
27
|
/*#__PURE__*/ l.string({ format: 'cid' }),
|
|
28
28
|
),
|
|
@@ -35,17 +35,25 @@ const main =
|
|
|
35
35
|
(() => RepoDefs.commitMeta) as any,
|
|
36
36
|
),
|
|
37
37
|
),
|
|
38
|
-
validationStatus: /*#__PURE__*/ l.optional(
|
|
38
|
+
validationStatus: /*#__PURE__*/ l.optional(
|
|
39
|
+
/*#__PURE__*/ l.string<{ knownValues: ['valid', 'unknown'] }>(),
|
|
40
|
+
),
|
|
39
41
|
}),
|
|
40
42
|
['InvalidSwap'],
|
|
41
43
|
)
|
|
42
44
|
export { main }
|
|
43
45
|
|
|
44
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
45
|
-
export type Input = l.InferMethodInput<typeof main>
|
|
46
|
-
export type InputBody = l.InferMethodInputBody<
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
47
|
+
export type $Input<B = l.BinaryData> = l.InferMethodInput<typeof main, B>
|
|
48
|
+
export type $InputBody<B = l.BinaryData> = l.InferMethodInputBody<
|
|
49
|
+
typeof main,
|
|
50
|
+
B
|
|
51
|
+
>
|
|
52
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
53
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
54
|
+
typeof main,
|
|
55
|
+
B
|
|
56
|
+
>
|
|
49
57
|
|
|
50
58
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
51
59
|
$params = /*#__PURE__*/ main.parameters,
|
|
@@ -37,11 +37,17 @@ const main =
|
|
|
37
37
|
)
|
|
38
38
|
export { main }
|
|
39
39
|
|
|
40
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
41
|
-
export type Input = l.InferMethodInput<typeof main>
|
|
42
|
-
export type InputBody = l.InferMethodInputBody<
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
41
|
+
export type $Input<B = l.BinaryData> = l.InferMethodInput<typeof main, B>
|
|
42
|
+
export type $InputBody<B = l.BinaryData> = l.InferMethodInputBody<
|
|
43
|
+
typeof main,
|
|
44
|
+
B
|
|
45
|
+
>
|
|
46
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
47
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
48
|
+
typeof main,
|
|
49
|
+
B
|
|
50
|
+
>
|
|
45
51
|
|
|
46
52
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
47
53
|
$params = /*#__PURE__*/ main.parameters,
|
|
@@ -22,15 +22,18 @@ const main =
|
|
|
22
22
|
/*#__PURE__*/ l.jsonPayload({
|
|
23
23
|
uri: /*#__PURE__*/ l.string({ format: 'at-uri' }),
|
|
24
24
|
cid: /*#__PURE__*/ l.optional(/*#__PURE__*/ l.string({ format: 'cid' })),
|
|
25
|
-
value: /*#__PURE__*/ l.
|
|
25
|
+
value: /*#__PURE__*/ l.lexMap(),
|
|
26
26
|
}),
|
|
27
27
|
['RecordNotFound'],
|
|
28
28
|
)
|
|
29
29
|
export { main }
|
|
30
30
|
|
|
31
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
32
|
-
export type Output = l.InferMethodOutput<typeof main>
|
|
33
|
-
export type OutputBody = l.InferMethodOutputBody<
|
|
31
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
32
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
33
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
34
|
+
typeof main,
|
|
35
|
+
B
|
|
36
|
+
>
|
|
34
37
|
|
|
35
38
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
36
39
|
$params = main.parameters,
|
|
@@ -34,9 +34,12 @@ const main =
|
|
|
34
34
|
)
|
|
35
35
|
export { main }
|
|
36
36
|
|
|
37
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
38
|
-
export type Output = l.InferMethodOutput<typeof main>
|
|
39
|
-
export type OutputBody = l.InferMethodOutputBody<
|
|
37
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
38
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
39
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
40
|
+
typeof main,
|
|
41
|
+
B
|
|
42
|
+
>
|
|
40
43
|
|
|
41
44
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
42
45
|
$params = main.parameters,
|
|
@@ -46,7 +49,7 @@ type Record$0 = {
|
|
|
46
49
|
$type?: 'com.atproto.repo.listRecords#record'
|
|
47
50
|
uri: l.AtUriString
|
|
48
51
|
cid: l.CidString
|
|
49
|
-
value: l.
|
|
52
|
+
value: l.LexMap
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
export type { Record$0 as Record }
|
|
@@ -57,7 +60,7 @@ const record$0 = /*#__PURE__*/ l.typedObject<Record$0>(
|
|
|
57
60
|
/*#__PURE__*/ l.object({
|
|
58
61
|
uri: /*#__PURE__*/ l.string({ format: 'at-uri' }),
|
|
59
62
|
cid: /*#__PURE__*/ l.string({ format: 'cid' }),
|
|
60
|
-
value: /*#__PURE__*/ l.
|
|
63
|
+
value: /*#__PURE__*/ l.lexMap(),
|
|
61
64
|
}),
|
|
62
65
|
)
|
|
63
66
|
|
|
@@ -20,7 +20,7 @@ const main =
|
|
|
20
20
|
collection: /*#__PURE__*/ l.string({ format: 'nsid' }),
|
|
21
21
|
rkey: /*#__PURE__*/ l.string({ format: 'record-key', maxLength: 512 }),
|
|
22
22
|
validate: /*#__PURE__*/ l.optional(/*#__PURE__*/ l.boolean()),
|
|
23
|
-
record: /*#__PURE__*/ l.
|
|
23
|
+
record: /*#__PURE__*/ l.lexMap(),
|
|
24
24
|
swapRecord: /*#__PURE__*/ l.optional(
|
|
25
25
|
/*#__PURE__*/ l.nullable(/*#__PURE__*/ l.string({ format: 'cid' })),
|
|
26
26
|
),
|
|
@@ -36,17 +36,25 @@ const main =
|
|
|
36
36
|
(() => RepoDefs.commitMeta) as any,
|
|
37
37
|
),
|
|
38
38
|
),
|
|
39
|
-
validationStatus: /*#__PURE__*/ l.optional(
|
|
39
|
+
validationStatus: /*#__PURE__*/ l.optional(
|
|
40
|
+
/*#__PURE__*/ l.string<{ knownValues: ['valid', 'unknown'] }>(),
|
|
41
|
+
),
|
|
40
42
|
}),
|
|
41
43
|
['InvalidSwap'],
|
|
42
44
|
)
|
|
43
45
|
export { main }
|
|
44
46
|
|
|
45
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
46
|
-
export type Input = l.InferMethodInput<typeof main>
|
|
47
|
-
export type InputBody = l.InferMethodInputBody<
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
48
|
+
export type $Input<B = l.BinaryData> = l.InferMethodInput<typeof main, B>
|
|
49
|
+
export type $InputBody<B = l.BinaryData> = l.InferMethodInputBody<
|
|
50
|
+
typeof main,
|
|
51
|
+
B
|
|
52
|
+
>
|
|
53
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
54
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
55
|
+
typeof main,
|
|
56
|
+
B
|
|
57
|
+
>
|
|
50
58
|
|
|
51
59
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
52
60
|
$params = /*#__PURE__*/ main.parameters,
|
|
@@ -21,11 +21,17 @@ const main =
|
|
|
21
21
|
)
|
|
22
22
|
export { main }
|
|
23
23
|
|
|
24
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
25
|
-
export type Input = l.InferMethodInput<typeof main>
|
|
26
|
-
export type InputBody = l.InferMethodInputBody<
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
25
|
+
export type $Input<B = l.BinaryData> = l.InferMethodInput<typeof main, B>
|
|
26
|
+
export type $InputBody<B = l.BinaryData> = l.InferMethodInputBody<
|
|
27
|
+
typeof main,
|
|
28
|
+
B
|
|
29
|
+
>
|
|
30
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
31
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
32
|
+
typeof main,
|
|
33
|
+
B
|
|
34
|
+
>
|
|
29
35
|
|
|
30
36
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
31
37
|
$params = /*#__PURE__*/ main.parameters,
|
|
@@ -28,9 +28,12 @@ const main =
|
|
|
28
28
|
)
|
|
29
29
|
export { main }
|
|
30
30
|
|
|
31
|
-
export type Params = l.InferMethodParams<typeof main>
|
|
32
|
-
export type Output = l.InferMethodOutput<typeof main>
|
|
33
|
-
export type OutputBody = l.InferMethodOutputBody<
|
|
31
|
+
export type $Params = l.InferMethodParams<typeof main>
|
|
32
|
+
export type $Output<B = l.BinaryData> = l.InferMethodOutput<typeof main, B>
|
|
33
|
+
export type $OutputBody<B = l.BinaryData> = l.InferMethodOutputBody<
|
|
34
|
+
typeof main,
|
|
35
|
+
B
|
|
36
|
+
>
|
|
34
37
|
|
|
35
38
|
export const $lxm = /*#__PURE__*/ main.nsid,
|
|
36
39
|
$params = main.parameters,
|
package/src/xrpc.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
InferInput,
|
|
5
5
|
InferPayload,
|
|
6
6
|
Main,
|
|
7
|
+
NsidString,
|
|
7
8
|
Params,
|
|
8
9
|
Payload,
|
|
9
10
|
Procedure,
|
|
@@ -12,7 +13,7 @@ import {
|
|
|
12
13
|
Subscription,
|
|
13
14
|
getMain,
|
|
14
15
|
} from '@atproto/lex-schema'
|
|
15
|
-
import { Agent } from './agent.js'
|
|
16
|
+
import { Agent, AgentOptions, buildAgent } from './agent.js'
|
|
16
17
|
import { XrpcFailure, asXrpcFailure } from './errors.js'
|
|
17
18
|
import { XrpcResponse } from './response.js'
|
|
18
19
|
import { BinaryBodyInit, CallOptions } from './types.js'
|
|
@@ -77,8 +78,7 @@ export type XrpcOptions<M extends Procedure | Query = Procedure | Query> =
|
|
|
77
78
|
/**
|
|
78
79
|
* Makes an XRPC request and throws on failure.
|
|
79
80
|
*
|
|
80
|
-
* This is the low-level function for making XRPC calls.
|
|
81
|
-
* prefer using {@link Client.xrpc} which provides a more ergonomic API.
|
|
81
|
+
* This is the low-level function for making XRPC calls.
|
|
82
82
|
*
|
|
83
83
|
* @param agent - The {@link Agent} to use for making the request
|
|
84
84
|
* @param ns - The lexicon method definition
|
|
@@ -88,28 +88,35 @@ export type XrpcOptions<M extends Procedure | Query = Procedure | Query> =
|
|
|
88
88
|
*
|
|
89
89
|
* @example
|
|
90
90
|
* ```typescript
|
|
91
|
+
* const response = await xrpc('https://bsky.network', com.atproto.identity.resolveHandle, {
|
|
92
|
+
* params: { handle: "atproto.com" }
|
|
93
|
+
* })
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
91
98
|
* const response = await xrpc(agent, app.bsky.feed.getTimeline.main, {
|
|
92
99
|
* params: { limit: 50 }
|
|
93
100
|
* })
|
|
94
101
|
* ```
|
|
95
102
|
*/
|
|
96
103
|
export async function xrpc<const M extends Query | Procedure>(
|
|
97
|
-
|
|
104
|
+
agentOpts: Agent | AgentOptions,
|
|
98
105
|
ns: NonNullable<unknown> extends XrpcOptions<M>
|
|
99
106
|
? Main<M>
|
|
100
107
|
: Restricted<'This XRPC method requires an "options" argument'>,
|
|
101
108
|
): Promise<XrpcResponse<M>>
|
|
102
109
|
export async function xrpc<const M extends Query | Procedure>(
|
|
103
|
-
|
|
110
|
+
agentOpts: Agent | AgentOptions,
|
|
104
111
|
ns: Main<M>,
|
|
105
112
|
options: XrpcOptions<M>,
|
|
106
113
|
): Promise<XrpcResponse<M>>
|
|
107
114
|
export async function xrpc<const M extends Query | Procedure>(
|
|
108
|
-
|
|
115
|
+
agentOpts: Agent | AgentOptions,
|
|
109
116
|
ns: Main<M>,
|
|
110
117
|
options: XrpcOptions<M> = {} as XrpcOptions<M>,
|
|
111
118
|
): Promise<XrpcResponse<M>> {
|
|
112
|
-
const response = await xrpcSafe<M>(
|
|
119
|
+
const response = await xrpcSafe<M>(agentOpts, ns, options)
|
|
113
120
|
if (response.success) return response
|
|
114
121
|
else throw response
|
|
115
122
|
}
|
|
@@ -141,7 +148,7 @@ export type XrpcResult<M extends Procedure | Query> =
|
|
|
141
148
|
*
|
|
142
149
|
* @example
|
|
143
150
|
* ```typescript
|
|
144
|
-
* const result = await xrpcSafe(
|
|
151
|
+
* const result = await xrpcSafe('https://example.com', app.bsky.actor.getProfile, {
|
|
145
152
|
* params: { actor: 'alice.bsky.social' }
|
|
146
153
|
* })
|
|
147
154
|
*
|
|
@@ -153,24 +160,25 @@ export type XrpcResult<M extends Procedure | Query> =
|
|
|
153
160
|
* ```
|
|
154
161
|
*/
|
|
155
162
|
export async function xrpcSafe<const M extends Query | Procedure>(
|
|
156
|
-
|
|
163
|
+
agentOpts: Agent | AgentOptions,
|
|
157
164
|
ns: NonNullable<unknown> extends XrpcOptions<M>
|
|
158
165
|
? Main<M>
|
|
159
166
|
: Restricted<'This XRPC method requires an "options" argument'>,
|
|
160
167
|
): Promise<XrpcResult<M>>
|
|
161
168
|
export async function xrpcSafe<const M extends Query | Procedure>(
|
|
162
|
-
|
|
169
|
+
agentOpts: Agent | AgentOptions,
|
|
163
170
|
ns: Main<M>,
|
|
164
171
|
options: XrpcOptions<M>,
|
|
165
172
|
): Promise<XrpcResult<M>>
|
|
166
173
|
export async function xrpcSafe<const M extends Query | Procedure>(
|
|
167
|
-
|
|
174
|
+
agentOpts: Agent | AgentOptions,
|
|
168
175
|
ns: Main<M>,
|
|
169
176
|
options: XrpcOptions<M> = {} as XrpcOptions<M>,
|
|
170
177
|
): Promise<XrpcResult<M>> {
|
|
171
178
|
options.signal?.throwIfAborted()
|
|
172
179
|
const method: M = getMain(ns)
|
|
173
180
|
try {
|
|
181
|
+
const agent = buildAgent(agentOpts)
|
|
174
182
|
const url = xrpcRequestUrl(method, options)
|
|
175
183
|
const request = xrpcRequestInit(method, options)
|
|
176
184
|
const response = await agent.fetchHandler(url, request)
|
|
@@ -183,14 +191,14 @@ export async function xrpcSafe<const M extends Query | Procedure>(
|
|
|
183
191
|
function xrpcRequestUrl<M extends Procedure | Query | Subscription>(
|
|
184
192
|
method: M,
|
|
185
193
|
options: CallOptions & { params?: Params },
|
|
186
|
-
) {
|
|
187
|
-
const path = `/xrpc/${method.nsid}`
|
|
194
|
+
): `/xrpc/${NsidString}${'' | `?${string}`}` {
|
|
195
|
+
const path = `/xrpc/${method.nsid}` as const
|
|
188
196
|
|
|
189
197
|
const queryString = method.parameters
|
|
190
198
|
?.toURLSearchParams(options.params ?? {})
|
|
191
199
|
.toString()
|
|
192
200
|
|
|
193
|
-
return queryString ? `${path}?${queryString}` : path
|
|
201
|
+
return queryString ? (`${path}?${queryString}` as const) : path
|
|
194
202
|
}
|
|
195
203
|
|
|
196
204
|
function xrpcRequestInit<T extends Procedure | Query>(
|