From cc09277586f19e36796bf1216acc382dea5adf52 Mon Sep 17 00:00:00 2001 From: unnoq Date: Mon, 29 Sep 2025 15:01:16 +0700 Subject: [PATCH 1/2] docs: add example of event iterator to playgrounds --- .../astro/src/components/orpc-stream.tsx | 16 ++++++++++++++++ playgrounds/astro/src/lib/orpc.ts | 1 + playgrounds/astro/src/pages/index.astro | 3 +++ .../entrypoints/popup/App.tsx | 3 +++ .../popup/components/orpc-stream.tsx | 15 +++++++++++++++ playgrounds/cloudflare-worker/src/App.tsx | 3 +++ .../src/components/orpc-stream.tsx | 15 +++++++++++++++ playgrounds/cloudflare-worker/src/lib/orpc.ts | 8 ++++++++ playgrounds/electron/src/renderer/src/App.tsx | 3 +++ .../renderer/src/components/orpc-stream.tsx | 15 +++++++++++++++ playgrounds/next/src/app/orpc-stream.tsx | 17 +++++++++++++++++ playgrounds/next/src/app/page.tsx | 3 +++ playgrounds/next/src/lib/orpc.ts | 1 + playgrounds/nuxt/app.vue | 3 +++ playgrounds/nuxt/components/orpc-stream.vue | 18 ++++++++++++++++++ playgrounds/nuxt/plugins/orpc.client.ts | 10 ++++++++++ playgrounds/solid-start/src/lib/orpc.ts | 10 ++++++++++ playgrounds/solid-start/src/routes/index.tsx | 3 +++ .../solid-start/src/routes/orpc-stream.tsx | 17 +++++++++++++++++ playgrounds/svelte-kit/src/lib/orpc.ts | 10 ++++++++++ playgrounds/svelte-kit/src/routes/+page.svelte | 3 +++ .../svelte-kit/src/routes/orpc-stream.svelte | 18 ++++++++++++++++++ .../src/components/orpc-stream.tsx | 15 +++++++++++++++ playgrounds/tanstack-start/src/lib/orpc.ts | 1 + .../tanstack-start/src/routes/index.tsx | 3 +++ 25 files changed, 214 insertions(+) create mode 100644 playgrounds/astro/src/components/orpc-stream.tsx create mode 100644 playgrounds/browser-extension/entrypoints/popup/components/orpc-stream.tsx create mode 100644 playgrounds/cloudflare-worker/src/components/orpc-stream.tsx create mode 100644 playgrounds/electron/src/renderer/src/components/orpc-stream.tsx create mode 100644 playgrounds/next/src/app/orpc-stream.tsx create mode 100644 playgrounds/nuxt/components/orpc-stream.vue create mode 100644 playgrounds/solid-start/src/routes/orpc-stream.tsx create mode 100644 playgrounds/svelte-kit/src/routes/orpc-stream.svelte create mode 100644 playgrounds/tanstack-start/src/components/orpc-stream.tsx diff --git a/playgrounds/astro/src/components/orpc-stream.tsx b/playgrounds/astro/src/components/orpc-stream.tsx new file mode 100644 index 000000000..713b70a86 --- /dev/null +++ b/playgrounds/astro/src/components/orpc-stream.tsx @@ -0,0 +1,16 @@ +import { useQuery } from '@tanstack/react-query' +import { orpc } from '../lib/orpc' +import { queryClient } from '../shared/query' + +export function EventIteratorQueries() { + const streamed = useQuery(orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } }), queryClient) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/astro/src/lib/orpc.ts b/playgrounds/astro/src/lib/orpc.ts index 060f6020f..97ba59d25 100644 --- a/playgrounds/astro/src/lib/orpc.ts +++ b/playgrounds/astro/src/lib/orpc.ts @@ -9,6 +9,7 @@ const link = new RPCLink({ url: `${typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000'}/rpc`, plugins: [ new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', groups: [{ condition: () => true, context: {}, diff --git a/playgrounds/astro/src/pages/index.astro b/playgrounds/astro/src/pages/index.astro index 6ade74993..a3dda90e3 100644 --- a/playgrounds/astro/src/pages/index.astro +++ b/playgrounds/astro/src/pages/index.astro @@ -1,6 +1,7 @@ --- import { CreatePlanetMutationForm } from "../components/orpc-mutation"; import { ListPlanetsQuery } from "../components/orpc-query"; +import { EventIteratorQueries } from "../components/orpc-stream"; ---
@@ -12,4 +13,6 @@ import { ListPlanetsQuery } from "../components/orpc-query";
+
+
\ No newline at end of file diff --git a/playgrounds/browser-extension/entrypoints/popup/App.tsx b/playgrounds/browser-extension/entrypoints/popup/App.tsx index 79119f75d..268771def 100644 --- a/playgrounds/browser-extension/entrypoints/popup/App.tsx +++ b/playgrounds/browser-extension/entrypoints/popup/App.tsx @@ -1,5 +1,6 @@ import { CreatePlanetMutationForm } from './components/orpc-mutation' import { ListPlanetsQuery } from './components/orpc-query' +import { EventIteratorQueries } from './components/orpc-stream' export default function App() { return ( @@ -9,6 +10,8 @@ export default function App() {
+
+ ) } diff --git a/playgrounds/browser-extension/entrypoints/popup/components/orpc-stream.tsx b/playgrounds/browser-extension/entrypoints/popup/components/orpc-stream.tsx new file mode 100644 index 000000000..cf1c896ce --- /dev/null +++ b/playgrounds/browser-extension/entrypoints/popup/components/orpc-stream.tsx @@ -0,0 +1,15 @@ +import { useQuery } from '@tanstack/react-query' +import { orpc } from '../lib/orpc' + +export function EventIteratorQueries() { + const streamed = useQuery(orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } })) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/cloudflare-worker/src/App.tsx b/playgrounds/cloudflare-worker/src/App.tsx index 1115812e4..fd4b01530 100644 --- a/playgrounds/cloudflare-worker/src/App.tsx +++ b/playgrounds/cloudflare-worker/src/App.tsx @@ -3,6 +3,7 @@ import { CreatePlanetMutationForm } from './components/orpc-mutation' import { ListPlanetsQuery } from './components/orpc-query' import '@scalar/api-reference-react/style.css' import { ApiReferenceReact } from '@scalar/api-reference-react' +import { EventIteratorQueries } from './components/orpc-stream' export default function App() { if (location.pathname === '/api') { @@ -31,6 +32,8 @@ export default function App() {
+
+ ) } diff --git a/playgrounds/cloudflare-worker/src/components/orpc-stream.tsx b/playgrounds/cloudflare-worker/src/components/orpc-stream.tsx new file mode 100644 index 000000000..cf1c896ce --- /dev/null +++ b/playgrounds/cloudflare-worker/src/components/orpc-stream.tsx @@ -0,0 +1,15 @@ +import { useQuery } from '@tanstack/react-query' +import { orpc } from '../lib/orpc' + +export function EventIteratorQueries() { + const streamed = useQuery(orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } })) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/cloudflare-worker/src/lib/orpc.ts b/playgrounds/cloudflare-worker/src/lib/orpc.ts index 52bf5f746..3ee314ea7 100644 --- a/playgrounds/cloudflare-worker/src/lib/orpc.ts +++ b/playgrounds/cloudflare-worker/src/lib/orpc.ts @@ -4,6 +4,7 @@ import { DurableIteratorLinkPlugin } from '@orpc/experimental-durable-iterator/c import type { RouterClient } from '@orpc/server' import { createTanstackQueryUtils } from '@orpc/tanstack-query' import type { router } from '../../worker/routers' +import { BatchLinkPlugin } from '@orpc/client/plugins' const link = new RPCLink({ url: `${window.location.origin}/rpc`, @@ -12,6 +13,13 @@ const link = new RPCLink({ url: `${window.location.origin}/chat-room`, refreshTokenBeforeExpireInSeconds: 10 * 60, // 10 minutes }), + new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', + groups: [{ + condition: () => true, + context: {}, + }], + }), ], }) diff --git a/playgrounds/electron/src/renderer/src/App.tsx b/playgrounds/electron/src/renderer/src/App.tsx index c1642beaa..9c3bdd7db 100644 --- a/playgrounds/electron/src/renderer/src/App.tsx +++ b/playgrounds/electron/src/renderer/src/App.tsx @@ -1,5 +1,6 @@ import { CreatePlanetMutationForm } from './components/orpc-mutation' import { ListPlanetsQuery } from './components/orpc-query' +import { EventIteratorQueries } from './components/orpc-stream' function App(): React.JSX.Element { return ( @@ -9,6 +10,8 @@ function App(): React.JSX.Element {
+
+ ) } diff --git a/playgrounds/electron/src/renderer/src/components/orpc-stream.tsx b/playgrounds/electron/src/renderer/src/components/orpc-stream.tsx new file mode 100644 index 000000000..cc658ebc2 --- /dev/null +++ b/playgrounds/electron/src/renderer/src/components/orpc-stream.tsx @@ -0,0 +1,15 @@ +import { orpc } from '@renderer/lib/orpc' +import { useQuery } from '@tanstack/react-query' + +export function EventIteratorQueries() { + const streamed = useQuery(orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } })) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/next/src/app/orpc-stream.tsx b/playgrounds/next/src/app/orpc-stream.tsx new file mode 100644 index 000000000..c9ea516b1 --- /dev/null +++ b/playgrounds/next/src/app/orpc-stream.tsx @@ -0,0 +1,17 @@ +'use client' + +import { orpc } from '@/lib/orpc' +import { useQuery } from '@tanstack/react-query' + +export function EventIteratorQueries() { + const streamed = useQuery(orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } })) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/next/src/app/page.tsx b/playgrounds/next/src/app/page.tsx index 118df15c9..ae3e511e5 100644 --- a/playgrounds/next/src/app/page.tsx +++ b/playgrounds/next/src/app/page.tsx @@ -2,6 +2,7 @@ import { redirectToScalarForm } from './actions' import { CreatePlanetMutationForm } from './orpc-mutation' import { ListPlanetsQuery } from './orpc-query' import { OrpcServerAction } from './orpc-server-action' +import { EventIteratorQueries } from './orpc-stream' export default function Home() { return ( @@ -22,6 +23,8 @@ export default function Home() {
+
+ ) } diff --git a/playgrounds/next/src/lib/orpc.ts b/playgrounds/next/src/lib/orpc.ts index d7086cf15..a825702ef 100644 --- a/playgrounds/next/src/lib/orpc.ts +++ b/playgrounds/next/src/lib/orpc.ts @@ -18,6 +18,7 @@ const link = new RPCLink({ url: `${typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000'}/rpc`, plugins: [ new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', groups: [{ condition: () => true, context: {}, diff --git a/playgrounds/nuxt/app.vue b/playgrounds/nuxt/app.vue index f2f323acd..a4cda2b62 100644 --- a/playgrounds/nuxt/app.vue +++ b/playgrounds/nuxt/app.vue @@ -10,6 +10,9 @@


+
+
+ diff --git a/playgrounds/nuxt/components/orpc-stream.vue b/playgrounds/nuxt/components/orpc-stream.vue new file mode 100644 index 000000000..002b2abe8 --- /dev/null +++ b/playgrounds/nuxt/components/orpc-stream.vue @@ -0,0 +1,18 @@ + + + diff --git a/playgrounds/nuxt/plugins/orpc.client.ts b/playgrounds/nuxt/plugins/orpc.client.ts index c232ea2d5..f9aaee9cc 100644 --- a/playgrounds/nuxt/plugins/orpc.client.ts +++ b/playgrounds/nuxt/plugins/orpc.client.ts @@ -3,11 +3,21 @@ import type { router } from '~/server/routers' import { createORPCClient } from '@orpc/client' import { RPCLink } from '@orpc/client/fetch' import { createTanstackQueryUtils } from '@orpc/tanstack-query' +import { BatchLinkPlugin } from '@orpc/client/plugins' export default defineNuxtPlugin(() => { const link = new RPCLink({ url: `${window.location.origin}/rpc`, headers: () => ({}), + plugins: [ + new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', + groups: [{ + condition: () => true, + context: {}, + }], + }), + ], }) const client: RouterClient = createORPCClient(link) diff --git a/playgrounds/solid-start/src/lib/orpc.ts b/playgrounds/solid-start/src/lib/orpc.ts index 00e3833a6..b8cba2c8b 100644 --- a/playgrounds/solid-start/src/lib/orpc.ts +++ b/playgrounds/solid-start/src/lib/orpc.ts @@ -8,6 +8,7 @@ import { createORPCClient } from '@orpc/client' import { RPCLink } from '@orpc/client/fetch' import { createTanstackQueryUtils } from '@orpc/tanstack-query' import { getRequestEvent } from 'solid-js/web' +import { BatchLinkPlugin } from '@orpc/client/plugins' declare global { var $client: RouterClient | undefined @@ -16,6 +17,15 @@ declare global { const link = new RPCLink({ url: `${typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3000'}/rpc`, headers: () => getRequestEvent()?.request.headers ?? {}, + plugins: [ + new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', + groups: [{ + condition: () => true, + context: {}, + }], + }), + ], }) export const client: RouterClient = globalThis.$client ?? createORPCClient(link) diff --git a/playgrounds/solid-start/src/routes/index.tsx b/playgrounds/solid-start/src/routes/index.tsx index cf5af529d..05a76b0d9 100644 --- a/playgrounds/solid-start/src/routes/index.tsx +++ b/playgrounds/solid-start/src/routes/index.tsx @@ -1,5 +1,6 @@ import { CreatePlanetMutationForm } from './orpc-mutation' import { ListPlanetsQuery } from './orpc-query' +import { EventIteratorQueries } from './orpc-stream' export default function Home() { return ( @@ -16,6 +17,8 @@ export default function Home() {
+
+ ) } diff --git a/playgrounds/solid-start/src/routes/orpc-stream.tsx b/playgrounds/solid-start/src/routes/orpc-stream.tsx new file mode 100644 index 000000000..87698997b --- /dev/null +++ b/playgrounds/solid-start/src/routes/orpc-stream.tsx @@ -0,0 +1,17 @@ +import { useQuery } from '@tanstack/solid-query' +import { orpc } from '~/lib/orpc' + +export function EventIteratorQueries() { + const streamed = useQuery( + () => orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } }), + ) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/svelte-kit/src/lib/orpc.ts b/playgrounds/svelte-kit/src/lib/orpc.ts index 7ea9a6959..6b6dc1209 100644 --- a/playgrounds/svelte-kit/src/lib/orpc.ts +++ b/playgrounds/svelte-kit/src/lib/orpc.ts @@ -2,6 +2,7 @@ import type { RouterClient } from '@orpc/server' import type { router } from '../routers' import { createORPCClient } from '@orpc/client' import { RPCLink } from '@orpc/client/fetch' +import { BatchLinkPlugin } from '@orpc/client/plugins' import { createTanstackQueryUtils } from '@orpc/tanstack-query' const rpcLink = new RPCLink({ @@ -9,6 +10,15 @@ const rpcLink = new RPCLink({ headers: () => ({ Authorization: 'Bearer default-token', }), + plugins: [ + new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', + groups: [{ + condition: () => true, + context: {}, + }], + }), + ], }) export const client: RouterClient = createORPCClient(rpcLink) diff --git a/playgrounds/svelte-kit/src/routes/+page.svelte b/playgrounds/svelte-kit/src/routes/+page.svelte index 7a92ba1ef..8a35c8c73 100644 --- a/playgrounds/svelte-kit/src/routes/+page.svelte +++ b/playgrounds/svelte-kit/src/routes/+page.svelte @@ -2,6 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'; import OrpcMutation from './orpc-mutation.svelte'; import OrpcQuery from './orpc-query.svelte'; + import OrpcStream from './orpc-stream.svelte'; const queryClient = new QueryClient(); @@ -20,5 +21,7 @@
+
+ diff --git a/playgrounds/svelte-kit/src/routes/orpc-stream.svelte b/playgrounds/svelte-kit/src/routes/orpc-stream.svelte new file mode 100644 index 000000000..421a0f875 --- /dev/null +++ b/playgrounds/svelte-kit/src/routes/orpc-stream.svelte @@ -0,0 +1,18 @@ + + +
+

oRPC and Tanstack Query | Event Iterator example

+
+{JSON.stringify($streamed.data, null, 2)}
+  
+
\ No newline at end of file diff --git a/playgrounds/tanstack-start/src/components/orpc-stream.tsx b/playgrounds/tanstack-start/src/components/orpc-stream.tsx new file mode 100644 index 000000000..6192924b8 --- /dev/null +++ b/playgrounds/tanstack-start/src/components/orpc-stream.tsx @@ -0,0 +1,15 @@ +import { useQuery } from '@tanstack/react-query' +import { orpc } from '~/lib/orpc' + +export function EventIteratorQueries() { + const streamed = useQuery(orpc.sse.experimental_streamedOptions({ queryFnOptions: { maxChunks: 3 } })) + + return ( +
+

oRPC and Tanstack Query | Event Iterator example

+
+        {JSON.stringify(streamed.data, null, 2)}
+      
+
+ ) +} diff --git a/playgrounds/tanstack-start/src/lib/orpc.ts b/playgrounds/tanstack-start/src/lib/orpc.ts index 01f8b73fb..384c384f4 100644 --- a/playgrounds/tanstack-start/src/lib/orpc.ts +++ b/playgrounds/tanstack-start/src/lib/orpc.ts @@ -31,6 +31,7 @@ const getORPCClient = createIsomorphicFn() url: `${window.location.origin}/api/rpc`, plugins: [ new BatchLinkPlugin({ + exclude: ({ path }) => path[0] === 'sse', groups: [{ condition: () => true, context: {}, diff --git a/playgrounds/tanstack-start/src/routes/index.tsx b/playgrounds/tanstack-start/src/routes/index.tsx index 2e51d52a7..6c773b437 100644 --- a/playgrounds/tanstack-start/src/routes/index.tsx +++ b/playgrounds/tanstack-start/src/routes/index.tsx @@ -1,6 +1,7 @@ import { createFileRoute } from '@tanstack/react-router' import { CreatePlanetMutationForm } from '~/components/orpc-mutation' import { ListPlanetsQuery } from '~/components/orpc-query' +import { EventIteratorQueries } from '~/components/orpc-stream' export const Route = createFileRoute('/')({ component: RouteComponent, @@ -19,6 +20,8 @@ function RouteComponent() {
+
+ ) } From e1ca32486a1cb112dd684351df7974b51c3be3b1 Mon Sep 17 00:00:00 2001 From: unnoq Date: Mon, 29 Sep 2025 15:14:15 +0700 Subject: [PATCH 2/2] add missing plugins --- playgrounds/nuxt/server/routes/rpc/[...].ts | 4 ++++ playgrounds/solid-start/src/routes/rpc/[...rest].ts | 4 ++++ .../svelte-kit/src/routes/rpc/[...rest]/+server.ts | 4 ++++ playgrounds/tanstack-start/src/routes/api/rpc.$.ts | 13 ++++++++++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/playgrounds/nuxt/server/routes/rpc/[...].ts b/playgrounds/nuxt/server/routes/rpc/[...].ts index daf0d1a20..0d26ce2cc 100644 --- a/playgrounds/nuxt/server/routes/rpc/[...].ts +++ b/playgrounds/nuxt/server/routes/rpc/[...].ts @@ -1,5 +1,6 @@ import { onError } from '@orpc/server' import { RPCHandler } from '@orpc/server/fetch' +import { BatchHandlerPlugin } from '@orpc/server/plugins' import { router } from '~/server/routers' const rpcHandler = new RPCHandler(router, { @@ -8,6 +9,9 @@ const rpcHandler = new RPCHandler(router, { console.error(error) }), ], + plugins: [ + new BatchHandlerPlugin(), + ], }) export default defineEventHandler(async (event) => { diff --git a/playgrounds/solid-start/src/routes/rpc/[...rest].ts b/playgrounds/solid-start/src/routes/rpc/[...rest].ts index 97bd6775e..b00c90ac2 100644 --- a/playgrounds/solid-start/src/routes/rpc/[...rest].ts +++ b/playgrounds/solid-start/src/routes/rpc/[...rest].ts @@ -3,6 +3,7 @@ import { RPCHandler } from '@orpc/server/fetch' import { router } from '~/routers' import { onError } from '@orpc/server' import '~/polyfill' +import { BatchHandlerPlugin } from '@orpc/server/plugins' const handler = new RPCHandler(router, { interceptors: [ @@ -10,6 +11,9 @@ const handler = new RPCHandler(router, { console.error(error) }), ], + plugins: [ + new BatchHandlerPlugin(), + ], }) async function handle({ request }: APIEvent) { diff --git a/playgrounds/svelte-kit/src/routes/rpc/[...rest]/+server.ts b/playgrounds/svelte-kit/src/routes/rpc/[...rest]/+server.ts index 663ebbd5c..84ebb3c08 100644 --- a/playgrounds/svelte-kit/src/routes/rpc/[...rest]/+server.ts +++ b/playgrounds/svelte-kit/src/routes/rpc/[...rest]/+server.ts @@ -3,6 +3,7 @@ import { router } from '../../../routers' import { onError } from '@orpc/server' import type { RequestHandler } from '@sveltejs/kit' import '../../../polyfill' +import { BatchHandlerPlugin } from '@orpc/server/plugins' const handler = new RPCHandler(router, { interceptors: [ @@ -10,6 +11,9 @@ const handler = new RPCHandler(router, { console.error(error) }), ], + plugins: [ + new BatchHandlerPlugin(), + ], }) const handle: RequestHandler = async ({ request }) => { diff --git a/playgrounds/tanstack-start/src/routes/api/rpc.$.ts b/playgrounds/tanstack-start/src/routes/api/rpc.$.ts index 0ad472773..a1b9cba6f 100644 --- a/playgrounds/tanstack-start/src/routes/api/rpc.$.ts +++ b/playgrounds/tanstack-start/src/routes/api/rpc.$.ts @@ -3,8 +3,19 @@ import '~/polyfill' import { RPCHandler } from '@orpc/server/fetch' import { createFileRoute } from '@tanstack/react-router' import { router } from '~/routers' +import { BatchHandlerPlugin } from '@orpc/server/plugins' +import { onError } from '@orpc/server' -const handler = new RPCHandler(router) +const handler = new RPCHandler(router, { + interceptors: [ + onError((error) => { + console.error(error) + }), + ], + plugins: [ + new BatchHandlerPlugin(), + ], +}) async function handle({ request }: { request: Request }) { const { response } = await handler.handle(request, {