Skip to main content
doc0blade47/honodocumentation home
Sign in

Deno Adapter

Last updated Oct 12, 2026100% grounded
Relevant source files

The following files were used as context for generating this wiki page:

Overview

The Deno Adapter provides runtime integration for running Hono applications within the Deno environment. It bridges Hono's middleware and helper systems with Deno-specific platform APIs, exposing modules for static file serving, WebSocket upgrading, static site generation, and connection network metadata extraction.

Sources: src/adapter/deno/index.ts:1-9

Module exports and entry points

Public API Surface

The hono/deno entry point exposes specific utility modules designed for the Deno runtime environment. These exports bridge standard Hono mechanics with Deno platform features such as file system-based static asset delivery, static site generation module bindings, WebSocket connection upgrades, and remote connection metadata retrieval.

Export NameSource ModulePurpose
serveStatic./serve-staticServes static files from the Deno file system Static Site Generation
toSSG./ssgGenerates static sites using Deno file system bindings
denoFileSystemModule./ssgProvides Deno file system methods for static site generation output
upgradeWebSocket./websocketUpgrades standard HTTP connections to Deno WebSocket streams
getConnInfo./conninfoExtracts remote client network metadata from Deno incoming connections

Sources: src/adapter/deno/index.ts:1-9

Runtime Environment Detection

The adapter helper module defines the runtime identifier 'deno' alongside other supported execution engines. When evaluating runtime environments through getRuntimeKey, the Deno runtime is identified by matching the navigator.userAgent string against known user agent configurations.

Runtime KeyUser Agent String / Detection Criteria
denoDeno
bunBun
workerdCloudflare-Workers
nodeNode.js
edge-lightglobal.EdgeRuntime string presence
fastlyglobal.fastly definition check
otherFallback when no specific runtime matches

Sources: src/helper/adapter/index.ts:43-84

Note

Environment variable resolution in the adapter helper accesses Deno.env.toObject() when the runtime key resolves to 'deno', mapping runtime configuration directly into typed bindings.

Sources: src/helper/adapter/index.ts:29-33

Serving static files from disk

File System Adapter Integration

The serveStatic helper in src/adapter/deno/serve-static.ts wraps Hono's core baseServeStatic middleware from src/middleware/serve-static to deliver assets directly from the Deno file system. It destructs open, lstatSync, and errors from the global Deno namespace to handle file resolution and directory checks.

const { open, lstatSync, errors } = Deno
 
export const serveStatic = <E extends Env = Env>(
  options: ServeStaticOptions<E> = {}
): MiddlewareHandler => {
  return async function serveStatic(c, next) {
    const getContent = async (path: string) => {
      try {
        if (isDir(path)) {
          return null
        }
 
        const file = await open(path)
        return file.readable
      } catch (e) {
        if (!(e instanceof errors.NotFound)) {
          console.warn(`${e}`)
        }
        return null
      }
    }
    const isDir = (path: string) => {
      let isDir
      try {
        const stat = lstatSync(path)
        isDir = stat.isDirectory
      } catch {}
      return isDir
    }
    return baseServeStatic({
      ...options,
      getContent,
      join,
      isDir,
    })(c, next)
  }
}

Sources: src/adapter/deno/serve-static.ts:6-42

Asset Resolution and Error Handling

When a request arrives, getContent first checks whether the target path points to a directory using the internal isDir helper backed by Deno.lstatSync. If the path represents a directory, getContent returns null immediately to trigger directory index fallback or routing continuation. Otherwise, it attempts to open the file via Deno.open and returns its .readable stream property.

const getContent = async (path: string) => {
  try {
    if (isDir(path)) {
      return null
    }
 
    const file = await open(path)
    return file.readable
  } catch (e) {
    if (!(e instanceof errors.NotFound)) {
      console.warn(`${e}`)
    }
    return null
  }
}
const isDir = (path: string) => {
  let isDir
  try {
    const stat = lstatSync(path)
    isDir = stat.isDirectory
  } catch {}
  return isDir
}

Sources: src/adapter/deno/serve-static.ts:12-34

Warning

Any caught exception during file opening that is not an instance of Deno.errors.NotFound is logged via console.warn, whereas NotFound errors are silently ignored to allow clean fallback handling by downstream middleware.

Sources: src/adapter/deno/serve-static.ts:20-25

WebSocket upgrade integration

Upgrade Mechanism and Subprotocol Negotiation

The upgradeWebSocket helper wraps Hono's defineWebSocketHelper to handle full-duplex WebSocket connections in Deno. It first inspects the incoming request headers; if the upgrade header does not equal 'websocket', the helper returns undefined to let standard HTTP request handling proceed.

