getPlatform

Access platform-specific runtime context from any server-side code. Returns the raw platform object provided by the current adapter -- Cloudflare Worker bindings, Node.js request/response, or Vercel function context.

Import

import { getPlatform } from "catmint/server";

Signature

function getPlatform<T = unknown>(): T;

Parameters

None. Uses a generic type parameter T to type the returned platform object.

Return Value

Returns the platform-specific context object for the current request. The shape depends on the adapter:

AdapterPlatform Object Shape
Cloudflare{ env: Env, ctx: ExecutionContext }
Node.js{ req: IncomingMessage, res: ServerResponse }
Vercel (Node.js){ req: IncomingMessage, res: ServerResponse }
Vercel (Edge){} (no additional platform context)

Throws

Throws an error if called outside of a server request context (e.g. at module scope or in client code).

Usage

Cloudflare Workers

Access KV, R2, D1, Durable Objects, and other Cloudflare bindings:

import { createServerFn } from "catmint/server";
import { getPlatform } from "catmint/server";

interface CloudflarePlatform {
  env: {
    MY_KV: KVNamespace;
    MY_BUCKET: R2Bucket;
    DB: D1Database;
  };
  ctx: ExecutionContext;
}

export const getValue = createServerFn(async (key: string) => {
  const { env } = getPlatform<CloudflarePlatform>();
  return await env.MY_KV.get(key);
});

export const uploadFile = createServerFn(
  async ({ name, data }: { name: string; data: ArrayBuffer }) => {
    const { env } = getPlatform<CloudflarePlatform>();
    await env.MY_BUCKET.put(name, data);
    return { success: true };
  },
);

export const queryDb = createServerFn(async () => {
  const { env } = getPlatform<CloudflarePlatform>();
  const { results } = await env.DB.prepare("SELECT * FROM users").all();
  return results;
});

Node.js

Access the raw Node.js request and response objects:

import { getPlatform } from "catmint/server";
import type { IncomingMessage, ServerResponse } from "node:http";

interface NodePlatform {
  req: IncomingMessage;
  res: ServerResponse;
}

export const getClientIp = createServerFn(async () => {
  const { req } = getPlatform<NodePlatform>();
  return req.socket.remoteAddress;
});

In Middleware

// app/middleware.ts
import { defineMiddleware } from "catmint/middleware";
import { getPlatform } from "catmint/server";

interface CloudflarePlatform {
  env: { AUTH_KV: KVNamespace };
}

export const middleware = defineMiddleware(async (ctx) => {
  const { env } = getPlatform<CloudflarePlatform>();
  const session = await env.AUTH_KV.get(
    ctx.request.headers.get("x-session-id") ?? "",
  );
  if (!session) {
    return new Response("Unauthorized", { status: 401 });
  }
  return ctx.next();
});

In API Endpoints

// app/api/cache/endpoint.ts
import { getPlatform } from "catmint/server";

interface CloudflarePlatform {
  env: { CACHE: KVNamespace };
  ctx: ExecutionContext;
}

export async function GET({ request }: { request: Request }) {
  const { env, ctx } = getPlatform<CloudflarePlatform>();
  const cached = await env.CACHE.get("data");
  if (cached) {
    return new Response(cached, {
      headers: { "Content-Type": "application/json" },
    });
  }

  const fresh = JSON.stringify({ timestamp: Date.now() });
  ctx.waitUntil(env.CACHE.put("data", fresh, { expirationTtl: 60 }));
  return new Response(fresh, {
    headers: { "Content-Type": "application/json" },
  });
}

Dev Mode

getPlatform() works during catmint dev when the configured adapter provides a dev() hook. The dev server calls the adapter's hook at startup and uses it to populate the request context on every incoming request.

AdapterDev Mode Return Value
Cloudflare{ env, ctx, cf, caches } -- locally emulated via Wrangler's getPlatformProxy()
Node.js{ req, res } -- the raw Node.js request and response objects
VercelNo dev() hook -- getPlatform() returns undefined

For the Cloudflare adapter, wrangler must be installed as a dev dependency. Bindings configured in the adapter options are automatically available during dev -- no separate wrangler.toml is needed. See the adapter-cloudflare docs for setup details.

If no adapter is configured or the adapter does not implement dev(), getPlatform() returns undefined during development.

Typing the Platform

Define an interface for your platform and pass it as the generic parameter. This gives you full type safety without runtime overhead:

// app/lib/platform.ts
export interface AppPlatform {
  env: {
    DB: D1Database;
    CACHE: KVNamespace;
    ASSETS_BUCKET: R2Bucket;
  };
  ctx: ExecutionContext;
}
// app/lib/db.fn.ts
import { createServerFn } from "catmint/server";
import { getPlatform } from "catmint/server";
import type { AppPlatform } from "./platform";

export const getUsers = createServerFn(async () => {
  const { env } = getPlatform<AppPlatform>();
  const { results } = await env.DB.prepare(
    "SELECT * FROM users LIMIT 50",
  ).all();
  return results;
});

See Also