Skip to content
Oxide
Esc
navigateopen⌘Jpreview

Router

Group procedures into a router, nest them, check their inputs, and call them in the same process.

tacho() creates a procedure builder. Call it as rpc({ ... }) to make a router.

import { const tacho: <C extends Context = {}>() => Builder<C, undefined, unique symbol>tacho } from "tacho";
import { import zz } from "zod";

const const rpc: Builder<{}, undefined, unique symbol>rpc = tacho<{}>(): Builder<{}, undefined, unique symbol>tacho();

export const 
const app: {
    ping: ProcedureDef<{}, undefined, "pong">;
    user: {
        get: ProcedureDef<{}, {
            id: string;
        }, {
            id: string;
            name: string;
        }>;
    };
}
app
=
const rpc: <{
    ping: ProcedureDef<{}, undefined, "pong">;
    user: {
        get: ProcedureDef<{}, {
            id: string;
        }, {
            id: string;
            name: string;
        }>;
    };
}>(def: {
    ping: ProcedureDef<{}, undefined, "pong">;
    user: {
        get: ProcedureDef<{}, {
            id: string;
        }, {
            id: string;
            name: string;
        }>;
    };
}) => {
    ping: ProcedureDef<{}, undefined, "pong">;
    user: {
        get: ProcedureDef<{}, {
            id: string;
        }, {
            id: string;
            name: string;
        }>;
    };
}
rpc
({
ping: ProcedureDef<{}, undefined, "pong">ping: const rpc: Builder<{}, undefined, unique symbol>rpc.
run: <"pong">(fn: (opts: {
    input: undefined;
    ctx: {};
}) => "pong" | Promise<"pong">) => ProcedureDef<{}, undefined, "pong">
run
(() => "pong" as type const = "pong"const),
user: {
    get: ProcedureDef<{}, {
        id: string;
    }, {
        id: string;
        name: string;
    }>;
}
user
: {
get: ProcedureDef<{}, {
    id: string;
}, {
    id: string;
    name: string;
}>
get
: const rpc: Builder<{}, undefined, unique symbol>rpc
.
input<{
    id: string;
}>(schema: Schema<{
    id: string;
}>): Builder<{}, {
    id: string;
}, unique symbol>
input
(import zz.
function object<{
    id: z.ZodString;
}>(shape?: {
    id: z.ZodString;
} | undefined, params?: string | {
    error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
    message?: string | undefined | undefined;
} | undefined): z.ZodObject<{
    id: z.ZodString;
}, z.core.$strip>
object
({ id: z.ZodStringid: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string() }))
.
output<{
    id: string;
    name: string;
}>(schema: Schema<{
    id: string;
    name: string;
}>): Builder<{}, {
    id: string;
}, {
    id: string;
    name: string;
}>
output
(import zz.
function object<{
    id: z.ZodString;
    name: z.ZodString;
}>(shape?: {
    id: z.ZodString;
    name: z.ZodString;
} | undefined, params?: string | {
    error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
    message?: string | undefined | undefined;
} | undefined): z.ZodObject<{
    id: z.ZodString;
    name: z.ZodString;
}, z.core.$strip>
object
({ id: z.ZodStringid: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string(), name: z.ZodStringname: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string() }))
.
run: (fn: (opts: {
    input: {
        id: string;
    };
    ctx: {};
}) => HandlerResult<{
    id: string;
    name: string;
}>) => ProcedureDef<{}, {
    id: string;
}, {
    id: string;
    name: string;
}>
run
(({
input: {
    id: string;
}
input
}) => ({ id: stringid:
input: {
    id: string;
}
input
.id: stringid, name: stringname: "Ada" })),
}, });
  • .input(schema) - Standard Schema. Failed input is INVALID_PARAMS.
  • .output(schema) - Failed output is INTERNAL_ERROR. Streams check each yield.
  • .run(fn) - Terminal. fn gets { input, ctx }. Return a value, a Promise, or an async function*.

No .input() → params are untyped / unused. Nested paths are user.get.

Was this page helpful?