UNPKG

trpc-sveltekit

Version:

SvelteKit adapter for tRPC.io, working with Node.js, Vercel and Netlify

77 lines (76 loc) 3.59 kB
import { resolveHTTPResponse } from '@trpc/server/http'; import { serialize } from 'cookie'; /** * Create a SvelteKit handle function for tRPC requests. * * If you want to use it in conjunction with other SvelteKit handles, * consider [the sequence helper function](https://kit.svelte.dev/docs/modules#sveltejs-kit-hooks). * @see https://kit.svelte.dev/docs/hooks */ export function createTRPCHandle({ router, url = '/trpc', createContext, responseMeta, onError }) { return async ({ event, resolve }) => { if (event.url.pathname.startsWith(url + '/')) { const request = event.request; const req = { method: request.method, headers: request.headers, query: event.url.searchParams, body: await request.text() }; // Using the default `event.setHeaders` and `event.cookies` will not work // as the event in not resolved by SvelteKit. Instead, we "proxy" the access // to the headers. const originalSetHeaders = event.setHeaders; const originalSetCookies = event.cookies.set; const originalDeleteCookies = event.cookies.delete; const headersProxy = {}; const cookiesProxy = {}; // Same as the one provided from sveltekit const defaultCookiesOptions = { httpOnly: true, sameSite: 'lax', secure: event.url.hostname === 'localhost' && event.url.protocol === 'http:' ? false : true }; event.setHeaders = (headers) => { for (const [key, value] of Object.entries(headers)) { headersProxy[key] = value; } // Still call the original `event.setHeaders` function, as it may be used in SvelteKit internals. originalSetHeaders(headers); }; event.cookies.set = (name, value, options) => { cookiesProxy[name] = { value, options: { ...defaultCookiesOptions, ...options } }; originalSetCookies(name, value, options); }; event.cookies.delete = (name, options) => { cookiesProxy[name] = { value: '', options: { ...options, maxAge: 0 } }; originalDeleteCookies(name, options); }; const httpResponse = await resolveHTTPResponse({ router, req, path: event.url.pathname.substring(url.length + 1), createContext: async () => createContext?.(event), responseMeta, // eslint-disable-next-line @typescript-eslint/no-explicit-any onError: onError }); const { status, headers, body } = httpResponse; const finalHeaders = new Headers(); for (const [key, value] of Object.entries(headers)) { finalHeaders.set(key, value); } for (const [key, value] of Object.entries(headersProxy)) { finalHeaders.set(key, value); } if (Object.keys(cookiesProxy).length > 0) { for (const [name, { value, options }] of Object.entries(cookiesProxy)) { const serializedCookie = serialize(name, value, options); finalHeaders.append('Set-Cookie', serializedCookie); } } return new Response(body, { status, headers: finalHeaders }); } return resolve(event); }; }