npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fluojs/platform-deno

v2.0.1

Published

Deno-based HTTP adapter for the Fluo runtime.

Downloads

440

Readme

@fluojs/platform-deno

Deno-backed HTTP adapter for the fluo runtime, built on native Deno.serve.

Table of Contents

Installation

deno add npm:@fluojs/platform-deno npm:@fluojs/runtime npm:@fluojs/http

This package is intended to run on Deno. The published manifest intentionally does not declare engines.node, so npm metadata stays aligned with the Deno runtime contract; the repository's Node.js 20+ requirement only applies to the maintainer build/test toolchain.

When to Use

Use this package when running fluo applications on the Deno runtime. This adapter leverages Deno's native fetch-standard Request and Response objects, providing a secure and high-performance environment for TypeScript backend development.

During application shutdown, the adapter stops new ingress and gives active HTTP handlers a bounded drain window before the Deno server lifecycle completes.

Factory registers createDenoShutdownSignalRegistration() after listen when supplied as shutdownRegistration, and removes those SIGINT/SIGTERM listeners when close begins.

Quick Start

import {
  DenoHttpApplicationAdapter,
  createDenoShutdownSignalRegistration,
} from '@fluojs/platform-deno';
import { FluoFactory } from '@fluojs/runtime';
import { AppModule } from './app.module.ts';

const app = await FluoFactory.create(AppModule, {
  adapter: DenoHttpApplicationAdapter.create({ port: 3000 }),
  shutdownRegistration: createDenoShutdownSignalRegistration(),
});
await app.listen();

The application-owned startup path opens a network listener. The host may register SIGINT/SIGTERM with createDenoShutdownSignalRegistration() and owns callback failure handling. Run the entrypoint with network access:

deno run --allow-net main.ts

Signal listener registration does not require a separate Deno permission. The adapter does not read environment variables. Add a scoped grant such as --allow-env=PORT,DATABASE_URL only when application code reads those keys. Hosts coordinate signal callback failure status and forced termination themselves.

Common Patterns

Early Hints are unsupported

Deno's Fetch Response cannot represent an informational response before the final response, so context.response.earlyHints is absent. Check for capability presence before use. The adapter never turns a requested 103 into a silent no-op or a final-response header.

Streaming multipart consumption

Set multipart: { strategy: 'stream' } at application bootstrap to receive multipart data incrementally. For multipart routes, RequestContext.request.body is an AsyncIterableIterator<MultipartPart>: field parts expose kind: 'field', name, value, and headers; file parts expose kind: 'file', name, filename, contentType, headers, and a single-consumer ReadableStream<Uint8Array> at stream. Finish or cancel each file stream before requesting the next part.

Runtime route dispatch owns an iterator created for a route and automatically calls return() after the handler finishes, cancelling and releasing an active source. Standalone parseMultipartStream(...) consumers own that responsibility: consume the iterator to completion or call return() when ending early.

Host-Owned Deno.serve

If your application owns Deno.serve(...), bootstrap the fluo application without calling app.listen() and create a request handler from its public dispatcher. createDenoFetchHandler(...) only translates and dispatches requests; it never starts a server or owns shutdown, signals, or websocket upgrades.

import { DenoHttpApplicationAdapter, createDenoFetchHandler } from '@fluojs/platform-deno';
import { FluoFactory } from '@fluojs/runtime';

const adapter = DenoHttpApplicationAdapter.create();
const app = await FluoFactory.create(AppModule, { adapter });
const handler = createDenoFetchHandler({
  dispatcher: app.dispatcher,
  rawBody: true,
});

const server = Deno.serve({ port: 3000 }, handler);

try {
  await server.finished;
} finally {
  await app.close();
}

The surrounding host must stop server, coordinate process signals, and decide whether websocket upgrades are handled separately. Use app.listen() when fluo should own the managed server lifecycle; supply createDenoShutdownSignalRegistration() to Factory when the host wants Deno signal registration. adapter.handle(...) remains available only after the managed adapter's listen(dispatcher) binding has completed.

Direct Adapter Construction

