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

@gnosticdev/hono-actions

v2.0.11

Published

Define server actions with built-in validation, error handling, and a pre-built hono client for calling the routes.

Readme

Astro Actions with Hono

Define server actions with built-in validation, error handling, and a pre-built hono client for calling the routes.

Installation

# with astro cli
astro add @gnosticdev/hono-actions

# package manager (npm, pnpm, bun, etc.)
bun add @gnosticdev/hono-actions

Requirements

This package requires:

  • astro: ^5.13.0

[!IMPORTANT] For typescript, make sure you set strictNullChecks to true, or extend astro/tsconfigs/strict(est) in your tsconfig.json

Supported Adapters

This integration works with all supported Astro adapters:

  • @astrojs/cloudflare
  • @astrojs/node (standalone mode only)
  • @astrojs/vercel
  • @astrojs/netlify

Setup

1. Add the integration to your Astro config

The integration works with all Astro adapters. Here are examples for each:

Cloudflare/Vercel/Netlify Adapter

// astro.config.ts
import { defineConfig } from 'astro/config'
import cloudflare from '@astrojs/cloudflare'
import honoActions from '@gnosticdev/hono-actions'

export default defineConfig({
  output: 'server',
  adapter: cloudflare() // vercel() or netlify(),
  integrations: [
    honoActions({
      basePath: '/api', // Optional: default is '/api'
      actionsPath: 'src/server/actions.ts' // Optional: custom path to your actions file
    })
  ]
})

Node.js Adapter

Node.js adapter only supports the 'standalone' mode.

// astro.config.ts
import { defineConfig } from 'astro/config'
import node from '@astrojs/node'
import honoActions from '@gnosticdev/hono-actions'

export default defineConfig({
  output: 'server',
  adapter: node({
    mode: 'standalone'
  }),
  integrations: [
    honoActions()
  ]
})

2. Create your actions file

Create a file at one of these locations, or use the actionsPath option to specify a custom path:

  • src/server/actions.ts
  • src/hono/actions.ts
  • src/hono/index.ts
  • src/hono.ts
  • src/hono-actions.ts

Usage

// src/hono.ts (or any of the supported locations above)
import { defineHonoAction type HonoEnv } from '@gnosticdev/hono-actions/actions'
import { z } from 'astro/zod'
import { Hono } from 'hono'

export const myAction = defineHonoAction({
  schema: z.object({
    name: z.string()
  }),
  handler: async (input, ctx) => {
    // `input` is automatically typed from the schema
    // `ctx` is a strongly-typed Hono Context with your `HonoEnv`
    return { message: `Hello ${input.name}!` }
  }
})

// Define another POST action
export const anotherAction = defineHonoAction({
  schema: z.object({ name2: z.string() }),
  handler: async (input, ctx) => {
    return {
      message2: `Hello ${input.name2}!`
    }
  }
})

// Optional: Define an action without a schema (accepts any JSON)
export const noSchemaAction = defineHonoAction({
  handler: async (input, ctx) => {
    if (!('name' in input)) {
      throw new HonoActionError({
        message: 'Name is required',
        code: 'INPUT_VALIDATION_ERROR'
      })
    }
    return { message: `Hello ${String((input as any).name)}!` }
  }
})

// You can also define standard Hono routes (GET/PATCH/etc.), not just POST actions.
// This is useful where standard Astro actions are POST-only.
const app = new Hono<HonoEnv>()
const getRoute = app.get('/', (c) => c.json({ message: 'Hi from a get route' }))

// Export all actions and routes in a single `honoActions` object.
// Each key becomes the route name under your basePath, e.g.:
//  - POST /api/myAction
//  - POST /api/anotherAction
//  - GET  /api/getRoute
export const honoActions = {
  myAction,
  anotherAction,
  noSchemaAction,
  getRoute
}

3. Use actions in your Astro components or pages

// src/pages/example.astro or any .astro file
---
import { honoClient, parseResponse } from '@gnosticdev/hono-actions/client'

// Call a POST action
const { data: actionRes } = await parseResponse(
  await honoClient.api.myAction.$post({ json: { name: 'John' } })
)

// Call a GET route
const { message } = await parseResponse(
  await honoClient.api.getRoute.$get()
)
---

<div>
  {actionRes && <p>{actionRes.message}</p>}
  <p>{message}</p>
</div>

4. Use in client-side JavaScript

// In a client-side script or component
import { honoClient } from '@gnosticdev/hono-actions/client'
import type { DetailedError } from '@gnosticdev/hono-actions/client'

