spaceship_fusion

Package Version Hex Docs

A build tool for Gleam projects that generates platform-specific shims, compiles class files, and bundles with esbuild.

Features

Installation

gleam add spaceship_fusion

CLI Commands

fusion init

Initialize a new project for fusion.

# Basic (Node runtime)
gleam run -m fusion -- init

# Cloudflare
gleam run -m fusion -- init --cloudflare

# Cloudflare with specific wrangler version
gleam run -m fusion -- init --cloudflare --wrangler=2

What it does:

  1. Edits gleam.toml with [fusion] section
  2. For --cloudflare: generates wrangler.toml with D1 binding

Flags:

FlagDescriptionDefault
--cloudflareTarget Cloudflare Workersfalse
--wrangler=<ver>Wrangler version (cloudflare only)"latest"

fusion build

Build the project.

gleam run -m fusion -- build

What it does:

  1. Scans src/classes/ for class .gleam files
  2. Runs gleam build --target javascript
  3. Generates class adapter files in build/fusion/classes/
  4. Generates platform-specific shim.js
  5. Processes static assets:
    • Copies directory to build/dist/ (non-Cloudflare)
    • Embeds includes as base64 in assets.mjs (Cloudflare)
  6. Bundles with esbuild to build/dist/index.js

fusion scan

Scan class files and display metadata.

gleam run -m fusion -- scan

fusion dev

Start development mode with file watching.

gleam run -m fusion -- dev

What it does:

  1. Runs full build
  2. Starts appropriate server based on runtime:
    • node → runs node build/fusion/shim.js
    • cloudflare → runs npx wrangler dev

fusion class create <name>

Create a new class file.

gleam run -m fusion -- class create "greeter"

What it does:

  1. Creates src/classes/ if it doesn’t exist
  2. Creates src/classes/<name>.gleam with template

fusion class list

List all class files.

gleam run -m fusion -- class list

Output:

Found 1 class(es)
  Greeter (classes/greeter)
    .greet(message: String)

Configuration

Add a [fusion] section to your gleam.toml:

[fusion]
runtime = "cloudflare"  # or "node", "bun", "deno"
entry_point = "main"    # function to call as entry point
port = 3000
minify = true
source_map = true

[fusion.assets]
directory = "public"                    # Public assets to serve
includes = ["priv/secret.cert"]         # Files to embed in bundle

Entry Point

The entry point function is called by the generated shim. The function signature depends on the runtime:

Web server (all runtimes):

pub fn main(req: Request(BitArray)) -> Response(BitArray) {
  // handle HTTP request
}

Cloudflare Workers (with env/ctx):

pub fn main(req: Request(BitArray), env: Dynamic, ctx: Dynamic) -> Response(BitArray) {
  // access env vars and context
}

Class Files

Place .gleam files in src/classes/ with annotations:

/// @extends Service
/// @name MyService
/// @export
pub fn handle_message(msg: String) -> String {
  // ...
}

Assets

Configure static assets in gleam.toml:

[fusion.assets]
# Public directory - served as static files
directory = "public"

# Private files - embedded in bundle for Cloudflare
includes = ["priv/cert.pem", "priv/config.json"]

Build behavior:

Runtimedirectoryincludes
Node/Bun/DenoCopied to dist/Copied to dist/
CloudflareCopied for [site]Embedded as base64 in assets.mjs

Reading assets in code:

import fusion/asset

// Read asset as bytes
let assert Ok(cert) = asset.read("priv/cert.pem")

// Read asset as string
let assert Ok(config) = asset.read_string("priv/config.json")

On Cloudflare, embedded assets are loaded from the bundle. On other runtimes, assets are read from the filesystem.

Build Output

build/
  fusion/
    classes/           # Generated class adapters
    shim.js            # Platform-specific entry point
    assets.mjs         # Embedded assets (Cloudflare only)
  dist/
    index.js           # esbuild output
    index.js.map       # Source map
    public/            # Copied public assets
    priv/              # Copied private assets (non-Cloudflare)

Runtime Shims

RuntimeEntry Point SignatureNotes
cloudflaremain(req, env, ctx)Generates wrangler.toml
nodemain(req)HTTP server with static files
bunmain(req)Bun.serve wrapper
denomain(req)Deno.serve wrapper

Examples

Basic Web Server (Node)

# gleam.toml
[fusion]
runtime = "node"
entry_point = "main"
port = 3000
// src/app.gleam
import gleam/http/request.{type Request}
import gleam/http/response

pub fn main(req: Request(BitArray)) -> response.Response(BitArray) {
  response.new(200)
  |> response.set_body(<<"Hello from Fusion!":utf8>>)
}

Cloudflare Worker with Assets

# gleam.toml
[fusion]
runtime = "cloudflare"
entry_point = "main"

[fusion.assets]
directory = "public"
includes = ["priv/api-key.txt"]
// src/app.gleam
import fusion/asset

pub fn main(req, env, ctx) {
  // Read embedded asset
  let assert Ok(api_key) = asset.read_string("priv/api-key.txt")
  
  response.new(200)
  |> response.set_body(<<"Hello!":utf8>>)
}

Development

gleam build   # Build the project
gleam test    # Run the tests
gleam format  # Format the code

License

Apache-2.0

Search Document