Application code should usually prefer DenoHttpApplicationAdapter.create(options) so adapter setup stays explicit. Custom orchestration and tests may use new DenoHttpApplicationAdapter(options?) directly; the constructor accepts the same optional public DenoAdapterOptions as the factory, applies the default port when options are omitted, preserves hostname over the portable host alias, and rejects invalid port or maxBodySize values during setup.

Opt-in Deno WebSocket Binding

The adapter supports Deno's native Deno.upgradeWebSocket after the application imports and configures the @fluojs/websockets/deno binding. Without that binding, websocket upgrade requests continue through normal HTTP dispatch instead of being upgraded implicitly.

import { Module } from '@fluojs/core';
import { OnMessage, WebSocketGateway } from '@fluojs/websockets';
import { DenoWebSocketModule } from '@fluojs/websockets/deno';

@WebSocketGateway({ path: '/ws' })
export class MyGateway {
  @OnMessage('ping')
  handlePing(_payload: unknown, socket) {
    socket.send(JSON.stringify({ event: 'pong', data: 'hello from deno' }));
  }
}

@Module({
  imports: [DenoWebSocketModule.forRoot()],
  providers: [MyGateway],
})
export class RealtimeModule {}

Deno websocket inbound payloads

DenoWebSocketMessage represents every payload form the Deno binding can deliver: ArrayBuffer | ArrayBufferView | Blob | string. Existing handlers that narrowed this public union exhaustively for Blob | string must add ArrayBuffer and ArrayBufferView branches. The @fluojs/websockets/deno binding already accepts and normalizes these binary payloads before it dispatches gateway handlers.

HTTPS and Runtime Portability

Pass Deno TLS certificate material through the https option to start Deno.serve in HTTPS mode. The adapter forwards https.cert and https.key to Deno as cert and key, and startup logging reports an https:// listen URL so the Deno package stays aligned with the shared HTTP adapter portability contract.

import { DenoHttpApplicationAdapter, createDenoShutdownSignalRegistration } from '@fluojs/platform-deno';
import { FluoFactory } from '@fluojs/runtime';
const app = await FluoFactory.create(AppModule, {
  adapter: DenoHttpApplicationAdapter.create({
    hostname: '127.0.0.1',
    https: {
      cert: await Deno.readTextFile('./cert.pem'),
      key: await Deno.readTextFile('./key.pem'),
    },
    port: 3443,
  }),
  shutdownRegistration: createDenoShutdownSignalRegistration(),
});
await app.listen();

hostname remains the Deno-native option name. The adapter also accepts host as a portability alias for shared HTTP adapter tests and cross-runtime configuration helpers; when both are provided, hostname wins for the Deno.serve(...) bind target and reported listen URL.

Advanced options include injectable serve and upgradeWebSocket seams for tests or non-hosted runtimes, rawBody, maxBodySize, and multipart. createDenoFetchHandler(...) accepts the same request parsing options and preserves byte-exact JSON/text raw bodies while excluding rawBody for multipart requests. When a seam is not injected, the managed adapter falls back to globalThis.Deno.serve and globalThis.Deno.upgradeWebSocket at listen/upgrade time. createDenoShutdownSignalRegistration() selects SIGINT/SIGTERM by default; omitting Factory shutdownRegistration leaves signals to the host, and failed multi-signal registration rolls back listeners that were already attached. Duplicate listen(...) calls on an already-running adapter are no-ops that preserve the original dispatcher pipeline. Close waits up to 10 seconds for active requests to drain before aborting the Deno serve signal. If graceful shutdown rejects, the adapter aborts ingress but retains the active server controller until server.finished settles; only then does it release the managed lifecycle and rethrow the original shutdown error. handle(...) returns a JSON 500 before listen() binds the dispatcher, including websocket upgrade requests, and a JSON 503 while shutdown is in progress.

Conformance Coverage

