4. Write your own package
Declare a resource in a package manifest and implement its check/apply wscript.
After this lesson you can
- Register a resource with typed params in package.wcl - Implement the check() / apply() entry points in wscript - Validate that the script compiles against the host API
Before you start: Facts, variables, and ordering
A package is a folder under pkgs/ with a package.wcl that registers what it provides. Drop the folder in and it's discovered on the next run — no registry, no recompile. Each resource names its wscript and declares a param per input; playbook properties are validated against those params before anything executes.
The script exports check(params) -> Result[CheckResult, string] and apply(params) -> Result[ApplyResult, string]. check must never mutate; apply must converge so a re-check returns AlreadyConfigured — even in a fresh process. That is the whole contract, and the testlab (next lessons) exists to prove you honoured it.
§ 1Exercise: A marker-file resource
Create pkgs/mypkg/ with a dir_present resource that ensures a directory exists, then validate.
// pkgs/mypkg/package.wcl
package "mypkg" {
description = "My first package"
resource "dir_present" {
description = "Ensure a directory exists"
script = "resources/dir_present.wscript"
concurrency = "parallel"
param "path" { description = "Absolute path" type = "string" required = true }
}
}
Expected result
config-weave validate ./my-playbook compiles the new script and exits 0; a step with resource = "mypkg.dir_present" converges and stays converged.
Hint
In the script: fs::is_dir(p) decides check; fs::mkdir(p) (creates missing parents) is the whole apply.
§ 2Exercise: Type-check scripts in your editor
Emit the host API interface next to your scripts so the wscript LSP checks them against the exact host surface.
&&
Expected result
weave.wscripti and a starter wscript.toml appear; the editor now flags a misspelled host function before validate does.