serveDeno
Serves a Meeko application with Deno.serve, with Socket over Deno.upgradeWebSocket, graceful shutdown on signals and the process failure policy.
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#
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#
function serveDeno(app: ServerApp, options?: ServeDenoOptions): Promise<DenoServer>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
}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#
npx meeko build --adapter deno
deno run --allow-net --allow-env --allow-read=.meeko/output/deno .meeko/output/deno/main.jsmain.js includes all server dependencies. --allow-env is required because the runtime receives Deno.env.toObject(); meeko preview --adapter deno grants -A.
A container#
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#
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#
deno run .meeko/output/deno/main.jsDeno requests network, environment and build read access (or denies it if there is no terminal), and startup fails without those permissions.
deno run --allow-net --allow-env --allow-read=.meeko/output/deno .meeko/output/deno/main.jsCall it outside Deno#
// node server.mjs
await serveDeno(app);Error: The Meeko Deno adapter requires the Deno runtime.
deno run --allow-net --allow-env --allow-read=. main.jsAn invalid port or limit#
await serveDeno(app, { port: 70000, maxMessageBytes: 0 });RangeError: Invalid port: 70000; with a valid port, RangeError: Invalid maxMessageBytes (or Invalid idleTimeout).
await serveDeno(app, { port: 8000, maxMessageBytes: 16 * 1024 });Notes#
- Socket in Deno.
Deno.upgradeWebSockethas no frame limit: the adapter measures each message and closes larger ones with1009, but Deno has already reassembled it in memory. Limit request sizes at the proxy if you need an earlier cap. Binary messages close with1003; the outgoing buffer is controlled withbufferedAmount. - Session rejections. The upgrade completes and the connection closes with
4401or4403one loop iteration after opening, so the close reaches the client even if it has already sent a message. - Process failures. Deno uses
globalThis'sunhandledrejectionanderror; it preservesrequestIdin rejections. - IP. The connection's
remoteAddr; behind a proxy,MEEKO_TRUST_PROXY. An invalid variable stops startup. - CSP and headers (since 1.7).
server.contentSecurityPolicyandserver.headersapply just as in Node.