CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-remix-run--node

Node.js platform abstractions and utilities for Remix applications

Pending
Overview
Eval results
Files

server-runtime.mddocs/

Server Runtime API

Complete re-export of @remix-run/server-runtime providing unified access to all Remix server functionality including request handling, response utilities, data fetching, and error handling.

Capabilities

Request Handler

Creates a request handler for processing Remix application requests.

/**
 * Creates a request handler for a Remix application
 * @param build - The server build configuration
 * @returns RequestHandler function for processing requests
 */
function createRequestHandler(build: ServerBuild): RequestHandler;

interface RequestHandler {
  (request: Request, loadContext?: AppLoadContext): Promise<Response>;
}

Usage Examples:

import { createRequestHandler } from "@remix-run/node";
import * as build from "./build/index.js";

// Create request handler
const handleRequest = createRequestHandler(build);

// Use with Express
app.all("*", async (req, res) => {
  const request = new Request(`http://localhost:3000${req.url}`, {
    method: req.method,
    headers: req.headers,
    body: req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined
  });
  
  const response = await handleRequest(request);
  
  res.status(response.status);
  response.headers.forEach((value, name) => {
    res.header(name, value);
  });
  
  if (response.body) {
    response.body.pipeTo(new WritableStream({
      write(chunk) {
        res.write(chunk);
      },
      close() {
        res.end();
      }
    }));
  } else {
    res.end();
  }
});

Response Utilities

Utilities for creating various types of responses in Remix applications.

/**
 * Creates a JSON response with proper headers
 * @param object - The object to serialize as JSON
 * @param init - Optional response initialization options
 * @returns TypedResponse with JSON content
 */
function json<T>(object: T, init?: ResponseInit): TypedResponse<T>;

/**
 * Creates a deferred response for streaming data
 * @param object - Object containing promises to be resolved
 * @param init - Optional response initialization options
 * @returns TypedDeferredData for streaming
 */
function defer<T>(object: T, init?: ResponseInit): TypedDeferredData<T>;

/**
 * Creates a redirect response
 * @param url - The URL to redirect to
 * @param init - Status code (302) or ResponseInit object
 * @returns Redirect response
 */
function redirect(url: string, init?: number | ResponseInit): Response;

/**
 * Creates a document redirect response
 * @param url - The URL to redirect to
 * @param init - Status code or ResponseInit object
 * @returns Document redirect response
 */
function redirectDocument(url: string, init?: number | ResponseInit): Response;

/**
 * Creates a replace response (replaces current history entry)
 * @param url - The URL to replace with
 * @param init - Status code or ResponseInit object
 * @returns Replace response
 */
function replace(url: string, init?: number | ResponseInit): Response;

/**
 * Creates a data response (legacy utility)
 * @param object - The data to include in the response
 * @param init - Optional response initialization options
 * @returns Response with data
 */
function data<T>(object: T, init?: ResponseInit): Response;

Usage Examples:

import { json, defer, redirect, data } from "@remix-run/node";

// JSON response
export async function loader({ params }: LoaderFunctionArgs) {
  const user = await getUserById(params.userId);
  
  if (!user) {
    return json({ error: "User not found" }, { status: 404 });
  }
  
  return json({ user });
}

// Deferred response for streaming
export async function loader({ params }: LoaderFunctionArgs) {
  // Fast data
  const user = await getUserById(params.userId);
  
  // Slow data (streamed later)
  const postsPromise = getPostsByUserId(params.userId);
  const commentsPromise = getCommentsByUserId(params.userId);
  
  return defer({
    user, // Available immediately
    posts: postsPromise, // Streamed when ready
    comments: commentsPromise // Streamed when ready
  });
}

// Redirect responses
export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const intent = formData.get("intent");
  
  if (intent === "delete") {
    await deleteUser(String(formData.get("userId")));
    return redirect("/users");
  }
  
  if (intent === "update") {
    await updateUser(String(formData.get("userId")), formData);
    return redirectDocument(`/users/${formData.get("userId")}`);
  }
  
  return redirect("/");
}

Session and Cookie Utilities

Utilities for working with sessions and cookies.

/**
 * Creates a new session instance
 * @param initialData - Optional initial session data
 * @param id - Optional session ID
 * @returns New session instance
 */
function createSession<Data = SessionData, FlashData = Data>(
  initialData?: Partial<Data>,
  id?: string
): Session<Data, FlashData>;

/**
 * Type guard to check if an object is a Cookie
 * @param object - Object to check
 * @returns True if object is a Cookie
 */
function isCookie(object: any): object is Cookie;

/**
 * Type guard to check if an object is a Session
 * @param object - Object to check
 * @returns True if object is a Session
 */
function isSession(object: any): object is Session;

