Loading...
Loading...
Use when building Elixir applications that need to evaluate JavaScript or TypeScript code, load ES modules, import npm/jsr packages, call JS functions from Elixir, or use V8 snapshots. Triggers on Denox, deno_core, Rustler NIF JS runtime, TypeScript transpilation in Elixir.
npx skill4agent add gsmlg-dev/code-agent denoximportexportimport()# mix.exs
{:denox, "~> 0.2.0"}| Function | Purpose | Event Loop |
|---|---|---|
| Create V8 isolate | — |
| Eval JS, return JSON string | No |
| Transpile+eval TS (no type-check) | No |
| Eval with Promises/ | Yes |
| Async TS eval | Yes |
| Eval, discard result ( | No |
| Load ES module file | Yes |
| Read+eval file (no import/export) | No |
| Call named JS function | No |
| Call async JS function | Yes |
| Eval + | No |
| TS eval + decode | No |
| Call + decode | No |
| Async call + decode | Yes |
{:ok, result} | {:error, message}exec:ok | {:error, message}Denox.runtime(
base_dir: "lib/js", # resolve relative module imports
sandbox: true, # disable fs/net extensions
cache_dir: "_denox/cache", # disk cache for remote modules
import_map: %{"utils" => "file:///path/to/utils.js"},
callback_pid: pid, # enable JS→Elixir callbacks
snapshot: snapshot_bytes # V8 snapshot for fast cold start
)evalcalleval_asynccall_asyncawaitimport()setTimeout# Sync — fast, no event loop
{:ok, "3"} = Denox.eval(rt, "1 + 2")
# Async — pumps event loop
{:ok, "42"} = Denox.eval_async(rt, "return await Promise.resolve(42)")deno run--checkconst x: string = 42{:ok, "42"} = Denox.eval_ts(rt, "const x: number = 42; x")Denox.exec(rt, "globalThis.add = (a, b) => a + b")
{:ok, "5"} = Denox.call(rt, "add", [2, 3])
{:ok, 5} = Denox.call_decode(rt, "add", [2, 3])# Load module with import/export support
{:ok, rt} = Denox.runtime(base_dir: "/path/to/project")
{:ok, _} = Denox.eval_module(rt, "/path/to/project/main.ts"){:ok, rt} = Denox.runtime(cache_dir: "_denox/cache")
{:ok, result} = Denox.eval_async(rt, """
const { z } = await import("https://esm.sh/zod@3.22");
return z.string().parse("hello");
""")eval_asyncimport()# Supervision tree
children = [{Denox.Pool, name: :js_pool, size: 4}]
# Usage (round-robin)
{:ok, result} = Denox.Pool.eval(:js_pool, "1 + 2")
Denox.Pool.load_npm(:js_pool, "priv/bundles/zod.js") # load into all:name:size{:ok, rt, handler} = Denox.CallbackHandler.runtime(
callbacks: %{
"greet" => fn [name] -> "Hello, #{name}!" end,
"add" => fn [a, b] -> a + b end
}
)
{:ok, _} = Denox.eval(rt, ~s[Denox.callback("greet", "Alice")]){:ok, snap} = Denox.create_snapshot("globalThis.helper = (x) => x * 2")
{:ok, rt} = Denox.runtime(snapshot: snap)
{:ok, "10"} = Denox.call(rt, "helper", [5])
# TypeScript snapshots
{:ok, snap} = Denox.create_snapshot("globalThis.add = (a: number, b: number) => a + b", transpile: true)Denox.Depsdeno# Install from deno.json
Denox.Deps.install()
# Add/remove deps
Denox.Deps.add("zod", "npm:zod@^3.22")
Denox.Deps.remove("zod")
# List deps
{:ok, imports} = Denox.Deps.list()
# Create runtime with installed deps
{:ok, rt} = Denox.Deps.runtime()mix denox.installmix denox.add <name> <spec>mix denox.remove <name>Denox.NpmdenoDenox.Npm.bundle!("npm:zod@3.22", "priv/bundles/zod.js")
:ok = Denox.Npm.load(rt, "priv/bundles/zod.js")[:denox, :eval, :start | :stop | :exception]:eval:eval_ts:eval_async:eval_ts_async:eval_module:eval_file| Mistake | Fix |
|---|---|
Using | Use |
Expecting type errors from | Denox is transpile-only, no type-checking |
| Sharing one runtime across concurrent tasks | Use |
Forgetting | Async wraps code in IIFE; use |
CDN import without | Set |
| Running untrusted code without sandbox | Use |