Skip to content

PATTERN Cited by 1 source

Injected request-object converter

Injected request-object converter is the pattern where, instead of building a fat cross-framework abstraction layer that tries to unify request shapes across N frameworks, a code-generating SDK injects a small framework-specific converter function into each generated handler. The handler receives the framework's native request object, the injected converter translates it to the SDK-expected shape (typically the standard Web Request API), and the rest of the SDK code consumes the standard shape.

Canonical verbatim

From Vercel's 2026-04-21 WDK post: "A challenge that appeared while creating multiple framework integrations was that different frameworks have different opinions on what a 'request' looks like. SvelteKit passes a custom request object to route handlers, but our workflow handlers expect the standard Web Request API. We fixed this by injecting a small converter function into each generated handler."

The injected snippet (SvelteKit)

async function convertSvelteKitRequest(request) {
    method: request.method,
    headers: new Headers(request.headers)
  if (!['GET', 'HEAD'].includes(request.method)) {
    options.body = await request.arrayBuffer();
  return new Request(request.url, options);
}

(Snippet as shown in the source post; partial — missing outer {} and the const options = {} line.)

The converter:

  • Reads the framework's native request object.
  • Constructs an options object with method + headers (as a Headers instance).
  • For non-GET/HEAD requests, reads the body as an arrayBuffer() and attaches it.
  • Returns a standard new Request(url, options) — the Web Fetch API primitive the rest of WDK's code expects.

Why per-handler injection over shared library

Alternatives considered and rejected:

  1. Shared convertRequest(framework, request) library function — would force every handler to runtime-dispatch on framework, shipping code paths for frameworks the handler doesn't need.
  2. Fat cross-framework UniversalRequest class — would require the SDK to define and maintain an abstraction layer over the union of all framework request shapes. Every framework addition expands the abstraction.
  3. Adapter middleware — would need to run in the framework's middleware chain, creating a tight binding to each framework's middleware API.

Injected per-handler conversion avoids all three:

  • Dead-code-free — only the framework-specific converter is present in each generated handler. No runtime dispatch, no framework the handler doesn't use.
  • Easy to evolve — adding a framework means adding one small converter function per handler at codegen time, not extending a central abstraction.
  • Easy to diff / debug — the converter is readable JS in the generated handler, not hidden behind an import.

How the converter gets injected

WDK's compiler plugin (patterns/swc-plugin-three-mode-transform) emits the converter function into each generated handler during the Step-mode and Workflow-mode transforms. Framework-specific converter templates live in the framework's integration package (e.g. workflow/sveltekit).

When to use

  • Cross-framework SDK that ships generated handlers.
  • When the SDK has a canonical request shape (Web Fetch API Request is the common choice).
  • When framework-specific conversion logic is small enough (tens of lines) that inlining is cheaper than abstracting.

When NOT to use

  • When the SDK doesn't generate handlers (nothing to inject into).
  • When the SDK supports one framework only (bind to its request shape directly).
  • When converter logic is complex enough to warrant a shared library (rare — converter logic is usually just method + headers + body shape-shifting).

Canonical instance

Vercel Workflow DevKit (WDK) injects convertSvelteKitRequest into SvelteKit-generated handlers; presumably analogous converters exist for each of the 8 supported frameworks (Next.js, Astro, Express, Hono, etc.) though only the SvelteKit converter is disclosed in the post.

Seen in

Last updated · 476 distilled / 1,218 read