0
# Server Runtime API
1
2
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.
3
4
## Capabilities
5
6
### Request Handler
7
8
Creates a request handler for processing Remix application requests.
9
10
```typescript { .api }
11
/**
12
* Creates a request handler for a Remix application
13
* @param build - The server build configuration
14
* @returns RequestHandler function for processing requests
15
*/
16
function createRequestHandler(build: ServerBuild): RequestHandler;
17
18
interface RequestHandler {
19
(request: Request, loadContext?: AppLoadContext): Promise<Response>;
20
}
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import { createRequestHandler } from "@remix-run/node";
27
import * as build from "./build/index.js";
28
29
// Create request handler
30
const handleRequest = createRequestHandler(build);
31
32
// Use with Express
33
app.all("*", async (req, res) => {
34
const request = new Request(`http://localhost:3000${req.url}`, {
35
method: req.method,
36
headers: req.headers,
37
body: req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined
38
});
39
40
const response = await handleRequest(request);
41
42
res.status(response.status);
43
response.headers.forEach((value, name) => {
44
res.header(name, value);
45
});
46
47
if (response.body) {
48
response.body.pipeTo(new WritableStream({
49
write(chunk) {
50
res.write(chunk);
51
},
52
close() {
53
res.end();
54
}
55
}));
56
} else {
57
res.end();
58
}
59
});
60
```
61
62
### Response Utilities
63
64
Utilities for creating various types of responses in Remix applications.
65
66
```typescript { .api }
67
/**
68
* Creates a JSON response with proper headers
69
* @param object - The object to serialize as JSON
70
* @param init - Optional response initialization options
71
* @returns TypedResponse with JSON content
72
*/
73
function json<T>(object: T, init?: ResponseInit): TypedResponse<T>;
74
75
/**
76
* Creates a deferred response for streaming data
77
* @param object - Object containing promises to be resolved
78
* @param init - Optional response initialization options
79
* @returns TypedDeferredData for streaming
80
*/
81
function defer<T>(object: T, init?: ResponseInit): TypedDeferredData<T>;
82
83
/**
84
* Creates a redirect response
85
* @param url - The URL to redirect to
86
* @param init - Status code (302) or ResponseInit object
87
* @returns Redirect response
88
*/
89
function redirect(url: string, init?: number | ResponseInit): Response;
90
91
/**
92
* Creates a document redirect response
93
* @param url - The URL to redirect to
94
* @param init - Status code or ResponseInit object
95
* @returns Document redirect response
96
*/
97
function redirectDocument(url: string, init?: number | ResponseInit): Response;
98
99
/**
100
* Creates a replace response (replaces current history entry)
101
* @param url - The URL to replace with
102
* @param init - Status code or ResponseInit object
103
* @returns Replace response
104
*/
105
function replace(url: string, init?: number | ResponseInit): Response;
106
107
/**
108
* Creates a data response (legacy utility)
109
* @param object - The data to include in the response
110
* @param init - Optional response initialization options
111
* @returns Response with data
112
*/
113
function data<T>(object: T, init?: ResponseInit): Response;
114
```
115
116
**Usage Examples:**
117
118
```typescript
119
import { json, defer, redirect, data } from "@remix-run/node";
120
121
// JSON response
122
export async function loader({ params }: LoaderFunctionArgs) {
123
const user = await getUserById(params.userId);
124
125
if (!user) {
126
return json({ error: "User not found" }, { status: 404 });
127
}
128
129
return json({ user });
130
}
131
132
// Deferred response for streaming
133
export async function loader({ params }: LoaderFunctionArgs) {
134
// Fast data
135
const user = await getUserById(params.userId);
136
137
// Slow data (streamed later)
138
const postsPromise = getPostsByUserId(params.userId);
139
const commentsPromise = getCommentsByUserId(params.userId);
140
141
return defer({
142
user, // Available immediately
143
posts: postsPromise, // Streamed when ready
144
comments: commentsPromise // Streamed when ready
145
});
146
}
147
148
// Redirect responses
149
export async function action({ request }: ActionFunctionArgs) {
150
const formData = await request.formData();
151
const intent = formData.get("intent");
152
153
if (intent === "delete") {
154
await deleteUser(String(formData.get("userId")));
155
return redirect("/users");
156
}
157
158
if (intent === "update") {
159
await updateUser(String(formData.get("userId")), formData);
160
return redirectDocument(`/users/${formData.get("userId")}`);
161
}
162
163
return redirect("/");
164
}
165
```
166
167
### Session and Cookie Utilities
168
169
Utilities for working with sessions and cookies.
170
171
```typescript { .api }
172
/**
173
* Creates a new session instance
174
* @param initialData - Optional initial session data
175
* @param id - Optional session ID
176
* @returns New session instance
177
*/
178
function createSession<Data = SessionData, FlashData = Data>(
179
initialData?: Partial<Data>,
180
id?: string
181
): Session<Data, FlashData>;
182
183
/**
184
* Type guard to check if an object is a Cookie
185
* @param object - Object to check
186
* @returns True if object is a Cookie
187
*/
188
function isCookie(object: any): object is Cookie;
189
190
/**
191
* Type guard to check if an object is a Session
192
* @param object - Object to check
193
* @returns True if object is a Session
194
*/
195
function isSession(object: any): object is Session;
196
```
197
198
### Upload Handling Utilities
199
200
Utilities for handling file uploads in Remix applications.
201
202
```typescript { .api }
203
/**
204
* Composes multiple upload handlers into a single handler
205
* @param handlers - Array of upload handlers to compose
206
* @returns Composed upload handler
207
*/
208
function unstable_composeUploadHandlers(
209
...handlers: UploadHandler[]
210
): UploadHandler;
211
212
/**
213
* Creates a memory-based upload handler
214
* @param options - Configuration options for memory upload handler
215
* @returns UploadHandler that stores files in memory
216
*/
217
function unstable_createMemoryUploadHandler(
218
options?: MemoryUploadHandlerOptions
219
): UploadHandler;
220
221
/**
222
* Parses multipart form data using specified upload handlers
223
* @param request - The request containing multipart form data
224
* @param uploadHandler - Handler for processing uploaded files
225
* @returns Promise resolving to FormData with processed uploads
226
*/
227
function unstable_parseMultipartFormData(
228
request: Request,
229
uploadHandler: UploadHandler
230
): Promise<FormData>;
231
```
232
233
**Usage Examples:**
234
235
```typescript
236
import {
237
unstable_composeUploadHandlers,
238
unstable_createMemoryUploadHandler,
239
unstable_parseMultipartFormData,
240
unstable_createFileUploadHandler
241
} from "@remix-run/node";
242
243
// Compose multiple upload handlers
244
const uploadHandler = unstable_composeUploadHandlers(
245
// Try file handler first for large files
246
unstable_createFileUploadHandler({
247
directory: "/tmp/uploads",
248
filter: ({ filename, contentType }) => {
249
return filename && contentType.startsWith("image/");
250
}
251
}),
252
// Fall back to memory handler for small files
253
unstable_createMemoryUploadHandler({
254
maxPartSize: 100000 // 100KB
255
})
256
);
257
258
// Use in action
259
export async function action({ request }: ActionFunctionArgs) {
260
const formData = await unstable_parseMultipartFormData(
261
request,
262
uploadHandler
263
);
264
265
const avatar = formData.get("avatar") as File;
266
const document = formData.get("document") as File;
267
268
return json({
269
avatar: avatar?.name,
270
document: document?.name
271
});
272
}
273
```
274
275
### Development Utilities
276
277
Utilities for development and debugging in Remix applications.
278
279
```typescript { .api }
280
/**
281
* Broadcasts a development ready signal
282
* @param build - The server build
283
* @param options - Optional broadcast options
284
*/
285
function broadcastDevReady(build: ServerBuild, options?: any): void;
286
287
/**
288
* Logs a development ready message
289
* @param build - The server build
290
*/
291
function logDevReady(build: ServerBuild): void;
292
```
293
294
## Type Definitions
295
296
The server runtime provides comprehensive TypeScript types for all Remix server functionality:
297
298
```typescript { .api }
299
// Core function types
300
type ActionFunction<Context = AppLoadContext> = (
301
args: ActionFunctionArgs<Context>
302
) => Promise<Response> | Response | Promise<any> | any;
303
304
type LoaderFunction<Context = AppLoadContext> = (
305
args: LoaderFunctionArgs<Context>
306
) => Promise<Response> | Response | Promise<any> | any;
307
308
interface ActionFunctionArgs<Context = AppLoadContext> {
309
request: Request;
310
params: Params;
311
context: Context;
312
}
313
314
interface LoaderFunctionArgs<Context = AppLoadContext> {
315
request: Request;
316
params: Params;
317
context: Context;
318
}
319
320
// Response types
321
interface TypedResponse<T = unknown> extends Response {
322
json(): Promise<T>;
323
}
324
325
interface TypedDeferredData<T = Record<string, unknown>> {
326
data: T;
327
init?: ResponseInit;
328
}
329
330
// Error handling
331
interface ErrorResponse {
332
status: number;
333
statusText: string;
334
data: any;
335
}
336
337
// Meta and headers functions
338
type MetaFunction<
339
Loader extends LoaderFunction | unknown = unknown,
340
ParentsLoaders extends Record<string, LoaderFunction> = {}
341
> = (args: MetaArgs<Loader, ParentsLoaders>) => MetaDescriptor[];
342
343
type HeadersFunction = (args: HeadersArgs) => Headers | HeadersInit;
344
345
type LinksFunction = () => LinkDescriptor[];
346
347
// Session and cookie types
348
interface SessionData {
349
[key: string]: any;
350
}
351
352
interface Cookie {
353
readonly name: string;
354
readonly isSigned: boolean;
355
readonly expires?: Date;
356
parse(cookieHeader?: string | null): Promise<any>;
357
serialize(value: any): Promise<string>;
358
}
359
360
// Upload handler types
361
type UploadHandler = (args: UploadHandlerPart) => Promise<File | string | null | undefined>;
362
363
interface UploadHandlerPart {
364
name: string;
365
filename?: string;
366
contentType: string;
367
data: AsyncIterable<Uint8Array>;
368
}
369
```
370
371
**Error Classes:**
372
373
```typescript { .api }
374
/**
375
* Error thrown when upload part size exceeds the configured limit
376
*/
377
class MaxPartSizeExceededError extends Error {
378
constructor(field: string, maxPartSize: number);
379
}
380
```
381
382
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.