Skip to content

fullofcaffeine/reflaxe.elixir

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Haxir logo

Reflaxe.Elixir (aka Haxir)

Version License: GPL-3.0 CI Haxe Elixir

Type-safe Haxe to Elixir compiler with Phoenix/LiveView support. Write business logic in Haxe, compile to idiomatic Elixir code for the BEAM ecosystem.

Warning

Stability: Reflaxe.Elixir v1.1.x is considered non‑alpha for the documented subset. Some features remain experimental/opt‑in (e.g. source mapping, migrations .exs emission, fast_boot). See: Known Limitations and Versioning & Stability.

Stability tiers (tl;dr)

  • Stable (documented subset): exercised by CI + todo-app; intended to be reliable within v1.x.
  • Experimental (opt-in): available, but expect rough edges and possible breaking changes (e.g. source maps, migrations .exs, fast_boot).
  • Dev/internal tooling: debug flags and contributor-only workflows; not part of the end-user stability contract.

See: Versioning & Stability.

Known sharp edges (top 3)

  • fast_boot is for faster local iteration; don’t rely on its output shape for CI/production builds.
  • Watcher port conflicts can happen (Phoenix watchers + Haxe server ports); the repo examples auto-probe, but custom setups may need tweaks.
  • Typed boundaries matter: prefer Term at external boundaries and decode into typed structures instead of using Dynamic.

See: Known Limitations.

Future Vision: See docs/08-roadmap/vision.md for long-term plans including AI tooling and universal platform support
Current Status: Stable subset (v1.1) — non‑alpha for the documented subset; experimental features are clearly labeled.

Why Reflaxe.Elixir?

🎯 Type-Safe BEAM Development with Haxe

The Problem: You want BEAM's incredible concurrency and fault tolerance, but Elixir's dynamic typing means runtime errors in production.

The Solution: Reflaxe.Elixir brings compile-time type safety to the BEAM ecosystem:

  • Type Safety Today - Catch errors at compile time, not in production
  • Idiomatic Elixir Output - Generated code looks hand-written by Elixir experts
  • Full Phoenix Integration - LiveView, Ecto, OTP, GenServers all supported
  • Future Expansion - Haxe's multi-target nature enables future platform support

The BEAM is designed to recover from failures (supervision + “let it crash/let it heal”), but typed code still helps a lot:

  • Prevent accidental crashes and make refactors safer.
  • Make intentional failures explicit (e.g. Result/Option patterns) so you can be deliberate about what should crash vs what should be handled locally.

How this compares to Gleam

Gleam is an excellent typed BEAM language with a strong focus on correctness and a great compiler UX. Reflaxe.Elixir takes a different path:

  • Direct Elixir ecosystem leverage: Reflaxe.Elixir generates idiomatic Elixir and targets HEEx (~H) and Phoenix/LiveView patterns directly.
  • Fewer “FFI boundary” tradeoffs: in Gleam, calling into non-Gleam libraries via externals is powerful, but the external code can’t be type-checked by the Gleam compiler and editor assistance is reduced. Reflaxe.Elixir aims to keep you on the “typed path” while still producing standard Elixir/Phoenix code.

💡 Real-World Scenarios

Build Type-Safe Phoenix Applications

Write your Phoenix app in Haxe and get:

  • Compile-time validation of LiveView assign/update patterns
  • Type-safe Ecto schemas with automatic changeset generation
  • OTP supervision trees with typed GenServer callbacks
  • Idiomatic Elixir output that Phoenix developers recognize

Share Code with Frontend (Future)

The foundation for multi-target development:

  • Business logic in Haxe - validation, algorithms, data transformations
  • Backend on BEAM - Phoenix/LiveView/Ecto with full type safety ✅
  • Frontend on JavaScript - Async/await support + Genes ES module output (see todo-app) ✅
  • TypeScript ecosystem access - dts2hx planned (optional future)

Leverage BEAM's Unique Strengths

  • Massive concurrency - Handle millions of connections with lightweight processes
  • Fault tolerance - Let it crash philosophy with supervisor recovery
  • Hot code reloading - Update production systems without downtime
  • Type safety - Catch errors before they reach production

