Suite of AT Protocol TypeScript libraries built on web standards
21
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: xrpc standalone export

+92 -1
+38
xrpc/client.ts
··· 25 25 } from "./util.ts"; 26 26 import type { DidString } from "@atp/lex"; 27 27 28 + export function xrpc<const M extends XrpcMethodLike>( 29 + agentOpts: Agent | AgentOptions, 30 + input: M, 31 + ): Promise<XRPCResponse>; 32 + export function xrpc<const M extends XrpcMethodLike, const O>( 33 + agentOpts: Agent | AgentOptions, 34 + input: M, 35 + options: O & XrpcCallCompatibleOptions<M, O>, 36 + ): Promise<XRPCResponse>; 37 + export async function xrpc<const M extends XrpcMethodLike>( 38 + agentOpts: Agent | AgentOptions, 39 + input: M, 40 + options: XrpcCallOptions<M> = {} as XrpcCallOptions<M>, 41 + ): Promise<XRPCResponse> { 42 + return await new Client(agentOpts).xrpc(input, options); 43 + } 44 + 45 + export function xrpcSafe<const M extends XrpcMethodLike>( 46 + agentOpts: Agent | AgentOptions, 47 + input: M, 48 + ): Promise<XRPCError | XRPCResponse>; 49 + export function xrpcSafe<const M extends XrpcMethodLike, const O>( 50 + agentOpts: Agent | AgentOptions, 51 + input: M, 52 + options: O & XrpcCallCompatibleOptions<M, O>, 53 + ): Promise<XRPCError | XRPCResponse>; 54 + export async function xrpcSafe<const M extends XrpcMethodLike>( 55 + agentOpts: Agent | AgentOptions, 56 + input: M, 57 + options: XrpcCallOptions<M> = {} as XrpcCallOptions<M>, 58 + ): Promise<XRPCError | XRPCResponse> { 59 + return await new Client(agentOpts).xrpcSafe(input, options); 60 + } 61 + 28 62 export class Client { 29 63 readonly agent: Agent; 30 64 readonly fetchHandler: FetchHandler; ··· 324 358 325 359 if ("main" in input && isXrpcMethod(input.main)) { 326 360 return input.main; 361 + } 362 + 363 + if ("Main" in input && isXrpcMethod(input.Main)) { 364 + return input.Main; 327 365 } 328 366 329 367 throw new TypeError("Expected an XRPC method or a namespace with main");
+54 -1
xrpc/tests/client_test.ts
··· 1 1 import { l } from "@atp/lex"; 2 2 import { assertEquals, assertRejects } from "@std/assert"; 3 - import { Client } from "../mod.ts"; 3 + import { Client, xrpc, xrpcSafe } from "../mod.ts"; 4 4 import type { XrpcCallCompatibleOptions } from "../types.ts"; 5 5 import { XRPCError, XRPCInvalidResponseError } from "../types.ts"; 6 6 ··· 47 47 assertEquals(result.data, { value: "ok" }); 48 48 }); 49 49 50 + Deno.test("calls top-level xrpc", async () => { 51 + const method = l.query( 52 + "io.example.query", 53 + l.params({ limit: l.optional(l.integer()) }), 54 + l.jsonPayload({ value: l.string() }), 55 + ); 56 + 57 + const result = await xrpc( 58 + (url, init) => { 59 + assertEquals(url, "/xrpc/io.example.query?limit=6"); 60 + assertEquals(init.method, "get"); 61 + return Promise.resolve(Response.json({ value: "ok" })); 62 + }, 63 + method, 64 + { 65 + params: { limit: 6 }, 66 + }, 67 + ); 68 + 69 + assertEquals(result.data, { value: "ok" }); 70 + }); 71 + 50 72 Deno.test("narrows xrpcSafe success results on success flag", async () => { 51 73 const method = l.query( 52 74 "io.example.query", ··· 70 92 assertEquals(result.data, { value: "ok" }); 71 93 } else { 72 94 throw new Error(result.error); 95 + } 96 + }); 97 + 98 + Deno.test("calls top-level xrpcSafe", async () => { 99 + const method = l.query( 100 + "io.example.query", 101 + l.params({ limit: l.optional(l.integer()) }), 102 + l.jsonPayload({ value: l.string() }), 103 + ); 104 + 105 + const result = await xrpcSafe( 106 + () => 107 + Promise.resolve( 108 + Response.json( 109 + { error: "BadRequest", message: "nope" }, 110 + { status: 400 }, 111 + ), 112 + ), 113 + method, 114 + { 115 + params: { limit: 2 }, 116 + }, 117 + ); 118 + 119 + assertEquals(result.success, false); 120 + 121 + if (!result.success) { 122 + assertEquals(result.error, "BadRequest"); 123 + assertEquals(result.message, "nope"); 124 + } else { 125 + throw new Error(JSON.stringify(result.data)); 73 126 } 74 127 }); 75 128