Upload Handling Utilities

Utilities for handling file uploads in Remix applications.

/**
 * Composes multiple upload handlers into a single handler
 * @param handlers - Array of upload handlers to compose
 * @returns Composed upload handler
 */
function unstable_composeUploadHandlers(
  ...handlers: UploadHandler[]
): UploadHandler;

/**
 * Creates a memory-based upload handler
 * @param options - Configuration options for memory upload handler
 * @returns UploadHandler that stores files in memory
 */
function unstable_createMemoryUploadHandler(
  options?: MemoryUploadHandlerOptions
): UploadHandler;

/**
 * Parses multipart form data using specified upload handlers
 * @param request - The request containing multipart form data
 * @param uploadHandler - Handler for processing uploaded files
 * @returns Promise resolving to FormData with processed uploads
 */
function unstable_parseMultipartFormData(
  request: Request,
  uploadHandler: UploadHandler
): Promise<FormData>;

Usage Examples:

import {
  unstable_composeUploadHandlers,
  unstable_createMemoryUploadHandler,
  unstable_parseMultipartFormData,
  unstable_createFileUploadHandler
} from "@remix-run/node";

// Compose multiple upload handlers
const uploadHandler = unstable_composeUploadHandlers(
  // Try file handler first for large files
  unstable_createFileUploadHandler({
    directory: "/tmp/uploads",
    filter: ({ filename, contentType }) => {
      return filename && contentType.startsWith("image/");
    }
  }),
  // Fall back to memory handler for small files
  unstable_createMemoryUploadHandler({
    maxPartSize: 100000 // 100KB
  })
);

// Use in action
export async function action({ request }: ActionFunctionArgs) {
  const formData = await unstable_parseMultipartFormData(
    request,
    uploadHandler
  );
  
  const avatar = formData.get("avatar") as File;
  const document = formData.get("document") as File;
  
  return json({
    avatar: avatar?.name,
    document: document?.name
  });
}

Development Utilities

Utilities for development and debugging in Remix applications.

/**
 * Broadcasts a development ready signal
 * @param build - The server build
 * @param options - Optional broadcast options
 */
function broadcastDevReady(build: ServerBuild, options?: any): void;

/**
 * Logs a development ready message
 * @param build - The server build
 */
function logDevReady(build: ServerBuild): void;

Type Definitions

The server runtime provides comprehensive TypeScript types for all Remix server functionality:

// Core function types
type ActionFunction<Context = AppLoadContext> = (
  args: ActionFunctionArgs<Context>
) => Promise<Response> | Response | Promise<any> | any;

type LoaderFunction<Context = AppLoadContext> = (
  args: LoaderFunctionArgs<Context>
) => Promise<Response> | Response | Promise<any> | any;

interface ActionFunctionArgs<Context = AppLoadContext> {
  request: Request;
  params: Params;
  context: Context;
}

interface LoaderFunctionArgs<Context = AppLoadContext> {
  request: Request;
  params: Params;
  context: Context;
}

// Response types
interface TypedResponse<T = unknown> extends Response {
  json(): Promise<T>;
}

interface TypedDeferredData<T = Record<string, unknown>> {
  data: T;
  init?: ResponseInit;
}

// Error handling
interface ErrorResponse {
  status: number;
  statusText: string;
  data: any;
}

// Meta and headers functions
type MetaFunction<
  Loader extends LoaderFunction | unknown = unknown,
  ParentsLoaders extends Record<string, LoaderFunction> = {}
> = (args: MetaArgs<Loader, ParentsLoaders>) => MetaDescriptor[];

type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit;

type LinksFunction = () => LinkDescriptor[];

// Session and cookie types
interface SessionData {
  [key: string]: any;
}

interface Cookie {
  readonly name: string;
  readonly isSigned: boolean;
  readonly expires?: Date;
  parse(cookieHeader?: string | null): Promise<any>;
  serialize(value: any): Promise<string>;
}

// Upload handler types
type UploadHandler = (args: UploadHandlerPart) => Promise<File | string | null | undefined>;

interface UploadHandlerPart {
  name: string;
  filename?: string;
  contentType: string;
  data: AsyncIterable<Uint8Array>;
}

Error Classes:

/**
 * Error thrown when upload part size exceeds the configured limit
 */
class MaxPartSizeExceededError extends Error {
  constructor(field: string, maxPartSize: number);
}

This comprehensive server runtime API provides all the tools needed to build full-featured Remix applications with proper error handling, data loading, form processing, file uploads, and session management.

Install with Tessl CLI

npx tessl i tessl/npm-remix-run--node

docs

cookie-session.md

global-polyfills.md

index.md

server-runtime.md

session-storage.md

stream-utilities.md

upload-handling.md

tile.json