🚀 How It Compares

Reflaxe.Elixir Gleam Pure Elixir TypeScript
Type Safety ✅ Compile-time ✅ Compile-time ❌ Runtime ✅ Compile-time
BEAM Integration ✅ Full Phoenix/OTP ✅ Native ✅ Native ❌ None
Phoenix LiveView ✅ Native support ⚠️ Via externals (tradeoffs) ✅ Native ❌ None
Multi-target Potential ✅ Haxe foundation ✅ BEAM + JS ❌ BEAM only ⚠️ JS only
Ecosystem Maturity ✅ Since 2005 ⚠️ New ✅ Mature ✅ Mature
Learning Curve ✅ TypeScript-like ⚠️ Rust-like ⚠️ Ruby-like ✅ Familiar

🎪 Built on Proven Technology

  • Haxe (2005): Battle-tested cross-platform toolkit used in production by companies like Netflix, Disney, BBC, Toyota, and more
  • Elixir/BEAM: Powers WhatsApp (2B users), Discord, Pinterest, and other massive-scale systems
  • Reflaxe: Modern compiler framework making Haxe more powerful than ever

Current Status & Roadmap

✅ Stable (v1.1)

  • Phoenix Integration - LiveView, controllers, templates, routers 100% supported
  • HXX Template System - Complete compile-time JSX→HEEx transformation with AST-based processing
    • Template Helper Metadata ✨ NEW - Uses @:templateHelper metadata for extensible Phoenix function compilation
    • Type-Safe Phoenix Abstractions ✨ NEW - Assigns, LiveViewSocket, FlashMessage, RouteParams with operator overloading
  • Ecto Integration - Schemas, changesets, and typed queries supported; migrations remain opt‑in/experimental (-D ecto_migrations_exs)
  • Mix Integration - Seamless build pipeline with file watching and incremental compilation
  • Source Mapping (experimental) - .ex.map emission + mix haxe.source_map lookup are implemented (line coverage + many expression-level boundaries; see docs/04-api-reference/SOURCE_MAPPING.md)
  • OTP Support - GenServers, Supervisors, Registry with type-safe compilation
  • Type Safety - Complete Haxe→Elixir type mapping and compile-time validation
  • JavaScript Async/Await - Native async/await compilation for modern JS development

🔮 Future Expansion

For the complete roadmap including AI tooling, universal deployment, and multi-platform support, see docs/08-roadmap/vision.md:

  • JavaScript Integration - Advanced TypeScript ecosystem access
  • Mobile Support - Capacitor and React Native deployment
  • Desktop Applications - Electron/Tauri cross-platform apps
  • AI-Enhanced Tooling - Intelligent development assistance

Installation

Prerequisites

  • Haxe 4.3.7+ (installed globally, or pinned per-project via lix and used via ./node_modules/.bin/haxe)
  • Node.js 16+ (for lix package management; Node 20 recommended)
  • Elixir 1.14+ (for Phoenix/Ecto ecosystem)

Method 1: Install via Lix (Recommended)

# Create a lix scope in your project directory
npx lix scope create

# Install the latest GitHub release tag (recommended)
# If this fails (no `curl` / GitHub rate limit), pick a tag from the Releases page and set it manually.
REFLAXE_ELIXIR_TAG="$(curl -fsSL https://api.github.com/repos/fullofcaffeine/reflaxe.elixir/releases/latest | sed -n 's/.*\"tag_name\":[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p' | head -n 1)"
npx lix install "github:fullofcaffeine/reflaxe.elixir#${REFLAXE_ELIXIR_TAG}"

# Download pinned Haxe libraries for the project (reflaxe + tink_* + deps)
npx lix download

# Bleeding edge (main branch; not necessarily a release)
# npx lix install github:fullofcaffeine/reflaxe.elixir --force

Reflaxe.Elixir GitHub Releases are created for vX.Y.Z tags. To use a specific release, install that tag with lix.

Method 2: Vendoring (Copy source directly)

For projects that want to vendor the compiler source:

# Clone or download the repository
git clone https://github.com/fullofcaffeine/reflaxe.elixir.git