// Make requests from the browser
const handleSubmit = async (formData: FormData) => {
  const { data, error } = await parseResponse(await honoClient.api.anotherAction.$post({
    json: {
      name2: formData.get('name') as string
    }
  }).catch((err: DetailedError) => {
    console.error('Error:', err)
    return {
      data: null,
      error: err
    }
  })

  if (error){
    throw new Error(`Action failed: ${error.message}`)
  }

// type safe access to the data
  console.log('my name is ', data.name2)
}

Augmenting Type Interfaces

When using this library, you may need to augment the type interfaces to add custom types for your environment bindings, Hono context variables, or Astro locals. This is especially important when using the Cloudflare adapter.

Cloudflare Runtime Types

When using the @astrojs/cloudflare adapter, the library automatically exports Cloudflare runtime types. However, it assumes that Cloudflare types have been generated by Wrangler via the wrangler types command, which creates an Env interface that is automatically added to HonoEnv['Bindings'].

To generate Cloudflare types:

bunx --bun wrangler types

This creates a worker-configuration.d.ts file (or similar) containing the Env interface based on your wrangler.jsonc configuration.

Extending HonoEnv Types

To add additional types to your Hono environment, create a type declaration file (e.g., src/env.d.ts) and augment the module:

// src/env.d.ts
import '@gnosticdev/hono-actions/actions'

// Augmenting the actions types for use with cloudflare adapter
declare module '@gnosticdev/hono-actions/actions' {
    // 1) Extend existing Bindings, with Env from worker-configuration.d.ts
    interface Bindings extends Env {
        anotherVar: string
    }

    // 2) Add Variables available on `ctx.var.db` or `ctx.var.db.get('randomKey')` in hono actions
    interface HonoEnv {
        Variables: {
            db: Map<string, any>
        }
        Bindings: Bindings
    }
}

// Extend Astro Locals if you want to use in middleware
// need to add this to global scope bc we have an import in the file
declare global {
    type Runtime = import('@astrojs/cloudflare').Runtime<Env>
    declare namespace App {
        interface Locals extends Runtime {
            db: Map<string, any> // this will now be available on both `ctx.var.db` and `Astro.locals.db`
        }
    }
}

Now in your actions, you'll have full type safety:

// src/hono.ts
import { defineHonoAction, type HonoEnv } from '@gnosticdev/hono-actions/actions'

export const myAction = defineHonoAction({
  handler: async (input, ctx) => {
    // ctx.env has type: Bindings (includes Env + your custom bindings)
    const kv = ctx.env.CUSTOM_KV

    // ctx.var has type: HonoEnv['Variables']
    const user = kv.get('user')

    return { success: true }
  }
})

And in your Astro pages:

// src/pages/index.astro
---
// Astro.locals has type: App.Locals
const user = Astro.locals.user
---

Package Structure

This package provides these entry points:

  • @gnosticdev/hono-actions/actions: Action definition utilities (defineHonoAction, HonoActionError, HonoEnv (for cloudflare usage))
    • Used in your actions file(s)
  • @gnosticdev/hono-actions/client: Pre-built Hono client and helpers (honoClient, parseResponse)
    • Safe for browser and server environments
  • @gnosticdev/hono-actions: Astro integration
    • Uses Node.js built-ins (fs, path)
    • Only used in astro.config.ts

Configuration Options

The integration accepts the following options:

  • basePath (optional): The base path for your API routes. Default: '/api'
  • actionsPath (optional): Custom path to your actions file if not using auto-discovery

Features

  • Type-safe: Full TypeScript support with automatic type inference
  • Validation: Built-in request validation using Zod schemas
  • Error handling: Custom error types and automatic error responses
  • Auto-discovery: Automatically finds your actions file
  • Client generation: Pre-built client with full type safety
  • Development: Hot reload support during development
  • Flexible routing: Define standard Hono routes (GET/PATCH/etc.) alongside POST actions

Troubleshooting

Actions not found

If you get an error that no actions were found, make sure:

  1. Your actions file is in one of the supported locations
  2. You export a honoActions object containing your actions and any Hono routes
  3. The file path matches the actionsPath option if you specified one

Type errors

If you're getting TypeScript errors:

  1. Make sure all peer dependencies are installed
  2. Run astro sync to regenerate types
  3. Restart your TypeScript server in your editor

Module resolution errors

If you get module resolution errors during development:

  1. Try clearing your node_modules and reinstalling
  2. Make sure you're using compatible versions of the peer dependencies

Advanced Usage

Using AsyncLocalStorage with Custom Hono Instances

For advanced use cases involving request-scoped data and custom Hono instances, see docs/async_hooks.md.

License

MIT