ミドルウェア
t.procedure.use()
メソッドを使用して、プロシージャにミドルウェアを追加できます。ミドルウェアはプロシージャの呼び出しをラップし、その戻り値を渡す必要があります。
認証
以下の例では、adminProcedure
への呼び出しは、実行前にユーザーが「admin」であることを確認します。
ts
import {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 ,},});});
ts
import {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 ,},});});
ts
import {adminProcedure ,publicProcedure ,router } from './trpc';constadminRouter =router ({secretPlace :adminProcedure .query (() => 'a key'),});export constappRouter =router ({foo :publicProcedure .query (() => 'bar'),admin :adminRouter ,});
ts
import {adminProcedure ,publicProcedure ,router } from './trpc';constadminRouter =router ({secretPlace :adminProcedure .query (() => 'a key'),});export constappRouter =router ({foo :publicProcedure .query (() => 'bar'),admin :adminRouter ,});
上記の例で発生するTRPCError
の詳細については、エラー処理を参照してください。
ロギング
以下の例では、クエリの実行時間は自動的にログに記録されます。
ts
export 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 ;});
ts
export 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 ;});
ts
import { loggedProcedure, router } from './trpc';export const appRouter= router({ foo: loggedProcedure.query(() => 'bar'),abc:loggedProcedure .query (() => 'def'), });
ts
import { loggedProcedure, router } from './trpc';export const appRouter= router({ foo: loggedProcedure.query(() => 'bar'),abc: loggedProcedure. query (() => 'def'), });
コンテキスト拡張
「コンテキスト拡張」により、ミドルウェアは型安全な方法で基本プロシージャのコンテキストのキーを動的に追加および上書きできます。
以下は、コンテキストのプロパティを変更するミドルウェアの例です。変更されたプロパティは、他のミドルウェアやプロシージャなどの、後続のすべてのコンシューマーで使用できます。
ts
typeContext = {// 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 (({ctx }) =>ctx .user );
ts
typeContext = {// 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 (({ctx }) =>ctx .user );
再利用可能なミドルウェアとプラグインを作成するための.concat()
の使用
これは新しいAPIであるため、unstable_
というプレフィックスを付けていますが、安心して使用できます!詳細はこちら。
t.middleware
を使用してミドルウェアを作成すると、Context
型がtRPCインスタンスのContext
型に結び付けられるという制限があります。experimental_standaloneMiddleware()
を使用してミドルウェアを作成すると、モジュールに関連付けられた入力パーサーなどを定義できないという制限があります。
tRPCには、コンテキストとメタデータが一致する任意のtRPCインスタンスで使用できる部分的なプロシージャを独立して定義できる.concat()
と呼ばれるAPIがあります。
このヘルパーは主に、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 .unstable_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 .unstable_concat (plugin .pluginProc ,).use (opts => {const {ctx } =opts ;returnopts .next ()})export constappRouter =router ({hello :procedureWithPlugin .query (opts => {returnopts .ctx .fromPlugin ;})})
ミドルウェアの拡張
これは新しいAPIであるため、unstable_
というプレフィックスを付けていますが、安心して使用できます!詳細はこちら。
型安全な方法でミドルウェアを拡張できる強力な機能.pipe()
があります。
以下は、基本ミドルウェア(foo)を拡張するミドルウェアの例です。上記のコンテキスト拡張の例と同様に、ミドルウェアのパイプライン処理によってコンテキストのプロパティが変更され、プロシージャは新しいコンテキスト値を受け取ります。
ts
constfooMiddleware =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 (({ctx }) =>ctx .bar );
ts
constfooMiddleware =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 (({ctx }) =>ctx .bar );
ミドルウェアをパイプする順序が重要であり、コンテキストが重複する必要があることに注意してください。禁止されているパイプの例を以下に示します。ここでは、fooMiddleware
がctx.a
を上書きしますが、barMiddleware
はinitTRPC
での初期化からのルートコンテキストを依然として期待しているため、fooMiddleware
とbarMiddleware
をパイプすることはできませんが、barMiddleware
とfooMiddleware
をパイプすることはできます。
ts
import {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; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }'. 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; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }'. 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 );
ts
import {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; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }'. 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; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }' is not assignable to type '{ ctx: { a: "a"; foo: "foo"; }; type: "query" | "mutation" | "subscription"; path: string; input: unknown; getRawInput: GetRawInputFn; meta: object | undefined; next: { (): Promise<MiddlewareResult<{ foo: "foo"; }>>; <$ContextOverride>(opts: { ...; }): Promise<...>; (opts: { ...; }): Promise<...>; }; }'. 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 );
実験的:スタンドアロンミドルウェア
これは.unstable_concat()
に置き換えられました。
tRPCには、任意のtRPCインスタンスで使用できるミドルウェアを独立して定義できる実験的APIであるexperimental_standaloneMiddleware
があります。t.middleware
を使用してミドルウェアを作成すると、Context
型がtRPCインスタンスのContext
型に結び付けられるという制限があります。つまり、Context
型が異なる複数のtRPCインスタンスで同じミドルウェアを使用することはできません。
experimental_standaloneMiddleware
を使用すると、コンテキスト、入力、メタデータの型など、その要件を明示的に定義するミドルウェアを作成できます。
ts
import {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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. Types of property 'input' are incompatible. Type '{ projectId: string; }' is not assignable to type '{ projectId: 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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. Types of property 'input' are incompatible. Type '{ projectId: string; }' is not assignable to type '{ projectId: 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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' 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: 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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' are incompatible between these types. Type 'string[]' is not assignable to type 'number[]'.use (); projectAccessMiddleware
ts
import {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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. Types of property 'input' are incompatible. Type '{ projectId: string; }' is not assignable to type '{ projectId: 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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: string[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: number; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. Types of property 'input' are incompatible. Type '{ projectId: string; }' is not assignable to type '{ projectId: 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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' 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: 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; next: { ...; }; }' is not assignable to type '{ ctx: { allowedProjects: number[]; }; type: "query" | "mutation" | "subscription"; path: string; input: { projectId: string; }; getRawInput: GetRawInputFn; meta: object | undefined; next: { ...; }; }'. The types of 'ctx.allowedProjects' are incompatible between these types. Type 'string[]' is not assignable to type 'number[]'.use (); projectAccessMiddleware
複数のスタンドアロンミドルウェアの例を次に示します。
ts
import {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 }`,);
ts
import {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 }`,);