API
The JavaScript exports of the cursery package. In Node, it reads its WebAssembly from disk. Elsewhere, it imports it as a bundled module.
import { dispatch, evaluate, load, mount, renderToString, unload, unmount, } from "cursery";
load#
load(files)
Adds Nix files to the store. files maps paths to sources, e.g. from import.meta.glob. Returns their store path, the same one Nix gives the same files:
// Sources by path, e.g. `./app/default.nix`. const files = import.meta.glob("./app/**/*.nix", { query: "?raw", import: "default", eager: true, }); const path = load(files); // "/nix/store/…-source"
Paths are relative to the store path, so ./app/default.nix and app/default.nix are the same file. Loaded files can import each other by relative path. Identical files share a store path. Nothing is evaluated.
Throws if a path is outside the store path, or a source isn't a string.
unload#
unload(path)
Releases a store path from load. Its files stay available until every load of them is released. Throws if the path isn't loaded.
evaluate#
evaluate(code)
Evaluates a Nix expression strictly, and returns it as JavaScript. Attribute sets become objects with a null prototype.
evaluate("1 + 2"); // 3 evaluate("import ${path}/config.nix");
Evaluation is pure: impure builtins don't exist. Loaded files can be imported, and read with builtins.readFile. The bundled libraries resolve through the search path, as <web/...>.
Throws on syntax and evaluation errors, and on results JavaScript can't represent: functions, and integers beyond 253.
mount#
mount(container, path, options?)
Renders the app at path into the element container. path is a default.nix, or a directory with one, under a store path from load.
options.effects are the functions the app runs with io.call, by name. Each gets the input from Nix, and returns the output, or a promise of it. For usage, see Host IO.
The first mount replaces the container's contents. Mounting into it again, e.g. with a hot-reloaded path, updates the app in place: the DOM is patched to the new render, and the state carries over, ignoring the new init. The new options replace the old ones.
The app's global styles are adopted by the container's root, the document or a shadow root, while it's mounted.
Throws if the app fails to evaluate or render, or an effect isn't a function. The container and state are left as they were.
unmount#
unmount(container)
Removes the app mounted into the element, and clears its contents. Throws if nothing is mounted there.
dispatch#
dispatch(container, type, payload?)
Sends an action to the app mounted into the element, like io.dispatch type payload from Nix. payload is converted as JSON would, and defaults to null. The app renders before this returns. If update returns an effect, it runs in the dispatch's place. For usage, see Host IO.
Throws if nothing is mounted, the payload isn't JSON data, or the app is rendering. Also throws if update or its effect fails before waiting on a promise. Failures after that are logged.
renderToString#
renderToString(path, inputs?)
Renders the page at path to HTML, prefixed with <!doctype html>. It needs no DOM. path is a default.nix, or a directory with one, under a store path from load. The page is a function of inputs, converted as JSON would, defaulting to { }, that returns an html element. To write one, see Pre-rendering.
Throws if the inputs aren't JSON data, or the page fails to evaluate or isn't an html element.