Middlewares
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Puedes añadir middleware(s) a un procedimiento usando el método t.procedure.use(). Los middleware(s) envolverán la invocación del procedimiento y deben pasar su valor de retorno.
Autorización
En el ejemplo siguiente, cualquier llamada a adminProcedure verificará que el usuario sea "admin" antes de ejecutarse.
tsimport {TRPCError ,initTRPC } from '@trpc/server';interfaceContext {user ?: {id : string;isAdmin : boolean;// [..]};}constt =initTRPC .context <Context >().create ();export constpublicProcedure =t .procedure ;export constrouter =t .router ;export constadminProcedure =publicProcedure .use (async (opts ) => {const {ctx } =opts ;if (!ctx .user ?.isAdmin ) {throw newTRPCError ({code : 'UNAUTHORIZED' });}returnopts .next ({ctx : {user :ctx .user ,},});});
tsimport {TRPCError ,initTRPC } from '@trpc/server';interfaceContext {user ?: {id : string;isAdmin : boolean;// [..]};}constt =initTRPC .context <Context >().create ();export constpublicProcedure =t .procedure ;export constrouter =t .router ;export constadminProcedure =publicProcedure .use (async (opts ) => {const {ctx } =opts ;if (!ctx .user ?.isAdmin ) {throw newTRPCError ({code : 'UNAUTHORIZED' });}returnopts .next ({ctx : {user :ctx .user ,},});});
tsimport {adminProcedure ,publicProcedure ,router } from './trpc';constadminRouter =router ({secretPlace :adminProcedure .query (() => 'a key'),});export constappRouter =router ({foo :publicProcedure .query (() => 'bar'),admin :adminRouter ,});
tsimport {adminProcedure ,publicProcedure ,router } from './trpc';constadminRouter =router ({secretPlace :adminProcedure .query (() => 'a key'),});export constappRouter =router ({foo :publicProcedure .query (() => 'bar'),admin :adminRouter ,});
Consulta Manejo de errores para aprender más sobre el TRPCError lanzado en el ejemplo anterior.
Registro (Logging)
En el ejemplo siguiente, los tiempos de las consultas se registran automáticamente.
tsexport constloggedProcedure =publicProcedure .use (async (opts ) => {conststart =Date .now ();constresult = awaitopts .next ();constdurationMs =Date .now () -start ;constmeta = {path :opts .path ,type :opts .type ,durationMs };result .ok ?console .log ('OK request timing:',meta ):console .error ('Non-OK request timing',meta );returnresult ;});
tsexport constloggedProcedure =publicProcedure .use (async (opts ) => {conststart =Date .now ();constresult = awaitopts .next ();constdurationMs =Date .now () -start ;constmeta = {path :opts .path ,type :opts .type ,durationMs };result .ok ?console .log ('OK request timing:',meta ):console .error ('Non-OK request timing',meta );returnresult ;});
tsimport { loggedProcedure, router } from './trpc';export const appRouter= router({ foo: loggedProcedure.query(() => 'bar'),abc:loggedProcedure .query (() => 'def'), });
tsimport { loggedProcedure, router } from './trpc';export const appRouter= router({ foo: loggedProcedure.query(() => 'bar'),abc: loggedProcedure. query (() => 'def'), });
Extensión del Contexto
La "Extensión del Contexto" permite que los middleware añadan y sobrescriban claves en el contexto de un procedimiento base de manera tipada.
A continuación tenemos un ejemplo de un middleware que modifica propiedades de un contexto; estos cambios luego estarán disponibles para todos los consumidores encadenados, como otros middleware y procedimientos:
tstypeContext = {// user is nullableuser ?: {id : string;};};constprotectedProcedure =publicProcedure .use (async functionisAuthed (opts ) {const {ctx } =opts ;// `ctx.user` is nullableif (!ctx .user ) {throw newTRPCError ({code : 'UNAUTHORIZED' });}returnopts .next ({ctx : {// ✅ user value is known to be non-null nowuser :ctx .user ,},});});protectedProcedure .query ((opts ) => {const {ctx } =opts ;returnctx .user ;});
tstypeContext = {// user is nullableuser ?: {id : string;};};constprotectedProcedure =publicProcedure .use (async functionisAuthed (opts ) {const {ctx } =opts ;// `ctx.user` is nullableif (!ctx .user ) {throw newTRPCError ({code : 'UNAUTHORIZED' });}returnopts .next ({ctx : {// ✅ user value is known to be non-null nowuser :ctx .user ,},});});protectedProcedure .query ((opts ) => {const {ctx } =opts ;returnctx .user ;});
Usando .concat() para crear middleware y plugins reutilizables
- Crear middleware con
t.middlewaretiene la limitación de que el tipoContextestá vinculado al tipoContextde la instancia tRPC. - Crear middleware con
experimental_standaloneMiddleware()tiene la limitación de que no puedes definir analizadores de entrada y elementos similares vinculados a tu módulo.
tRPC tiene una API llamada .concat() que te permite definir independientemente un procedimiento parcial que puede usarse con cualquier instancia tRPC que coincida con el contexto y metadatos del plugin.
Este asistente está dirigido principalmente a la creación de plugins y bibliotecas con tRPC.
ts// ------------------------------------------------// 🧩🧩🧩 a library creating a reusable plugin 🧩🧩🧩// @filename: myPlugin.tsimport {initTRPC ,TRPCError } from '@trpc/server';export functioncreateMyPlugin () {// When creating a plugin for tRPC, you use the same API as creating any other tRPC-app// this is the plugin's root `t`-objectconstt =initTRPC .context <{// the procedure using the plugin will need to extend this context}>().meta <{// the base `initTRPC`-object of the application using this needs to extend this meta}>().create ();return {// you can also add `.input()` if you want your plugin to do input validationpluginProc :t .procedure .use ((opts ) => {returnopts .next ({ctx : {fromPlugin : 'hello from myPlugin' asconst ,},});}),};}// ------------------------------------// 🚀🚀🚀 the app using the plugin 🚀🚀🚀// @filename: app.tsimport {createMyPlugin } from './myPlugin';import {initTRPC ,TRPCError } from '@trpc/server';// the app's root `t`-objectconstt =initTRPC .context <{// ...}>().create ();export constpublicProcedure =t .procedure ;export constrouter =t .router ;// initialize the plugin (a real-world example would likely take options here)constplugin =createMyPlugin ();// create a base procedure using the pluginconstprocedureWithPlugin =publicProcedure .concat (plugin .pluginProc ,).use (opts => {const {ctx } =opts ;returnopts .next ()})export constappRouter =router ({hello :procedureWithPlugin .query (opts => {returnopts .ctx .fromPlugin ;})})
ts// ------------------------------------------------// 🧩🧩🧩 a library creating a reusable plugin 🧩🧩🧩// @filename: myPlugin.tsimport {initTRPC ,TRPCError } from '@trpc/server';export functioncreateMyPlugin () {// When creating a plugin for tRPC, you use the same API as creating any other tRPC-app// this is the plugin's root `t`-objectconstt =initTRPC .context <{// the procedure using the plugin will need to extend this context}>().meta <{// the base `initTRPC`-object of the application using this needs to extend this meta}>().create ();return {// you can also add `.input()` if you want your plugin to do input validationpluginProc :t .procedure .use ((opts ) => {returnopts .next ({ctx : {fromPlugin : 'hello from myPlugin' asconst ,},});}),};}// ------------------------------------// 🚀🚀🚀 the app using the plugin 🚀🚀🚀// @filename: app.tsimport {createMyPlugin } from './myPlugin';import {initTRPC ,TRPCError } from '@trpc/server';// the app's root `t`-objectconstt =initTRPC .context <{// ...}>().create ();export constpublicProcedure =t .procedure ;export constrouter =t .router ;// initialize the plugin (a real-world example would likely take options here)constplugin =createMyPlugin ();// create a base procedure using the pluginconstprocedureWithPlugin =publicProcedure .concat (plugin .pluginProc ,).use (opts => {const {ctx } =opts ;returnopts .next ()})export constappRouter =router ({hello :procedureWithPlugin .query (opts => {returnopts .ctx .fromPlugin ;})})
Extensión de middleware
Hemos prefijado esto como unstable_ porque es una nueva API, ¡pero puedes usarlo con seguridad! Lee más.
Tenemos una potente función llamada .pipe() que te permite extender middleware de manera tipada.
A continuación mostramos un ejemplo de un middleware que extiende un middleware base (foo). Al igual que en el ejemplo de extensión de contexto, encadenar middleware modificará propiedades del contexto, y los procedimientos recibirán el nuevo valor de contexto.
tsconstfooMiddleware =t .middleware ((opts ) => {returnopts .next ({ctx : {foo : 'foo' asconst ,},});});constbarMiddleware =fooMiddleware .unstable_pipe ((opts ) => {const {ctx } =opts ;ctx .foo ;returnopts .next ({ctx : {bar : 'bar' asconst ,},});});constbarProcedure =publicProcedure .use (barMiddleware );barProcedure .query ((opts ) => {const {ctx } =opts ;returnctx .bar ;});
tsconstfooMiddleware =t .middleware ((opts ) => {returnopts .next ({ctx : {foo : 'foo' asconst ,},});});constbarMiddleware =fooMiddleware .unstable_pipe ((opts ) => {const {ctx } =opts ;ctx .foo ;returnopts .next ({ctx : {bar : 'bar' asconst ,},});});constbarProcedure =publicProcedure .use (barMiddleware );barProcedure .query ((opts ) => {const {ctx } =opts ;returnctx .bar ;});
Ten en cuenta que el orden en que encadenas tus middleware importa y que el contexto debe superponerse. A continuación se muestra un ejemplo de encadenamiento prohibido. Aquí, fooMiddleware sobrescribe ctx.a mientras que barMiddleware aún espera el contexto raíz de la inicialización en initTRPC. Por lo tanto, encadenar fooMiddleware con barMiddleware no funcionaría, mientras que encadenar barMiddleware con fooMiddleware sí funciona.
tsimport {initTRPC } from '@trpc/server';constt =initTRPC .context <{a : {b : 'a';};}>().create ();constfooMiddleware =t .middleware ((opts ) => {const {ctx } =opts ;ctx .a ; // 👈 fooMiddleware expects `ctx.a` to be an objectreturnopts .next ({ctx : {a : 'a' asconst , // 👈 `ctx.a` is no longer an object},});});constbarMiddleware =t .middleware ((opts ) => {const {ctx } =opts ;ctx .a ; // 👈 barMiddleware expects `ctx.a` to be an objectreturnopts .next ({ctx : {foo : 'foo' asconst ,},});});// ❌ `ctx.a` does not overlap from `fooMiddleware` to `barMiddleware`Argument of type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to parameter of type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { a: "a"; }, { foo: "foo"; }, unknown> | MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to type 'MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { a: { b: "a"; }; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.a' are incompatible between these types. Type '{ b: "a"; }' is not assignable to type '"a"'.2345Argument of type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to parameter of type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { a: "a"; }, { foo: "foo"; }, unknown> | MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to type 'MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { a: { b: "a"; }; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.a' are incompatible between these types. Type '{ b: "a"; }' is not assignable to type '"a"'.fooMiddleware .unstable_pipe (); barMiddleware // ✅ `ctx.a` overlaps from `barMiddleware` and `fooMiddleware`barMiddleware .unstable_pipe (fooMiddleware );
tsimport {initTRPC } from '@trpc/server';constt =initTRPC .context <{a : {b : 'a';};}>().create ();constfooMiddleware =t .middleware ((opts ) => {const {ctx } =opts ;ctx .a ; // 👈 fooMiddleware expects `ctx.a` to be an objectreturnopts .next ({ctx : {a : 'a' asconst , // 👈 `ctx.a` is no longer an object},});});constbarMiddleware =t .middleware ((opts ) => {const {ctx } =opts ;ctx .a ; // 👈 barMiddleware expects `ctx.a` to be an objectreturnopts .next ({ctx : {foo : 'foo' asconst ,},});});// ❌ `ctx.a` does not overlap from `fooMiddleware` to `barMiddleware`Argument of type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to parameter of type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { a: "a"; }, { foo: "foo"; }, unknown> | MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to type 'MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { a: { b: "a"; }; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.a' are incompatible between these types. Type '{ b: "a"; }' is not assignable to type '"a"'.2345Argument of type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to parameter of type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { a: "a"; }, { foo: "foo"; }, unknown> | MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Type 'MiddlewareBuilder<{ a: { b: "a"; }; }, object, { foo: "foo"; }, unknown>' is not assignable to type 'MiddlewareBuilder<{ a: "a"; }, object, { foo: "foo"; }, unknown>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, $ContextOverridesOut, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, $ContextOverridesOut, unknown>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: "a"; foo: "foo"; }, object, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown> | MiddlewareBuilder<{ a: { b: "a"; }; foo: "foo"; }, object, any, unknown>'. Type 'MiddlewareFunction<{ a: "a"; }, object, { foo: "foo"; }, any, unknown>' is not assignable to type 'MiddlewareFunction<{ a: { b: "a"; }; }, object, { foo: "foo"; }, any, unknown>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { a: { b: "a"; }; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.a' are incompatible between these types. Type '{ b: "a"; }' is not assignable to type '"a"'.fooMiddleware .unstable_pipe (); barMiddleware // ✅ `ctx.a` overlaps from `barMiddleware` and `fooMiddleware`barMiddleware .unstable_pipe (fooMiddleware );
Experimental: Middleware independientes
Esta funcionalidad ha sido desaprobada en favor de .concat()
tRPC tiene una API experimental llamada experimental_standaloneMiddleware que te permite definir independientemente un middleware utilizable con cualquier instancia tRPC. Crear middleware con t.middleware tiene la limitación de que el tipo Context está vinculado al tipo Context de la instancia tRPC. Esto significa que no puedes usar el mismo middleware con múltiples instancias tRPC que tengan diferentes tipos Context.
Usando experimental_standaloneMiddleware puedes crear un middleware que defina explícitamente sus requisitos, es decir, los tipos Context, Input y Meta:
tsimport {experimental_standaloneMiddleware ,initTRPC ,TRPCError ,} from '@trpc/server';import * asz from 'zod';constprojectAccessMiddleware =experimental_standaloneMiddleware <{ctx : {allowedProjects : string[] }; // defaults to 'object' if not definedinput : {projectId : string }; // defaults to 'unknown' if not defined// 'meta', not defined here, defaults to 'object | undefined'}>().create ((opts ) => {if (!opts .ctx .allowedProjects .includes (opts .input .projectId )) {throw newTRPCError ({code : 'FORBIDDEN',message : 'Not allowed',});}returnopts .next ();});constt1 =initTRPC .context <{allowedProjects : string[];}>().create ();// ✅ `ctx.allowedProjects` satisfies "string[]" and `input.projectId` satisfies "string"constaccessControlledProcedure =t1 .procedure .input (z .object ({projectId :z .string () })).use (projectAccessMiddleware );// ❌ `ctx.allowedProjects` satisfies "string[]" but `input.projectId` does not satisfy "string"constaccessControlledProcedure2 =t1 .procedure .input (z .object ({projectId :z .number () })).Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }> | MiddlewareFunction<{ allowedProjects: string[]; }, object, object, object, { projectId: number; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'input.projectId' are incompatible between these types. Type 'string' is not assignable to type 'number'.2345Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }> | MiddlewareFunction<{ allowedProjects: string[]; }, object, object, object, { projectId: number; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'input.projectId' are incompatible between these types. Type 'string' is not assignable to type 'number'.use (); projectAccessMiddleware // ❌ `ctx.allowedProjects` does not satisfy "string[]" even though `input.projectId` satisfies "string"constt2 =initTRPC .context <{allowedProjects : number[];}>().create ();constaccessControlledProcedure3 =t2 .procedure .input (z .object ({projectId :z .string () })).Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }> | MiddlewareFunction<{ allowedProjects: number[]; }, object, object, object, { projectId: string; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: number[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' are incompatible between these types. Type 'string[]' is not assignable to type 'number[]'. Type 'string' is not assignable to type 'number'.2345Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }> | MiddlewareFunction<{ allowedProjects: number[]; }, object, object, object, { projectId: string; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: number[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' are incompatible between these types. Type 'string[]' is not assignable to type 'number[]'. Type 'string' is not assignable to type 'number'.use (); projectAccessMiddleware
tsimport {experimental_standaloneMiddleware ,initTRPC ,TRPCError ,} from '@trpc/server';import * asz from 'zod';constprojectAccessMiddleware =experimental_standaloneMiddleware <{ctx : {allowedProjects : string[] }; // defaults to 'object' if not definedinput : {projectId : string }; // defaults to 'unknown' if not defined// 'meta', not defined here, defaults to 'object | undefined'}>().create ((opts ) => {if (!opts .ctx .allowedProjects .includes (opts .input .projectId )) {throw newTRPCError ({code : 'FORBIDDEN',message : 'Not allowed',});}returnopts .next ();});constt1 =initTRPC .context <{allowedProjects : string[];}>().create ();// ✅ `ctx.allowedProjects` satisfies "string[]" and `input.projectId` satisfies "string"constaccessControlledProcedure =t1 .procedure .input (z .object ({projectId :z .string () })).use (projectAccessMiddleware );// ❌ `ctx.allowedProjects` satisfies "string[]" but `input.projectId` does not satisfy "string"constaccessControlledProcedure2 =t1 .procedure .input (z .object ({projectId :z .number () })).Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }> | MiddlewareFunction<{ allowedProjects: string[]; }, object, object, object, { projectId: number; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'input.projectId' are incompatible between these types. Type 'string' is not assignable to type 'number'.2345Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }> | MiddlewareFunction<{ allowedProjects: string[]; }, object, object, object, { projectId: number; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: number; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: number; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'input.projectId' are incompatible between these types. Type 'string' is not assignable to type 'number'.use (); projectAccessMiddleware // ❌ `ctx.allowedProjects` does not satisfy "string[]" even though `input.projectId` satisfies "string"constt2 =initTRPC .context <{allowedProjects : number[];}>().create ();constaccessControlledProcedure3 =t2 .procedure .input (z .object ({projectId :z .string () })).Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }> | MiddlewareFunction<{ allowedProjects: number[]; }, object, object, object, { projectId: string; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: number[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' are incompatible between these types. Type 'string[]' is not assignable to type 'number[]'. Type 'string' is not assignable to type 'number'.2345Argument of type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to parameter of type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }> | MiddlewareFunction<{ allowedProjects: number[]; }, object, object, object, { projectId: string; }>'. Type 'MiddlewareBuilder<{ allowedProjects: string[]; }, object, object, { projectId: string; }>' is not assignable to type 'MiddlewareBuilder<{ allowedProjects: number[]; }, object, object, { projectId: string; }>'. Types of property 'unstable_pipe' are incompatible. Type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: string[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>' is not assignable to type '<$ContextOverridesOut>(fn: MiddlewareFunction<{ allowedProjects: number[]; }, object, object, $ContextOverridesOut, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, $ContextOverridesOut, { ...; }>) => MiddlewareBuilder<...>'. Types of parameters 'fn' and 'fn' are incompatible. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: number[]; }, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }> | MiddlewareBuilder<{ allowedProjects: string[]; }, object, any, { projectId: string; }>'. Type 'MiddlewareFunction<{ allowedProjects: number[]; }, object, object, any, { projectId: string; }>' is not assignable to type 'MiddlewareFunction<{ allowedProjects: string[]; }, object, object, any, { projectId: string; }>'. Types of parameters 'opts' and 'opts' are incompatible. Type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; signal: AbortSignal | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' are incompatible between these types. Type 'string[]' is not assignable to type 'number[]'. Type 'string' is not assignable to type 'number'.use (); projectAccessMiddleware
Aquí tienes un ejemplo con múltiples middleware independientes:
tsimport {experimental_standaloneMiddleware ,initTRPC } from '@trpc/server';import * asz from 'zod';constt =initTRPC .create ();constschemaA =z .object ({valueA :z .string () });constschemaB =z .object ({valueB :z .string () });constvalueAUppercaserMiddleware =experimental_standaloneMiddleware <{input :z .infer <typeofschemaA >;}>().create ((opts ) => {returnopts .next ({ctx : {valueAUppercase :opts .input .valueA .toUpperCase () },});});constvalueBUppercaserMiddleware =experimental_standaloneMiddleware <{input :z .infer <typeofschemaB >;}>().create ((opts ) => {returnopts .next ({ctx : {valueBUppercase :opts .input .valueB .toUpperCase () },});});constcombinedInputThatSatisfiesBothMiddlewares =z .object ({valueA :z .string (),valueB :z .string (),extraProp :z .string (),});t .procedure .input (combinedInputThatSatisfiesBothMiddlewares ).use (valueAUppercaserMiddleware ).use (valueBUppercaserMiddleware ).query (({input : {valueA ,valueB ,extraProp },ctx : {valueAUppercase ,valueBUppercase },}) =>`valueA: ${valueA }, valueB: ${valueB }, extraProp: ${extraProp }, valueAUppercase: ${valueAUppercase }, valueBUppercase: ${valueBUppercase }`,);
tsimport {experimental_standaloneMiddleware ,initTRPC } from '@trpc/server';import * asz from 'zod';constt =initTRPC .create ();constschemaA =z .object ({valueA :z .string () });constschemaB =z .object ({valueB :z .string () });constvalueAUppercaserMiddleware =experimental_standaloneMiddleware <{input :z .infer <typeofschemaA >;}>().create ((opts ) => {returnopts .next ({ctx : {valueAUppercase :opts .input .valueA .toUpperCase () },});});constvalueBUppercaserMiddleware =experimental_standaloneMiddleware <{input :z .infer <typeofschemaB >;}>().create ((opts ) => {returnopts .next ({ctx : {valueBUppercase :opts .input .valueB .toUpperCase () },});});constcombinedInputThatSatisfiesBothMiddlewares =z .object ({valueA :z .string (),valueB :z .string (),extraProp :z .string (),});t .procedure .input (combinedInputThatSatisfiesBothMiddlewares ).use (valueAUppercaserMiddleware ).use (valueBUppercaserMiddleware ).query (({input : {valueA ,valueB ,extraProp },ctx : {valueAUppercase ,valueBUppercase },}) =>`valueA: ${valueA }, valueB: ${valueB }, extraProp: ${extraProp }, valueAUppercase: ${valueAUppercase }, valueBUppercase: ${valueBUppercase }`,);