export const upgradeWebSocket: UpgradeWebSocket<WebSocket, Deno.UpgradeWebSocketOptions> =
  defineWebSocketHelper(async (c, events, options) => {
    if (c.req.header('upgrade') !== 'websocket') {
      return
    }
 

Sources: src/adapter/deno/websocket.ts:4-9

To ensure browser compatibility, the helper extracts the first requested subprotocol from the sec-websocket-protocol header. Echoing this subprotocol back prevents connection rejections in strict clients such as Google Chrome when subprotocols are negotiated.

// Echo the negotiated subprotocol back to the client. Browsers (e.g. Chrome)
// reject the connection when a subprotocol was requested but the response is
// missing the `Sec-WebSocket-Protocol` header.
const subprotocol = c.req.header('sec-websocket-protocol')?.split(',')[0]?.trim()
 
const { response, socket } = Deno.upgradeWebSocket(c.req.raw, {
  ...(subprotocol ? { protocol: subprotocol } : {}),
  ...options,
})

Sources: src/adapter/deno/websocket.ts:10-18

Note

The Deno.upgradeWebSocket function accepts req along with UpgradeWebSocketOptions, returning an object containing both the HTTP response and the underlying socket.

Sources: src/adapter/deno/websocket.ts:15-18, src/adapter/deno/deno.d.ts:49-55

WSContext Event Bridging

Once the native socket is established, upgradeWebSocket instantiates a WSContext<WebSocket> wrapper that maps property getters and methods onto the Deno socket. It wires event handlers onopen, onmessage, onclose, and onerror directly to the corresponding callbacks defined in the event parameter object.

const wsContext: WSContext<WebSocket> = new WSContext({
  close: (code, reason) => socket.close(code, reason),
  get protocol() {
    return socket.protocol
  },
  raw: socket,
  get readyState() {
    return socket.readyState as WSReadyState
  },
  url: socket.url ? new URL(socket.url) : null,
  send: (source) => socket.send(source),
})
socket.onopen = (evt) => events.onOpen?.(evt, wsContext)
socket.onmessage = (evt) => events.onMessage?.(evt, wsContext)
socket.onclose = (evt) => events.onClose?.(evt, wsContext)
socket.onerror = (evt) => events.onError?.(evt, wsContext)
 
return response

Sources: src/adapter/deno/websocket.ts:20-37

The configuration options accepted by Deno's WebSocket upgrade routine are typed through Deno.UpgradeWebSocketOptions, supporting protocol selection and idle timeout configuration.

OptionTypeDefaultPurpose
protocolstring—Sets the .protocol property on the client-side WebSocket to match requested subprotocols
idleTimeoutnumber30Maximum seconds without a pong frame before connection is deemed unhealthy and closed; set to 0 to disable

Sources: src/adapter/deno/deno.d.ts:60-78

Extracting connection network metadata

Connection Info Helper Signature and Environment Binding

The getConnInfo helper extracts remote client connection metadata from the execution context in Deno environments. It conforms to the GetConnInfo type definition and reads remoteAddr directly from the environment bindings property c.env.

import type { GetConnInfo } from '../../helper/conninfo'
 
/**
 * Get conninfo with Deno
 * @param c Context
 * @returns ConnInfo
 */
export const getConnInfo: GetConnInfo = (c) => {
  const { remoteAddr } = c.env
  return {
    remote: {
      address: remoteAddr.hostname,
      port: remoteAddr.port,
      transport: remoteAddr.transport,
    },
  }

Sources: src/adapter/deno/conninfo.ts:1-16

Remote Address Mapping

The function returns a structured ConnInfo object containing a nested remote object. It maps property values from the Deno remoteAddr instance to standard address fields.

FieldSource PropertyType / Description
addressremoteAddr.hostnameRemote IP address or hostname of the connected client
portremoteAddr.portNetwork port number used by the client connection
transportremoteAddr.transportUnderlying transport protocol (tcp or udp)

Sources: src/adapter/deno/conninfo.ts:8-16

Note

getConnInfo assumes that c.env provides a populated remoteAddr object with hostname, port, and transport properties matching Deno's network address structure.

Sources: src/adapter/deno/conninfo.ts:8-15

Static site generation with Deno

File System Module Integration

The hono/deno adapter integrates with static site generation by wiring Deno native file system APIs into Hono's core SSG framework. The denoFileSystemModule object satisfies the FileSystemModule interface by implementing file writing and directory creation primitives.

export const denoFileSystemModule: FileSystemModule = {
  writeFile: async (path, data) => {
    const uint8Data =
      typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data)
    await Deno.writeFile(path, uint8Data)
  },
  mkdir: async (path, options) => {
    return Deno.mkdir(path, { recursive: options?.recursive ?? false })
  },
}

Sources: src/adapter/deno/ssg.ts:9-18

When writeFile is invoked, it checks whether the provided data is a string; if so, it encodes the text into a Uint8Array using TextEncoder, otherwise it wraps or casts the input data as a Uint8Array before calling Deno.writeFile. The mkdir method forwards directory creation requests to Deno.mkdir, defaulting the recursive flag to false if options are omitted.

writeFile: async (path, data) => {
  const uint8Data =
    typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data)
  await Deno.writeFile(path, uint8Data)
},
mkdir: async (path, options) => {
  return Deno.mkdir(path, { recursive: options?.recursive ?? false })
},

Sources: src/adapter/deno/ssg.ts:10-17

Note

Both denoFileSystemModule and the toSSG export are marked as experimental features whose APIs may change in future releases.

Sources: src/adapter/deno/ssg.ts:4-8, src/adapter/deno/ssg.ts:20-24

SSG Execution Function

The toSSG adapter function matches the ToSSGAdaptorInterface signature, taking a Hono application instance and generation options, and delegating execution to the base toSSG utility bundled with denoFileSystemModule.

export const toSSG: ToSSGAdaptorInterface = async (app, options) => {
  return baseToSSG(app, denoFileSystemModule, options)
}

Sources: src/adapter/deno/ssg.ts:25-27

Was this page helpful?