# Copy necessary files to your project
cp -r reflaxe.elixir/src/ your-project/vendor/reflaxe.elixir/src/
cp -r reflaxe.elixir/std/ your-project/vendor/reflaxe.elixir/std/
cp reflaxe.elixir/haxelib.json your-project/vendor/reflaxe.elixir/

# In your build.hxml, add:
# -cp vendor/reflaxe.elixir/src
# -cp vendor/reflaxe.elixir/std
# -lib reflaxe
# --macro reflaxe.elixir.CompilerInit.Start()

Usage in Your Project

Once installed, add to your build.hxml:

-lib reflaxe.elixir
-cp src_haxe

# Output directory for generated .ex files
-D elixir_output=lib/my_app_hx

# Required for Reflaxe targets
-D reflaxe_runtime

# Elixir is not a UTF-16 platform
-D no-utf16

# Application module prefix (prevents collisions with Elixir built-ins like `Application`)
-D app_name=MyAppHx

# Enable dead code elimination to reduce output noise
-dce full
#
# Why this repo recommends `-dce full`:
# - Keeps generated `.ex` output small and readable (less stdlib/helpers noise).
# - Makes snapshot diffs meaningful and keeps CI/budgets predictable.
# - Catches “indirect runtime reference” regressions early (OTP/Phoenix callbacks/modules can be DCE’d otherwise).

# Define a stable entrypoint
# Entrypoint Haxe class (package.ClassName). Adjust to your app.
--main my_app_hx.Main

⚠️ Important: Compiler Configuration

DO NOT use -D analyzer-optimize when compiling to Elixir. This flag triggers aggressive optimizations designed for C++ and JavaScript that produce non-idiomatic Elixir code.

Recommended configuration:

# Good optimizations
-dce full                    # Dead code elimination (recommended)
-D loop_unroll_max_cost=0    # Disable loop unrolling (preserve functional shapes)

# AVOID these
# -D analyzer-optimize       # Destroys functional patterns
# -D analyzer-check          # May trigger unwanted optimizations

For complete compiler configuration guidance, see docs/01-getting-started/compiler-flags-guide.md.

Quick Start

Start Here (New to Haxe and/or Phoenix?)

Follow: docs/01-getting-started/START_HERE.md

  • Run the repo todo-app (end-to-end) with a single command
  • Learn the Haxe→Elixir→Phoenix mental model
  • Generate a fresh Phoenix+Haxe project via the generator

Hello Phoenix in ~5 minutes (no repo clone)

This creates a new Phoenix+Haxe project using the latest GitHub release tag:

mkdir haxir-demo && cd haxir-demo
npm init -y
npm install --save-dev lix
npx lix scope create

# Install the generator (latest GitHub release tag)
# If this fails (no `curl` / GitHub rate limit), pick a tag from the Releases page and set it manually.
REFLAXE_ELIXIR_TAG="$(curl -fsSL https://api.github.com/repos/fullofcaffeine/reflaxe.elixir/releases/latest | sed -n 's/.*\"tag_name\":[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p' | head -n 1)"
npx lix install "github:fullofcaffeine/reflaxe.elixir#${REFLAXE_ELIXIR_TAG}"

# Optional but recommended: pin a known-good Haxe toolchain (avoids relying on a global install).
npx lix download haxe 4.3.7
npx lix use haxe 4.3.7

# Generate a Phoenix app
# (Use `haxe --run Run` here because some lix/haxelib shim versions rely on an internal
# `run-dir` command which is not reliable across environments.)
REFLAXE_ELIXIR_SRC="$(./node_modules/.bin/haxelib path reflaxe.elixir | tr -d '\r' | grep -E 'reflaxe\.elixir/.*/src/?$' | head -n 1)"
./node_modules/.bin/haxe -cp "$REFLAXE_ELIXIR_SRC" --run Run create hello_haxir --type phoenix --no-interactive

cd hello_haxir
mix setup
mix phx.server

See also: docs/06-guides/PHOENIX_NEW_APP.md.

Quick Demo (Todo App)

Run a full build + boot + Playwright smoke without blocking your terminal:

