Luau utilities
Eight calls that are not resources. They return values, load code, or define a kind of your own, and none of them produces a plan line.
niwa.try
niwa.try<T...>(body: () -> T...) -> ()Run a block whose failures do not halt the apply. What fails inside it is reported and the run continues.
niwa.secret
niwa.secret(name: string | { name: string, from: string? }) -> SecretTake a handle on a secret. niwa searches the keychain, then secrets/<name>.age in the config repo, then an external manager; from forces one of them. The handle is opaque: it resolves at apply time, never at plan time, and the value never reaches the config or the screen.
niwa.render
niwa.render(template: string, values: { [string]: string | number | Secret }) -> RenderedFill a template with values, writing {name} where each one goes. The result is opaque, like a secret: the plan shows its shape, and a secret inside it stays masked everywhere.
niwa.use
niwa.use(source: string) -> ()Load a shared module. It is pinned by hash in niwa.lock and sandboxed exactly like your own code.
niwa.resource
niwa.resource<S>(kind: string, definition: { check: (read: ReadHandle, spec: S) -> boolean, apply: (act: ActHandle, spec: S) -> (), reverse: ((act: ActHandle, spec: S) -> ()) | false, describe: (spec: S) -> string, privileged: boolean? }) -> (spec: S) -> ResultDefine a resource kind of your own. It returns a constructor; calling the constructor declares a resource. check gets a read-only handle, so it cannot change the machine by construction, and reverse = false marks the kind irreversible. A custom kind may not take one of the nineteen reserved names.
niwa.exists
niwa.exists(path: string) -> booleanIs there something at this path? The answer is memoised for the run, so twenty guards asking it cost one look.
niwa.command
niwa.command(name: string) -> booleanIs this command on PATH? Memoised for the run, like exists.
niwa.host
niwa.host() -> ()Load hosts/<this machine>.luau if it exists. Call it last: the host file is the override, so it has to run after the modules it overrides.
Next
- Write a custom resource — define a kind with check, apply, reverse, and describe
- Facts — computed values available in config