packages/platform-deno/src/adapter.test.ts is the package-local regression target for the managed Deno contract. It covers shared Web dispatch delegation, direct adapter.handle(...) success-path dispatch after listen(dispatcher), direct constructor/factory option normalization, HTTPS startup forwarding, host alias and hostname precedence for the Deno.serve(...) bind target and startup log, duplicate listen(...) no-op dispatcher preservation, default SIGINT/SIGTERM signal listener registration, omitting shutdownRegistration, listener rollback after partial signal-registration failure, websocket upgrade binding and no-binding HTTP fallback, websocket pre-listen bootstrap gating, global Deno serve/upgrade fallback seams, pre-listen 500 handling, shutdown 503 handling, in-flight request drain before serve-signal abort, shutdown-failure ownership until server.finished, and the bounded 10-second close timeout. packages/platform-deno/src/fetch-handler.test.ts applies the shared web-runtime portability harness to the host-owned handler, covering cookies/query decoding, JSON/text and byte-exact raw bodies, multipart exclusion, SSE framing, and proof that dispatch does not call Deno.serve(...). packages/platform-deno/src/declaration-surface.test.ts rebuilds the package and verifies the manifest-exported declarations.

The shared edge portability suite in packages/testing/src/portability/web-runtime-adapter-portability.test.ts exercises Deno beside Bun and Cloudflare Workers for malformed cookie preservation, query decoding, JSON/text raw-body capture, single byte-range status/header/body semantics, multipart raw-body exclusion, and SSE framing. The README parity assertion in the package test keeps these documented edge-runtime coverage claims synchronized with the Korean mirror.

The Deno 2 smoke lane checks the public npm:@fluojs/platform-deno root import and executes the built adapter closure natively. It dispatches a host-owned createDenoFetchHandler(...) request without a listener, then creates a static Deno adapter on port 0, calls FluoFactory.create(...) without a shutdown callback and awaits app.listen(), fetches a real route, and closes the application. Signal ownership remains disabled for that managed-listener test; signal registration is covered separately by the package-local contract suite.

Public API Overview

  • DenoHttpApplicationAdapter.create(options): Factory for the Deno HTTP adapter; it shares validation and normalization with direct construction.
  • createDenoFetchHandler(options): Synchronously creates a Request handler from an already bootstrapped app.dispatcher without starting or owning Deno.serve(...).
  • DenoHttpApplicationAdapter(options?): Core adapter implementation. Direct new DenoHttpApplicationAdapter() or new DenoHttpApplicationAdapter(options) applies the same default port, host alias handling, hostname precedence, and numeric option validation as DenoHttpApplicationAdapter.create(options).
  • createDenoShutdownSignalRegistration(signals?): Host signal callback supplied to Factory; rolls back partial registration and attempts every listener removal on close.
  • listen(dispatcher): Binds the fluo HTTP dispatcher and starts Deno.serve; duplicate calls are no-ops while preserving the original dispatcher.
  • close(): Stops ingress, drains active requests for up to 10 seconds, and aborts the Deno serve signal if shutdown does not settle. A rejected graceful shutdown retains getServer() ownership until server.finished settles, then releases the managed lifecycle and rethrows the original shutdown error.
  • handle(request): Manual Request to Response dispatcher. It succeeds after listen(dispatcher) binds the runtime dispatcher, returns JSON 500 before binding, and returns JSON 503 while shutdown is in progress.
  • getListenTarget(): Reports the bind target and public URL using Deno hostname or the portable host alias.
  • getRealtimeCapability(): Reports the fetch-style Deno websocket upgrade capability for runtime integration.
  • getServer(): Returns the active Deno.serve controller while the adapter is listening.
  • Deno realtime modules install their binding through the version-1 capability during module registration, before listen(dispatcher) starts the server; direct configure/setter APIs are removed.
  • DenoWebSocketMessage: The full inbound websocket payload union: ArrayBuffer | ArrayBufferView | Blob | string.
  • https: { cert, key }: HTTPS startup options forwarded to Deno.serve and reflected in the reported listen URL.
  • Option and seam types: CreateDenoFetchHandlerOptions, DenoServeOptions, DenoServeController, DenoServerWebSocket, websocket binding interfaces, DenoAdapterOptions, DenoShutdownSignal, and DenoServeOnListenInfo.

Related Packages

  • @fluojs/runtime: Core framework runtime.
  • @fluojs/websockets: Includes specific subpath @fluojs/websockets/deno.
  • @fluojs/http: HTTP decorators and abstractions.

Example Sources

  • packages/platform-deno/src/adapter.test.ts
  • packages/platform-deno/src/fetch-handler.test.ts
  • packages/websockets/src/deno/deno.test.ts