scripts/qa-sentinel.sh --app examples/todo-app --env e2e --port 4001 --playwright --e2e-spec "e2e/*.spec.ts" --async --deadline 900 --verbose
scripts/qa-logpeek.sh --run-id <RUN_ID> --until-done 900

Phoenix (Recommended Next Step)

  • New Phoenix project: docs/06-guides/PHOENIX_NEW_APP.md
  • Add Haxe gradually to an existing Phoenix project: docs/06-guides/PHOENIX_GRADUAL_ADOPTION.md

Also see: docs/06-guides/QUICKSTART.md

Development Workflow

Basic Compilation

# Compile once
haxe build.hxml

# Watch for changes (long-running)
mix haxe.watch

Client Builds (JavaScript)

For Phoenix apps with client-side hooks, the recommended path is:

  • Genes (recommended): ES modules + clean output via -lib genes (see docs/05-architecture/HXML_ARCHITECTURE.md and examples/todo-app/build-client.hxml).
  • Plain Haxe JS target: still works, but you’ll write more interop glue and typically won’t get ES module output.

Running Tests

# Full test suite (snapshots + Mix task tests)
npm test

# Compile-check every example under examples/
npm run test:examples

# Quick snapshot-only run
npm run test:quick

Running Examples

Each example is self-contained and documented. Start here:

  • examples/README.md

Most examples can be compiled with:

cd examples/<example-name>
haxe build.hxml   # or compile-all.hxml when present

Phoenix Integration

# Add to your Phoenix project's mix.exs
defp deps do
  [
    # ... other deps
    # Mix tasks only (build-time): pin to a GitHub release tag or use a commit SHA
    # Replace <RELEASE_TAG> with the tag you installed via lix (e.g. v1.2.3)
    {:reflaxe_elixir, github: "fullofcaffeine/reflaxe.elixir", tag: "<RELEASE_TAG>", only: [:dev, :test], runtime: false}
  ]
end

> Note: the `mix haxe.gen.*` generators are Haxe-first scaffolds (they emit **Haxe only**, not Elixir). Treat them as starting points and compare against `examples/todo-app/` for current Phoenix patterns. See `docs/04-api-reference/MIX_TASKS.md` for details.

# Compile Haxe as part of your build
mix compile.haxe

# Start Phoenix with Haxe compilation
mix phx.server

File Organization

your-project/
├── src_haxe/              # Your Haxe source files
│   ├── controllers/       # Phoenix controllers
│   ├── live/             # LiveView modules  
│   ├── contexts/         # Business logic
│   └── schemas/          # Ecto schemas
├── lib/                  # Generated Elixir files
│   └── (compiled output)
├── build.hxml            # Haxe build configuration
└── mix.exs              # Phoenix/Elixir dependencies

📚 Documentation

Start at docs/README.md for the curated documentation index.

Quick Links

Codegen Conventions

Reference

Examples

Each example includes its own README.md with compile/run steps:

  • examples/01-simple-modules/README.md
  • examples/02-mix-project/README.md
  • examples/03-phoenix-app/README.md
  • examples/04-ecto-migrations/README.md
  • examples/05-heex-templates/README.md
  • examples/06-user-management/README.md
  • examples/07-protocols/README.md
  • examples/08-behaviors/README.md
  • examples/09-phoenix-router/README.md
  • examples/10-option-patterns/README.md
  • examples/11-domain-validation/README.md
  • examples/test-integration/README.md
  • examples/todo-app/README.md

You can compile-check all examples with npm run test:examples.

Architecture

Project Meta

  • CONTRIBUTING.md – contribution workflow and commands
  • SECURITY.md – vulnerability reporting process
  • CODE_OF_CONDUCT.md – community guidelines
  • RELEASING.md – release checklist and tagging

Manual Installation (For Contributors)

# Clone and setup
git clone https://github.com/fullofcaffeine/reflaxe.elixir
cd reflaxe.elixir

# Install dependencies (both ecosystems)
npm ci            # Installs lix + Haxe dependencies
npx lix download  # Downloads project-specific Haxe libraries
mix deps.get      # Installs Elixir dependencies

