Middleware
Run code around a procedure - add a user, skip the handler, or change the result.
.use(mw) wraps a procedure. return next({ ctx }) continues and merges context. Skip next() to skip the handler. await next() to wrap the result.
import { class RpcErrorRpcError, const tacho: <C extends Context = {}>() => Builder<C, undefined, unique symbol>tacho } from "tacho";
const const rpc: Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
rpc = tacho<{
req: Request;
user?: string;
}>(): Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
tacho<{ req: Requestreq: Request; user?: string | undefineduser?: string }>();
const const protect: Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
protect = const rpc: Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
rpc.function use(mw: Middleware<{
req: Request;
user?: string;
}>): Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
use(async ({ ctx: {
req: Request;
user?: string;
}
ctx, next: (opts?: {
ctx: Partial<{
req: Request;
user?: string;
}>;
} | undefined) => Promise<unknown>
next }) => {
const const user: string | nulluser = ctx: {
req: Request;
user?: string;
}
ctx.req: Requestreq.Request.headers: HeadersThe **`headers`** read-only property of the Request interface contains the Headers object associated with the request.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/headers)headers.Headers.get(name: string): string | nullThe **`get()`** method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get)get("x-user");
if (!const user: string | nulluser) {
throw new new RpcError({ code, message, data }: {
code: number;
message: string;
data?: unknown;
}): RpcError
RpcError({ code: numbercode: -32001, message: stringmessage: "unauthorized" });
}
return next: (opts?: {
ctx: Partial<{
req: Request;
user?: string;
}>;
} | undefined) => Promise<unknown>
next({ ctx: Partial<{
req: Request;
user?: string;
}>
ctx: { user?: string | undefineduser } });
});
export const const router: {
me: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
greet: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
cached: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string>;
}
router = const rpc: <{
me: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
greet: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
cached: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string>;
}>(def: {
me: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
greet: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
cached: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string>;
}) => {
me: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
greet: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>;
cached: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string>;
}
rpc({
me: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>
me: const protect: Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
protect.run: <string | undefined>(fn: (opts: {
input: undefined;
ctx: {
req: Request;
user?: string;
};
}) => string | Promise<string | undefined> | undefined) => ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>
run(({ ctx: {
req: Request;
user?: string;
}
ctx }) => ctx: {
req: Request;
user?: string;
}
ctx.user?: string | undefineduser),
greet: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>
greet: const protect: Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
protect
.function use(mw: Middleware<{
req: Request;
user?: string;
}>): Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
use(async ({ next: (opts?: {
ctx: Partial<{
req: Request;
user?: string;
}>;
} | undefined) => Promise<unknown>
next }) => `hi ${await next: (opts?: {
ctx: Partial<{
req: Request;
user?: string;
}>;
} | undefined) => Promise<unknown>
next()}`)
.run: <string | undefined>(fn: (opts: {
input: undefined;
ctx: {
req: Request;
user?: string;
};
}) => string | Promise<string | undefined> | undefined) => ProcedureDef<{
req: Request;
user?: string;
}, undefined, string | undefined>
run(({ ctx: {
req: Request;
user?: string;
}
ctx }) => ctx: {
req: Request;
user?: string;
}
ctx.user?: string | undefineduser),
cached: ProcedureDef<{
req: Request;
user?: string;
}, undefined, string>
cached: const protect: Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
protect.function use(mw: Middleware<{
req: Request;
user?: string;
}>): Builder<{
req: Request;
user?: string;
}, undefined, unique symbol>
use(async () => "from-cache").run: <string>(fn: (opts: {
input: undefined;
ctx: {
req: Request;
user?: string;
};
}) => string | Promise<string>) => ProcedureDef<{
req: Request;
user?: string;
}, undefined, string>
run(() => "handler"),
});