The Go library for authoring Spade blocks. Define a handler
function, pass it to Run(), and the library handles parameter loading, input discovery,
and output writing.
go get github.com/krbundy/spadelibimport "github.com/krbundy/spadelib"The import path is the full module path, but the package identifier stays spadelib, so
calls read spadelib.Run(...), spadelib.Input[...], and so on.
package main
import "github.com/krbundy/spadelib"
func handler(args *spadelib.Args) (spadelib.RasterFile, error) {
source, err := spadelib.Input[spadelib.RasterFile](args, "source")
if err != nil {
return spadelib.RasterFile{}, err
}
resolution, err := spadelib.Param[float64](args, "resolution")
if err != nil {
return spadelib.RasterFile{}, err
}
// process source.Path at resolution...
return spadelib.NewRasterFile("result.tif"), nil
}
func main() {
spadelib.Run(handler)
}Run():
- Loads scalar parameters from
params.yaml - Scans
inputs/for file-based arguments, matched by name - Builds an
*Argsand calls your handler - Writes the returned value to
outputs/
On any error Run() prints it to stderr and exits non-zero.
A handler receives an *Args and pulls typed values out of it by name. Because Go generics
can't be methods, use the package-level Input and Param functions:
source, err := spadelib.Input[spadelib.RasterFile](args, "source") // file input
resolution, err := spadelib.Param[float64](args, "resolution") // scalar
if args.HasInput("mask") {
mask, err := spadelib.Input[spadelib.VectorFile](args, "mask") // optional input
}args.HasInput(name) and args.HasParam(name) test for optional arguments before reading.
Construct file types with the New* helpers (e.g. spadelib.NewRasterFile("path.tif"));
the location is on the Path field.
| Type | Description |
|---|---|
File |
Generic single file |
RasterFile |
Raster data (e.g., GeoTIFF) |
VectorFile |
Vector data (e.g., GeoJSON) |
TabularFile |
Tabular data (e.g., CSV) |
JsonFile |
JSON data |
| Type | Description |
|---|---|
Directory |
Directory-based input (e.g., shapefiles) |
| Type | Description |
|---|---|
FileCollection |
Collection of files |
RasterFileCollection |
Collection of raster files |
VectorFileCollection |
Collection of vector files |
TabularFileCollection |
Collection of tabular files |
Each holds a Paths []string field.
string, float64, int, bool, and the other basic types are read directly with
spadelib.Param[T].
File-based inputs are discovered from subdirectories in inputs/, where each subdirectory
name matches the name you pass to Input:
params.yaml # scalar args: {resolution: 10, method: "nearest"}
inputs/
reference/
data.tif # -> spadelib.Input[spadelib.RasterFile](args, "reference")
target/
data.tif # -> spadelib.Input[spadelib.RasterFile](args, "target")
The target type determines how each input is constructed:
- a
Filetype expects a single file in the subdirectory Directoryuses the subdirectory path itself- a
*Collectiontype gathers all files in the subdirectory
Return a typed value and Run() writes it to outputs/:
func handler(args *spadelib.Args) (spadelib.RasterFile, error) {
return spadelib.NewRasterFile("result.tif"), nil
}For multiple named outputs, return an *Outputs:
func handler(args *spadelib.Args) (*spadelib.Outputs, error) {
out := spadelib.NewOutputs()
out.Add("raster", spadelib.NewRasterFile("result.tif"))
out.Add("stats", spadelib.NewJsonFile("stats.json"))
return out, nil
}For a handler that produces no output, use spadelib.RunNoOutput, whose handler returns just
an error.
Named secrets provisioned to the block are read with GetSecret():
token, err := spadelib.GetSecret("api_token")Run() scrubs the secrets from the environment before your handler runs.
Describe a block's inputs and outputs with the manifest builder:
b := spadelib.NewManifestBuilder().Description("Resample a raster.")
spadelib.ManifestInput[spadelib.RasterFile](b, "source")
spadelib.ManifestOutput[spadelib.RasterFile](b, "raster")
manifest := b.Build()go test ./...See the Spade homepage for the full system documentation, the block specification, and the other language runtimes (Python, Rust, TypeScript, and R).