feat: add rest support
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import z, { ZodType } from "zod";
|
||||
|
||||
import type { RelayAdapter } from "./adapter.ts";
|
||||
import { Procedure, type Procedures } from "./procedure.ts";
|
||||
import type { RelayAdapter, RelayRESTInput } from "./adapter.ts";
|
||||
import { Procedure } from "./procedure.ts";
|
||||
import type { Relays } from "./relay.ts";
|
||||
import { Route } from "./route.ts";
|
||||
|
||||
/**
|
||||
* Make a new relay client instance.
|
||||
@@ -9,8 +11,8 @@ import { Procedure, type Procedures } from "./procedure.ts";
|
||||
* @param config - Client configuration.
|
||||
* @param procedures - Map of procedures to make available to the client.
|
||||
*/
|
||||
export function makeRelayClient<TProcedures extends Procedures>(config: RelayClientConfig, procedures: TProcedures): RelayClient<TProcedures> {
|
||||
return mapProcedures(procedures, config.adapter);
|
||||
export function makeRelayClient<TRelays extends Relays>(config: RelayClientConfig, relays: TRelays): RelayClient<TRelays> {
|
||||
return mapRelays(relays, config.adapter);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -19,23 +21,59 @@ export function makeRelayClient<TProcedures extends Procedures>(config: RelayCli
|
||||
|--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
function mapProcedures<TProcedures extends Procedures>(procedures: TProcedures, adapter: RelayAdapter): RelayClient<TProcedures> {
|
||||
function mapRelays<TRelays extends Relays>(relays: TRelays, adapter: RelayAdapter): RelayClient<TRelays> {
|
||||
const client: any = {};
|
||||
for (const key in procedures) {
|
||||
const entry = procedures[key];
|
||||
if (entry instanceof Procedure) {
|
||||
for (const key in relays) {
|
||||
const relay = relays[key];
|
||||
if (relay instanceof Procedure) {
|
||||
client[key] = async (params: unknown) => {
|
||||
const response = await adapter.send({ method: entry.method, params });
|
||||
const response = await adapter.send({ method: relay.method, params });
|
||||
if ("error" in response) {
|
||||
throw new Error(response.error.message);
|
||||
}
|
||||
if ("result" in response && entry.state.result !== undefined) {
|
||||
return entry.state.result.parseAsync(response.result);
|
||||
if ("result" in response && relay.state.result !== undefined) {
|
||||
return relay.state.result.parseAsync(response.result);
|
||||
}
|
||||
return response.result;
|
||||
};
|
||||
} else if (relay instanceof Route) {
|
||||
client[key] = async (...args: any[]) => {
|
||||
const input: RelayRESTInput = { method: relay.state.method, url: `${adapter.url}${relay.state.path}`, query: "" };
|
||||
|
||||
let index = 0; // argument incrementor
|
||||
|
||||
if (relay.state.params !== undefined) {
|
||||
const params = args[index++] as { [key: string]: string };
|
||||
for (const key in params) {
|
||||
input.url = input.url.replace(`:${key}`, params[key]);
|
||||
}
|
||||
}
|
||||
|
||||
if (relay.state.query !== undefined) {
|
||||
const query = args[index++] as { [key: string]: string };
|
||||
const pieces: string[] = [];
|
||||
for (const key in query) {
|
||||
pieces.push(`${key}=${query[key]}`);
|
||||
}
|
||||
if (pieces.length > 0) {
|
||||
input.query = `?${pieces.join("&")}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (relay.state.body !== undefined) {
|
||||
input.body = JSON.stringify(args[index++]);
|
||||
}
|
||||
|
||||
// ### Fetch
|
||||
|
||||
const data = await adapter.fetch(input);
|
||||
if (relay.state.output !== undefined) {
|
||||
return relay.state.output.parse(data);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
} else {
|
||||
client[key] = mapProcedures(entry, adapter);
|
||||
client[key] = mapRelays(relay, adapter);
|
||||
}
|
||||
}
|
||||
return client;
|
||||
@@ -47,16 +85,20 @@ function mapProcedures<TProcedures extends Procedures>(procedures: TProcedures,
|
||||
|--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
export type RelayClient<TProcedures extends Procedures> = {
|
||||
[TKey in keyof TProcedures]: TProcedures[TKey] extends Procedure<infer TState>
|
||||
export type RelayClient<TRelays extends Relays> = {
|
||||
[TKey in keyof TRelays]: TRelays[TKey] extends Procedure<infer TState>
|
||||
? TState["params"] extends ZodType
|
||||
? (params: z.infer<TState["params"]>) => Promise<TState["result"] extends ZodType ? z.infer<TState["result"]> : void>
|
||||
: () => Promise<TState["result"] extends ZodType ? z.infer<TState["result"]> : void>
|
||||
: TProcedures[TKey] extends Procedures
|
||||
? RelayClient<TProcedures[TKey]>
|
||||
: never;
|
||||
: TRelays[TKey] extends Route
|
||||
? (...args: TRelays[TKey]["args"]) => Promise<RelayRouteResponse<TRelays[TKey]>>
|
||||
: TRelays[TKey] extends Relays
|
||||
? RelayClient<TRelays[TKey]>
|
||||
: never;
|
||||
};
|
||||
|
||||
type RelayRouteResponse<TRoute extends Route> = TRoute["state"]["output"] extends ZodType ? z.infer<TRoute["state"]["output"]> : void;
|
||||
|
||||
export type RelayClientConfig = {
|
||||
adapter: RelayAdapter;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user