# Run tests
npm test          # Full suite (snapshots + Elixir validation + Mix)
npm run qa:sentinel  # Todo-app build + boot probe (async)

📖 New to lix or Haxe? See docs/01-getting-started/installation.md for complete setup guide with troubleshooting.

Project Structure

Reflaxe.Elixir follows standard Reflaxe compiler conventions (similar to Reflaxe.CPP):

reflaxe.elixir/
├── src/                    # Compiler source (macro-time transpiler code)
│   └── reflaxe/elixir/     # ElixirCompiler.hx and helpers
├── std/                    # Standard library (compile-time classpath)
│   ├── elixir/             # Elixir stdlib externs (IO, File, GenServer, etc.)
│   ├── phoenix/            # Phoenix framework externs (LiveView, Socket, etc.)
│   └── ecto/               # Ecto ORM externs (Schema, Changeset, Query)
├── lib/                    # Elixir runtime support (Mix integration)
│   ├── haxe_compiler.ex    # Mix compilation task
│   ├── haxe_watcher.ex     # File watching for development
│   └── haxe_server.ex      # Haxe compilation server wrapper
├── test/                   # Compiler tests (snapshot testing)
└── examples/               # Example applications
    └── todo-app/           
        └── src_haxe/       # User application code in Haxe

Directory Purposes

  • src/ - The compiler that transforms Haxe TypedExpr → ElixirAST → transforms → printed Elixir
  • std/ - Haxe externs and abstractions for Elixir/Phoenix/Ecto functionality (included via -lib reflaxe.elixir or vendoring)
  • lib/ - Elixir runtime files needed for Mix integration and compilation support
  • src_haxe/ - User application code written in Haxe (in examples)

This separation follows Reflaxe conventions and ensures clear boundaries between compiler code, standard library, and user application code.

Architecture

Reflaxe.Elixir uses a dual-ecosystem architecture:

🔧 Haxe Development (npm + lix)

  • Compiler development: Build the Haxe→Elixir compiler
  • Modern testing: tink_unittest + tink_testrunner with rich output
  • Dependency management: lix with GitHub sources + locked versions

⚡ Elixir Runtime (mix)

  • Generated code testing: Validate compiled Elixir modules
  • Phoenix integration: Test LiveView, Ecto, GenServer workflows
  • Native tooling: Standard mix tasks and BEAM ecosystem

Usage

Source Mapping (Experimental)

Reflaxe.Elixir has early scaffolding for Haxe→Elixir source mapping, but it is not yet fully wired end‑to‑end (map emission + runtime lookup).

See docs/04-api-reference/SOURCE_MAPPING.md for current status and how to experiment.

Phoenix LiveView

	import HXX.*;
	import elixir.types.Term;
	import phoenix.LiveSocket;
	import phoenix.Phoenix.HandleEventResult;
	import phoenix.Phoenix.MountResult;
	import phoenix.Phoenix.Socket;

