Skip to content
Meeko
Type to search the guides and the API reference. Open it from any page with / or Ctrl K; move with the arrow keys and open a result with Enter.
Get started

Contents

On this page

serveDeno

Serves a Meeko application with Deno.serve, with Socket over Deno.upgradeWebSocket, graceful shutdown on signals and the process failure policy.

adapter Since 1.0.0 @meekojs/meeko/deno Source code
ts
import { serveDeno } from "@meekojs/meeko/deno";

serveDeno(app, options) starts Deno.serve for a createServerApp application: it handles HTTP through app.fetch, upgrades Socket channels through Deno.upgradeWebSocket and records each connection's IP (remoteAddr). With handleSignals, it shuts down gracefully on SIGINT and SIGTERM (SIGINT and SIGBREAK on Windows) and, since 1.3, applies processErrors.

It is what the meeko build --adapter deno output runs (.meeko/output/deno/main.js).

Usage#

ts
import { createServerApp } from "@meekojs/meeko/server";
import { createDenoAssetReader, serveDeno } from "@meekojs/meeko/deno";

const app = await createServerApp({
  manifest, load, runtime, production: true,
  assets: createDenoAssetReader({ root: new URL("./client/", import.meta.url), assets: manifest.assets ?? {} }),
});
const server = await serveDeno(app, { host: "0.0.0.0", port: 8000, handleSignals: true });
console.log(server.url);

Type#

ts
function serveDeno(app: ServerApp, options?: ServeDenoOptions): Promise<DenoServer>

ServeDenoOptions

ts
interface ServeDenoOptions {
	readonly host?: string
	readonly port?: number
	readonly publicOrigin?: string
	readonly platform?: ServerPlatform
	readonly onError?: (error: unknown, requestId: string) => void
	readonly maxMessageBytes?: number
	readonly idleTimeout?: number
	readonly handleSignals?: boolean
}

DenoServer

ts
interface DenoServer {
	readonly url: string
	readonly finished: Promise<void>
	close(): Promise<void>
}

Parameters#

serveDeno(app, options?):

Option Type Default Description
host string "127.0.0.1" Interface; "0.0.0.0" accepts remote traffic.
port number 4173 Port; 0 chooses a free one.
publicOrigin string the application's, or the listening URL Origin for URLs and the Origin check.
platform ServerPlatform Deno with Deno.env.toObject() Each request's platform.
onError (error, requestId) => void the application's Observer for transport failures.
maxMessageBytes number the application's socket.maxMessageBytes, or 65536 Largest incoming Socket message; larger ones close the peer with 1009.
idleTimeout number 60 Seconds without pong before Deno closes a peer; pings are sent halfway through.
handleSignals boolean false Graceful shutdown on signals and, since 1.3, processErrors.

Return value#

A promise with a DenoServer:

Member Description
url The local URL with the listening address, such as http://127.0.0.1:4173. The meeko build --adapter deno output displays http://localhost:4173 since 1.7.1; url does not change.
finished Resolves when the HTTP server has stopped.
close() Closes Socket peers with 1001, stops HTTP, waits for waitUntil tasks and closes the application, in that order. During shutdown, new requests receive 503.

Examples#

Build and run with minimum permissions#

sh
npx meeko build --adapter deno
deno run --allow-net --allow-env --allow-read=.meeko/output/deno .meeko/output/deno/main.js

main.js includes all server dependencies. --allow-env is required because the runtime receives Deno.env.toObject(); meeko preview --adapter deno grants -A.

A container#

dockerfile
FROM denoland/deno:2.9.8
WORKDIR /app
COPY .meeko/output/deno ./
ENV MEEKO_HOST=0.0.0.0 MEEKO_PORT=8000 MEEKO_PUBLIC_ORIGIN=https://tienda.example.com
EXPOSE 8000
CMD ["run", "--allow-net", "--allow-env", "--allow-read=.", "main.js"]

server.host and server.port from meeko.config.ts only apply to Node; here, use MEEKO_HOST and MEEKO_PORT (or PORT).

Tests with a free port#

ts
const server = await serveDeno(app, { port: 0 });
const response = await fetch(`${server.url}/api/health`);
await response.body?.cancel();
await server.close();
await server.finished;

Common mistakes#

Run the output without permissions#

Incorrectsh
deno run .meeko/output/deno/main.js

Deno requests network, environment and build read access (or denies it if there is no terminal), and startup fails without those permissions.

Correctsh
deno run --allow-net --allow-env --allow-read=.meeko/output/deno .meeko/output/deno/main.js

Call it outside Deno#

Incorrectts
// node server.mjs
await serveDeno(app);

Error: The Meeko Deno adapter requires the Deno runtime.

Correctsh
deno run --allow-net --allow-env --allow-read=. main.js

An invalid port or limit#

Incorrectts
await serveDeno(app, { port: 70000, maxMessageBytes: 0 });

RangeError: Invalid port: 70000; with a valid port, RangeError: Invalid maxMessageBytes (or Invalid idleTimeout).

Correctts
await serveDeno(app, { port: 8000, maxMessageBytes: 16 * 1024 });

Notes#

  • Socket in Deno. Deno.upgradeWebSocket has no frame limit: the adapter measures each message and closes larger ones with 1009, but Deno has already reassembled it in memory. Limit request sizes at the proxy if you need an earlier cap. Binary messages close with 1003; the outgoing buffer is controlled with bufferedAmount.
  • Session rejections. The upgrade completes and the connection closes with 4401 or 4403 one loop iteration after opening, so the close reaches the client even if it has already sent a message.
  • Process failures. Deno uses globalThis's unhandledrejection and error; it preserves requestId in rejections.
  • IP. The connection's remoteAddr; behind a proxy, MEEKO_TRUST_PROXY. An invalid variable stops startup.
  • CSP and headers (since 1.7). server.contentSecurityPolicy and server.headers apply just as in Node.

Was this page helpful?

Add a comment

It is sent when you choose “Yes” or “No”. Only the page, your answer and the comment are stored: no cookies and no personal data.

0 of 2000 characters

Edit on GitHub: docs/en/reference/adapters/servedeno.md