Skip to content

A web framework written in Gleam, designed for multiple JavaScript runtimes and BEAM!

Notifications You must be signed in to change notification settings

Comamoca/hinoto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

27 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Last commit Repository Stars Issues Open Issues Bug Issues

fire

Hinoto

A web framework written in Gleam, designed for multiple JavaScript runtimes!

✨ Features

  • 🌐 Support multi runtimes
    Supports JavaScript runtimes (Node.js, Deno, Bun), CloudFlare Workers, and Erlang with Mist.
  • 🧩 Module first
    Features are divided into modules, generating JavaScript that is advantageous for Tree-shaking. Additionally, no extra FFI code is mixed in during bundling.
  • πŸ”§ Custom context
    The Hinoto type can contain arbitrary context, allowing runtime-specific information to be handled in the same way.
  • ⚑ Promise-based async (v2.0.0+)
    JavaScript targets use Promise-based handlers for async operations, while Erlang remains synchronous.

πŸš€ How to use

Node.js Example (v2.0.0+)

import gleam/http/request
import gleam/http/response
import gleam/javascript/promise
import gleam/option.{None}
import gleam/string
import hinoto
import hinoto/runtime/node

pub fn main() -> Nil {
  let fetch_handler =
    node.handler(fn(hinoto_instance) {
      use updated_hinoto <- promise.await(
        hinoto_instance
        |> hinoto.handle(handler),
      )
      promise.resolve(updated_hinoto)
    })

  node.start_server(fetch_handler, None, None)
}

pub fn handler(req) {
  case request.path_segments(req) {
    [] -> create_response(404, "<h1>Hello, Hinoto with Node.js!</h1>")
    ["greet", name] ->
      create_response(200, string.concat(["Hello! ", name, "!"]))
    _ -> create_response(404, "<h1>Not Found</h1>")
  }
  |> promise.resolve
}

pub fn create_response(status: Int, html: String) {
  response.new(status)
  |> response.set_body(html)
  |> response.set_header("content-type", "text/html")
}

Cloudflare Workers Example (v2.0.0+)

import gleam/http/request
import gleam/http/response
import gleam/javascript/promise.{type Promise}
import gleam/string
import hinoto.{type Hinoto}
import hinoto/runtime/workers.{type WorkersContext}

pub fn main() {
  workers.serve(fn(hinoto: Hinoto(WorkersContext, String)) -> Promise(
    Hinoto(WorkersContext, String),
  ) {
    use hinoto <- promise.await(
      hinoto
      |> hinoto.handle(handler),
    )
    promise.resolve(hinoto)
  })
}

pub fn handler(req) {
  case request.path_segments(req) {
    [] ->
      create_response(200, "<h1>Hello, Hinoto with Cloudflare Workers!</h1>")
    _ -> create_response(404, "<h1>Not Found</h1>")
  }
  |> promise.resolve
}

pub fn create_response(status: Int, html: String) {
  response.new(status)
  |> response.set_body(html)
  |> response.set_header("content-type", "text/html")
}

Note: v2.0.0 introduces Promise-based async handlers for JavaScript targets. See the Migration Guide below for upgrading from v1.x.

⬇️ Install

Add dependencies for hinoto and hinoto_cli to the dependencies section of gleam.toml.

hinoto = { git = "https://github.com/Comamoca/hinoto", ref = "main" }
hinoto_cli = { git = "https://github.com/Comamoca/hinoto_cli", ref = "main" }
gleam run -m hinoto/cli -- workers init
wrangler dev

⛏️ Development

For developing with various target JavaScript runtimes and CloudFlare Workers, wrangler is required.

cd example/

# For CF Workers
cd workers
wrangler dev

# For node.js
cd node_server

# For deno
cd deno_server

# For bun
cd bun_server

πŸ“ Todo

See todo.md

Request Body Types by Runtime

Each runtime uses an optimal body type for its environment:

Runtime Body Type Description
Mist (Erlang) Connection Native streaming body support for efficient handling of large uploads
Node.js String String-based bodies via Hinoto abstraction
Deno JsRequest Runtime-specific type handled via FFI
Bun JsRequest Runtime-specific type handled via FFI
Cloudflare Workers String String-based bodies via Hinoto abstraction

Why different types?

  • Erlang/Mist: Uses Connection to support streaming request bodies, enabling efficient handling of large file uploads and chunked data
  • JavaScript runtimes: Use String or runtime-specific types for simpler, stateless request handling

πŸ“œ License

MIT

🧩 Modules

πŸ‘ Affected projects

πŸ’• Special Thanks

About

A web framework written in Gleam, designed for multiple JavaScript runtimes and BEAM!

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •  

Contributors 2

  •  
  •