{"id":51319288,"url":"https://github.com/tuist/javex","last_synced_at":"2026-07-01T11:02:35.234Z","repository":{"id":351402103,"uuid":"1210815298","full_name":"tuist/javex","owner":"tuist","description":"Compile JavaScript to WebAssembly with Javy and run it on wasmtime, from Elixir.","archived":false,"fork":false,"pushed_at":"2026-04-16T16:59:56.000Z","size":571,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-30T09:41:47.179Z","etag":null,"topics":["elixir","javy","wasm"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/javex","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tuist.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-14T19:33:17.000Z","updated_at":"2026-04-17T22:41:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tuist/javex","commit_stats":null,"previous_names":["tuist/javex"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tuist/javex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuist%2Fjavex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuist%2Fjavex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuist%2Fjavex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuist%2Fjavex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tuist","download_url":"https://codeload.github.com/tuist/javex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tuist%2Fjavex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35003464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","javy","wasm"],"created_at":"2026-07-01T11:02:34.373Z","updated_at":"2026-07-01T11:02:35.228Z","avatar_url":"https://github.com/tuist.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🌶 Javex\n\n\u003e Run JavaScript inside your Elixir app, sandboxed in WebAssembly.\n\n[![Hex.pm](https://img.shields.io/hexpm/v/javex.svg)](https://hex.pm/packages/javex)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![CI](https://github.com/tuist/javex/actions/workflows/ci.yml/badge.svg)](https://github.com/tuist/javex/actions/workflows/ci.yml)\n\nJavex compiles JavaScript to WebAssembly with [Javy](https://github.com/bytecodealliance/javy) and runs it on [wasmtime](https://wasmtime.dev/), so you can hand a snippet of user-written JS to a Wasm sandbox and get a typed result back. Each call gets a fresh instance — no shared state, nothing leaks between requests.\n\n## ✨ Why you might want this\n\n- 🧮 **User-defined transforms.** Let your users write small JS expressions to filter, map, or reshape data without giving them shell or BEAM access.\n- 🔌 **Webhook / payload mappers.** Accept a JS snippet from a customer and run it on incoming events.\n- 🧪 **Custom rules and DSLs** that need real expression power without inventing a parser.\n- 🪶 **Tiny, fast.** Compiled modules are typically **a few KB**. Cold start is sub-millisecond once a runtime is up.\n- 🔒 **Sandboxed by default.** Per-call fuel, memory, and wall-clock timeouts are first-class options.\n\n## 🚀 Quick start\n\nIn your `mix.exs`:\n\n```elixir\ndef deps do\n  [{:javex, \"~\u003e 0.1\"}]\nend\n```\n\nAdd a runtime to your supervision tree:\n\n```elixir\n# lib/my_app/application.ex\nchildren = [\n  Javex.Runtime\n]\n```\n\nCompile and run:\n\n```elixir\njs = ~S\"\"\"\nJavy.IO.writeSync(1, new TextEncoder().encode(JSON.stringify({hello: \"world\"})));\n\"\"\"\n\n{:ok, mod} = Javex.compile(js)\n{:ok, %{\"hello\" =\u003e \"world\"}} = Javex.run(mod, nil)\n```\n\n\u003e 💡 **Reading input** in your JS requires a small stdin helper — see [Javy's README](https://github.com/bytecodealliance/javy#example) for the canonical `readInput()` / `writeOutput()` snippet to drop at the top of your script.\n\n## ⚙️ The bits you'll reach for\n\n| You want to… | Use |\n| --- | --- |\n| Compile a JS snippet | `Javex.compile/2` |\n| Run a compiled module with JSON I/O | `Javex.run(mod, input)` |\n| Run with raw bytes | `Javex.run(mod, bytes, encoding: :raw)` |\n| Cap fuel, memory, or timeout | `Javex.run(mod, input, fuel: …, max_memory: …, timeout: …)` |\n| Run multiple tiers (trusted / untrusted) | `Javex.Runtime.start_link(name: :strict, default_fuel: …, default_max_memory: …)` |\n\nPersisting compiled modules? `%Javex.Module{}` is a plain struct — `:erlang.term_to_binary/1` round-trips it, no helper needed.\n\n## 🛡 Safety knobs\n\n```elixir\n{:ok, output} =\n  Javex.run(mod, input,\n    timeout: 250,                 # wall-clock ms\n    fuel: 5_000_000,              # wasmtime fuel units\n    max_memory: 8 * 1024 * 1024   # bytes\n  )\n```\n\nErrors come back as a tagged tuple, never a process exit:\n\n```elixir\n{:error, %Javex.RuntimeError{kind: :timeout}}        # epoch deadline elapsed\n{:error, %Javex.RuntimeError{kind: :fuel_exhausted}}\n{:error, %Javex.RuntimeError{kind: :oom}}\n{:error, %Javex.RuntimeError{kind: :js_error}}       # uncaught JS exception\n```\n\n## 🧠 How it works (in 60 seconds)\n\n- Javy compiles your JS to a **dynamically-linked** Wasm module that imports QuickJS from a shared provider plugin (bundled in `priv/`). Each compiled module is a few KB instead of ~1 MB.\n- `Javex.Runtime` owns one wasmtime `Engine` plus the preloaded plugin. The `Engine` is `Send + Sync`, so one runtime handles your whole BEAM. Spin up sibling runtimes when you need different resource tiers.\n- Every `run/3` creates a fresh wasmtime `Store` and instance — clean JS state per call, with no measurable cold-start cost because the provider is already alive.\n- The Rust NIF ships **precompiled** for macOS (Apple Silicon + Intel) and Linux (aarch64 + x86_64 GNU). No Rust toolchain required to install.\n\n## 📄 License\n\n[MIT](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuist%2Fjavex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftuist%2Fjavex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftuist%2Fjavex/lists"}