Compiling and nodemaps for Lune✎
A graph becomes a file, and the file is where it is. No DataModel, no project file.
Pending review
This page is about graphs whose Target is Lune. The bar along the top of the canvas says which, and a new graph takes the project's. For Roblox, the answer is a different one and it is on Compiling and nodemaps for Roblox.
A graph is a .nodescript under .roswaal/scripts. Compiling it writes a .luau file to the same place under the output directory, in the same shape: .roswaal/scripts/lib/json.nodescript writes src/lib/json.luau. Both directories are project settings.
Info
lune run main — so the layout on disk is the whole answer.Nodemap basics
Here is the whole of it. A .nodemap is edited in Roswaal rather than by hand, and this is that editor with Describes set to A filesystem — the tree on the left, the Inspector on the right, and the layout it describes underneath. Every part is named beside it; the rest of this page explains them in order.
This map
Directory
The layout
Directories and files, as they sit on disk. Nothing is written when this is compiled — a Lune program has no project file, so what compiling does is check the layout holds together.
main.luaurequire("./main")lib/ lib/json.luaurequire("./lib/json") lib/text.luaurequire("./lib/text")
- The treeEvery directory and file the project has. Pick one and the Inspector follows.
- DescribesWhether this is a DataModel for Roblox or a filesystem for Lune. It decides what the rest of the panel is.
- NameWhat it is called on disk — with no extension, which the row on the right adds.
- KindA directory, or a file Roswaal writes a .luau for. Absent on the project root, which is neither.
- Add directory, Add file, DeleteBuild the tree. A file takes no children.
- The layoutThe directories and files as they land, and the require that reaches each one. Nothing is written — compiling a filesystem map checks it.
main in the map, main.luau on disk, and the require that reaches it beside.What a graph compiles to
Always a .luau file named after the graph. A Roblox graph picks between Script, LocalScript and ModuleScript, and the choice decides the file's ending because Rojo reads it — Greeter.server.luau. Lune has no such distinction: a file is a file, and whether it is a program or a module is decided by whether something requires it.
Warning
Compiling
| What it compiles | |
|---|---|
Compile script, or Ctrl + S | The open graph |
| Compile project | Every graph, then every node map |
| Compile: Dynamic | Each graph as you edit it, and any that change on disk — after a git pull, say |
roswaal compile | Everything, or the one graph or map you give it |
roswaal watch | The same, without the editor |
A graph with errors writes nothing; warnings do not stop it. With format on and StyLua on your PATH, the file is formatted as it is written. Then lune run main — Roswaal does not run it for you.
A generated file starts with a header naming its graph and a hash of what was written. Roswaal will not overwrite a file whose hash no longer matches — one edited by hand — or a file it did not write. Rename a graph or move it and its next compile removes the file it used to write; roswaal prune lists the ones left behind by a graph that is gone.
What a nodemap is for here
A map still has a job, and it is the one Rojo was doing incidentally: saying the layout out loud, and checking it holds together. Set a map's Describes to A filesystem and it becomes directories and files rather than services and instances. A new map is already the right kind — it follows the project's target.
What the right-hand column is not is a file Roswaal writes. A filesystem map compiles to nothing: the disk is already the answer, and compiling the map is checking that the answer is one Luau can load.
| A DataModel map | A filesystem map | |
|---|---|---|
| Root is | The DataModel | The project directory |
| Children are | Services, folders, instances | Directories and files |
| Compiles to | default.project.json, for Rojo | Nothing — it is a check |
| A node has | A class and a path on disk | A name, and whether it is a file |
What it checks
These are require-time errors in Luau, not house style. The language refuses an ambiguous path rather than picking one, so a layout with both of these is one the runtime will not load — and a map catches it while you can still move something, with both things named.
- A file beside a directory of the same name.
require("./foo")cannot mean bothfoo.luauandfoo/init.luau. - Two files differing only by extension.
foo.luauandfoo.luaboth answer to./foo. - A name a require cannot reach — letters, digits,
.,-and_, and no directory separators.
Info
main in the map, main.luau on disk. Typing one is a warning, so you do not end up with main.luau.luau.Requires, and what the file depends on
Everything a Lune program reaches for arrives through a require you wrote. The standard library is Lune's standard library; a short name for a path is Aliases and .luaurc; and the rule behind both is on Modules — a generated file does not grow imports nobody chose.
Warning
@lune/roblox. Vector3 and CFrame compile once it is required with the datatype as a member; the Inspector has the button. TweenInfo is not offered in Lune.Not reviewed yet