typedef CounterAssigns = { count: Int };

	@:native("MyAppWeb.CounterLive")
	@:liveview
	class CounterLive {
	    public static function mount(_params: Term, _session: Term, socket: Socket<CounterAssigns>): MountResult<CounterAssigns> {
	        var liveSocket: LiveSocket<CounterAssigns> = socket;
	        liveSocket = liveSocket.assign(_.count, 0);
	        return MountResult.Ok(liveSocket);
	    }

	    @:native("handle_event")
	    public static function handle_event(event: String, _params: Term, socket: Socket<CounterAssigns>): HandleEventResult<CounterAssigns> {
	        var liveSocket: LiveSocket<CounterAssigns> = socket;

        return switch (event) {
            case "increment":
                var nextCount = liveSocket.assigns.count + 1;
                HandleEventResult.NoReply(liveSocket.assign(_.count, nextCount));
            case _:
                HandleEventResult.NoReply(liveSocket);
        }
    }

	    public static function render(assigns: CounterAssigns): String {
	        return hxx('
	            <div class="counter">
	                <h1>${assigns.count}</h1>
	                <button phx-click="increment">+</button>
	            </div>
	        ');
	    }
	}
	```

Inline markup (optional syntax sugar)

If you prefer TSX-like authoring, you can also use Haxe inline markup literals as sugar over `hxx(...)`:

```haxe
class CounterView {
  public static function render(assigns: CounterAssigns): String {
    return <div class="counter">
      <h1>${assigns.count}</h1>
      <button phx-click="increment">+</button>
    </div>;
  }
}

Notes:

  • Inline markup is opt-in: enable it with -D hxx_inline_markup.
  • For a fragment root (React-style), you can use <> ... </>.
  • The root tag must be a valid XML name (or a fragment), so Phoenix dot-components like <.form> cannot be the root; wrap them in <> ... </> (or a normal element).

More: docs/02-user-guide/INLINE_MARKUP.md

Compiles to:

defmodule CounterLive do
  use Phoenix.LiveView
  
  def mount(_params, _session, socket) do
    {:ok, assign(socket, :count, 0)}
  end
  
  def handle_event("increment", _params, socket) do
    count = socket.assigns.count + 1
    {:noreply, assign(socket, :count, count)}
  end
  
  def render(assigns) do
    ~H"""
    <div class="counter">
      <h1>{assigns.count}</h1>
      <button phx-click="increment">+</button>
    </div>
    """
  end
end

Note: the Haxe return values are enums (MountResult.Ok(...), HandleEventResult.NoReply(...)), which compile to the standard Elixir atom-tagged tuples ({:ok, ...}, {:noreply, ...}).

Ecto Changesets

@:changeset  
class UserChangeset {
    @:validate_required(["name", "email"])
    @:validate_format("email", ~r/\S+@\S+\.\S+/)
    static function changeset(user, attrs) {
        // Compiled to proper Ecto.Changeset pipeline
    }
}

OTP GenServer

import elixir.types.Atom;
import elixir.types.GenServerCallbackResults.HandleCallResult;
import elixir.types.GenServerCallbackResults.InitResult;
import elixir.types.Term;

enum abstract CounterCall(Atom) to Atom {
    var Get = "get";
    var Increment = "increment";
}

@:genserver
class CounterServer {
    public static function init(initial: Int): InitResult<Int> {
        return InitResult.Ok(initial);
    }

    @:native("handle_call")
    public static function handle_call(request: CounterCall, _from: Term, state: Int): HandleCallResult<Int, Int> {
        return switch (request) {
            case Get:
                HandleCallResult.Reply(state, state);
            case Increment:
                HandleCallResult.Reply(state + 1, state + 1);
        }
    }
}

Development

Testing

The project uses a dual-ecosystem testing approach with self-referential library configuration:

npm test              # Full suite (snapshots + Elixir validation + Mix)
npm run test:quick    # Snapshot suite only
npm run test:mix      # Mix/Elixir tests only
npm run test:generator # Generator + Mix task scaffolds
npm run test:update   # Update expected snapshot outputs
npm run qa:sentinel   # Todo-app build + boot probe (async)
npm run ci:guards     # Guardrails (no app heuristics, etc.)

Test Infrastructure:

  • Complete Coverage: npm test runs Haxe compiler tests, generator tests, AND Mix runtime tests
  • Snapshot Testing: Validates compiler output against expected Elixir code
  • Generator Testing: Validates project templates and tooling
  • Runtime Validation: Mix tests compile/run generated Elixir code
  • Self-Referential Library: Tests use -lib reflaxe.elixir via haxe_libraries/reflaxe.elixir.hxml
  • Mix Integration: Tests real compilation in Phoenix projects
  • Test Helper: test/support/haxe_test_helper.ex handles project setup

⚠️ Critical: For self-referential library configuration issues, see docs/06-guides/SELF_REFERENTIAL_LIBRARY_TROUBLESHOOTING.md

For detailed testing documentation, see docs/03-compiler-development/TESTING_INFRASTRUCTURE.md

Development Workflow

# Start file watching for instant feedback
mix haxe.watch

# In another terminal, make changes
vim src_haxe/MyModule.hx  # Files auto-compile on save

# Or for compiler development:
vim src/reflaxe/elixir/ElixirCompiler.hx
npm test  # Test compiler changes

LLM Development

Perfect for AI-assisted development with fast feedback loops:

# Start watching with LLM-friendly output
mix haxe.watch --verbose

# LLM creates/modifies .hx files → automatic compilation
# Sub-second feedback enables rapid iteration

Package Management

Why lix + npm?

  • lix: Modern Haxe package manager with GitHub sources
  • npm: JavaScript ecosystem integration and script orchestration
  • Benefits: Project-specific Haxe versions, zero global conflicts

Why mix?

  • Native Elixir tooling: Industry standard for BEAM development
  • Phoenix ecosystem: Seamless LiveView, Ecto, OTP integration
  • Generated code validation: Tests the actual output, not just compilation

Performance

All compilation targets exceed performance requirements:

  • Basic compilation: 0.015ms (750x faster than 15ms target) ⚡
  • Ecto Changesets: 0.006ms average (2500x faster) ⚡
  • Migration DSL: 6.5μs per migration (2300x faster) ⚡
  • OTP GenServer: 0.07ms average (214x faster) ⚡
  • Phoenix LiveView: <1ms average (15x faster) ⚡

Verification

CI is the source of truth (see the CI badge above). Locally:

New-user quickcheck (install from GitHub release tag)

This validates that a brand-new project can install Reflaxe.Elixir from a vX.Y.Z release and compile a generated Phoenix app.

mkdir -p /tmp/reflaxe_elixir_verify && cd /tmp/reflaxe_elixir_verify
npm init -y
npm install --save-dev lix
npx lix scope create

# Pin a known-good Haxe toolchain (avoids relying on a global install).
npx lix download haxe 4.3.7
npx lix use haxe 4.3.7

# Install the latest GitHub release tag (recommended).
# If this fails (no `curl` / GitHub rate limit), pick a tag from the Releases page and set it manually.
REFLAXE_ELIXIR_TAG="$(curl -fsSL https://api.github.com/repos/fullofcaffeine/reflaxe.elixir/releases/latest | sed -n 's/.*\"tag_name\":[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p' | head -n 1)"
npx lix install "github:fullofcaffeine/reflaxe.elixir#${REFLAXE_ELIXIR_TAG}"
npx lix download

# Generate + compile a Phoenix app (compile-only smoke)
REFLAXE_ELIXIR_SRC="$(./node_modules/.bin/haxelib path reflaxe.elixir | tr -d '\r' | grep -E 'reflaxe\.elixir/.*/src/?$' | head -n 1)"
./node_modules/.bin/haxe -cp "$REFLAXE_ELIXIR_SRC" --run Run create my_app --type phoenix --no-interactive --skip-install
cd my_app
npm install --no-audit --no-fund
npx lix scope create
npx lix install "github:fullofcaffeine/reflaxe.elixir#${REFLAXE_ELIXIR_TAG}"
npx lix download
mix deps.get
mix compile

Maintainers: this flow is also verified weekly in CI by the scheduled workflow README Release Smoke (scheduled).

Repo verification (contributors / maintainers)

  • npm run ci:guards
  • npm test
  • npm run test:examples
  • npm run test:examples-elixir
  • npm run ci:budgets
  • npm run qa:sentinel (todo-app boot + Playwright smoke; non-blocking)

Contributing

See docs/10-contributing/contributing.md for detailed development guide. Releases are published automatically via semantic versioning; see docs/10-contributing/RELEASING.md.

Adding Features

  1. Extend the AST pipeline (src/reflaxe/elixir/ast/) in builder/transformer/printer layers
  2. Add/adjust std externs in std/ when exposing Elixir/Phoenix/Ecto APIs
  3. Add snapshot coverage under test/snapshot/ (and update intended outputs if needed)
  4. Run npm test and npm run qa:sentinel

Roadmap

License

GPL-3.0 - See LICENSE for details

Links

  • Haxe - The cross-platform toolkit
  • Reflaxe - Haxe-to-everything compiler framework
  • Elixir - Dynamic, functional language for BEAM
  • Phoenix - Productive web framework
  • lix - Modern Haxe package manager