@nextrush/adapter-denoDeno
Deno HTTP adapter for NextRush — connects your application to Deno.serve().
Connect your NextRush application to Deno's native Deno.serve() API. This adapter bridges NextRush's middleware system to Deno's HTTP server.
Source & internals
README · ARCHITECTURE · see also Adapter Contract
| Package | @nextrush/adapter-deno |
| Status | Stable |
| Support tier | Public — stable, semver-guarded |
Included in nextrush? | No — standalone install |
| Runtime | Deno >=2.0 only |
Installation
Import directly in Deno (no npm required):
import { createApp } from 'npm:@nextrush/core';
import { serve } from 'npm:@nextrush/adapter-deno';Or with import maps in deno.json:
{
"imports": {
"@nextrush/core": "npm:@nextrush/core",
"@nextrush/adapter-deno": "npm:@nextrush/adapter-deno"
}
}Deno Permissions Required
Deno requires explicit network permission to run an HTTP server. Use --allow-net at minimum. See
Deno Permissions for details.
Quick Start
import { createApp } from '@nextrush/core';
import { listen } from '@nextrush/adapter-deno';
const app = createApp();
app.use(async (ctx) => {
ctx.json({ runtime: 'deno', message: 'Hello World!' });
});
listen(app, 8080);
// Output: 🚀 NextRush listening on http://localhost:8080 (Deno)Run with Deno:
deno run --allow-net src/main.tsAPI Reference
serve(app, options?)
Start the HTTP server with full configuration control.
import { createApp } from '@nextrush/core';
import { serve } from '@nextrush/adapter-deno';
const app = createApp();
const server = serve(app, {
port: 8080,
host: '0.0.0.0',
onListen: ({ port, hostname }) => {
console.log(`Server running at http://${hostname}:${port}`);
},
onError: (error) => {
console.error('Server error:', error);
},
});ServeOptions
ServeOptions
| Property | Type | Description |
|---|---|---|
port | number= 8080 | Port to listen on |
host | string= '0.0.0.0' | Host to bind to |
onListen? | (info: { port: number; host: string; hostname: string }) => void | Callback when server starts listening |
onError? | (error: Error) => void | Custom error handler for uncaught server errors |
cert? | string | TLS certificate in PEM format. Deprecated — use tls.cert instead; removed in a future minor version. |
key? | string | TLS private key in PEM format. Deprecated — use tls.key instead; removed in a future minor version. |
tls? | { cert: string; key: string; ca?: string } | TLS configuration (canonical shape — matches @nextrush/adapter-bun). Deno.serve() negotiates HTTP/1.1 vs HTTP/2 via ALPN automatically once this is present. Prefer this over the deprecated flat cert/key fields. |
shutdownTimeout | number= 30000 | Grace period in ms for draining in-flight requests during shutdown |
gracefulShutdown? | boolean | GracefulShutdownOptions | Opt-in: wire SIGTERM/SIGINT to the same close() drain logic. `true` installs handlers for the default signal set; `{ signals, timeout }` overrides them. Omitted by default — no signal handler is installed and process behavior is unchanged. |
ServerInstance
The returned server instance provides control methods:
interface ServerInstance {
server: DenoServer; // Underlying Deno server
port: number; // Actual port
hostname: string; // Actual hostname
close(): Promise<void>; // Graceful shutdown
address(): { port; hostname };
finished: Promise<void>; // Resolves when server stops
}listen(app, port?)
Quick-start shorthand with default logging.
import { createApp } from '@nextrush/core';
import { listen } from '@nextrush/adapter-deno';
const app = createApp();
const server = listen(app, 8080);
// Output: 🚀 NextRush listening on http://localhost:8080 (Deno)createHandler(app)
Create a raw handler for advanced use cases.
import { createApp } from '@nextrush/core';
import { createHandler } from '@nextrush/adapter-deno';
const app = createApp();
const handler = createHandler(app);
// Use directly with Deno.serve
Deno.serve({ handler, port: 8080 });TLS/HTTPS & HTTP/2
Enable HTTPS with TLS certificates. Deno.serve() negotiates HTTP/1.1 vs HTTP/2 via ALPN
automatically once TLS is configured — there is no separate protocol option.
import { serve } from '@nextrush/adapter-deno';
const server = serve(app, {
port: 443,
tls: {
cert: await Deno.readTextFile('./cert.pem'),
key: await Deno.readTextFile('./key.pem'),
},
});Migrating from the flat cert/key fields
The top-level cert/key options are deprecated in favor of tls (matching
@nextrush/adapter-bun's shape) and will be removed in a future minor version:
// Before (deprecated)
serve(app, { cert, key });
// After
serve(app, { tls: { cert, key } });Deno Permissions
NextRush requires network permission to run:
# Minimum required
deno run --allow-net app.ts
# With file access (for static files, etc.)
deno run --allow-net --allow-read app.ts
# Development (more permissive)
deno run --allow-all app.tsServer Lifecycle
Waiting for Server Finish
Deno adapter exposes a finished promise:
const server = serve(app, { port: 8080 });
// Wait for server to complete (useful in scripts)
await server.finished;Graceful Shutdown
Handle server shutdown properly:
const server = serve(app, { port: 8080 });
Deno.addSignalListener('SIGTERM', async () => {
console.log('Shutting down...');
await server.close(); // Closes app + server
Deno.exit(0);
});Or wire it declaratively with gracefulShutdown instead of listening for signals yourself:
const server = await serve(app, {
port: 8080,
gracefulShutdown: true, // installs SIGTERM + SIGINT, using shutdownTimeout as the drain window
});
// Or override the signal set / drain timeout explicitly:
const server2 = await serve(app, {
port: 8080,
gracefulShutdown: { signals: ['SIGTERM'], timeout: 5_000 },
});Omitting gracefulShutdown installs no signal handler — process behavior is unchanged. The
handler is removed once close() completes, so repeated serve()/close() cycles never
accumulate duplicate listeners.
Client IP Access
The adapter extracts client IP from Deno's connection info:
app.use(async (ctx) => {
// Available via context
const ip = ctx.ip; // From remoteAddr
ctx.json({ clientIp: ip });
});Deno Deploy
For Deno Deploy, use createHandler:
import { createApp } from '@nextrush/core';
import { createHandler } from '@nextrush/adapter-deno';
const app = createApp();
app.use(async (ctx) => {
ctx.json({
message: 'Hello from Deno Deploy!',
region: Deno.env.get('DENO_REGION'),
});
});
Deno.serve(createHandler(app));TypeScript
Full TypeScript support with Deno's native TS:
import type { Application } from '@nextrush/core';
import type { ServeOptions, ServerInstance } from '@nextrush/adapter-deno';
import { serve, listen, createHandler } from '@nextrush/adapter-deno';
const options: ServeOptions = {
port: 8080,
hostname: '0.0.0.0',
};
const server: ServerInstance = serve(app, options);Related
- Platforms Overview — Understanding runtime adapters
- @nextrush/adapter-node — Node.js adapter
- @nextrush/adapter-bun — Bun adapter
- @nextrush/adapter-edge — Edge runtime adapter