Quickstart
This guide walks you through creating a Spade block in TypeScript using the Bun runtime. By the end you will have a working block that reads a raster file, applies a buffer parameter, and writes the result.
Prerequisites🔗
- Bun 1.0 or later
- TypeScript 5.0 or later
- The Spade CLI installed (Installation guide)
Step 1: Create a block collection🔗
mkdir raster-tools && cd raster-tools
spade init --language typescriptThis scaffolds the project:
raster-tools/
package.json
src/
blocks/Install the Spade library:
bun add spadeStep 2: Add a block🔗
spade add reprojectThis creates:
blocks/reproject.yaml-- the block manifestsrc/reproject.ts-- the handler entrypoint
Step 3: Define the manifest🔗
Edit blocks/reproject.yaml:
id: raster-tools.reproject
version: 0.1.0
kind: standard
network: false
description: Reprojects a raster to a target resolution
inputs:
source:
type: file
format: GeoTIFF
resolution:
type: number
outputs:
raster:
type: file
format: GeoTIFFStep 4: Write the handler🔗
Edit src/reproject.ts:
import {
run,
spadeBlock,
RasterFile,
} from "spade";
const handler = spadeBlock({
inputs: {
source: RasterFile,
resolution: "number",
},
output: RasterFile,
description: "Reprojects a raster to a target resolution",
})(function handler({ source, resolution }: { source: RasterFile; resolution: number }) {
console.log(`Reprojecting ${source.path} at resolution ${resolution}`);
// Your raster processing logic here
const outputPath = "outputs/raster/reprojected.tif";
return new RasterFile(outputPath);
});
await run(handler);Key concepts:
spadeBlockis a decorator factory that attaches type metadata to your handler via aWeakMap. The metadata tellsrun()how to load inputs and tellsbuild()how to generate the manifest.- The handler receives a single object. File inputs arrive as typed class instances (e.g.,
RasterFilewith a.pathproperty). Scalar parameters likeresolutionarrive as plain values. run(handler)is the entry point, and it'sasync-- call it withawait. It readsparams.yamlfor scalar parameters, scansinputs/for file inputs, merges everything into a single argument object, calls your handler (awaiting it if it returns aPromise), and writes outputs.
Step 5: Validate and install🔗
spade check
spade install file://.Step 6: Use in a pipeline🔗
blocks:
- id: "@reproject"
name: raster-tools.reproject
inputs: []
args:
resolution: 10Alternative: setMetadata🔗
If you prefer not to use the decorator pattern, you can attach metadata with setMetadata directly:
import { run, setMetadata, RasterFile } from "spade";
function handler({ source, resolution }: { source: RasterFile; resolution: number }) {
return new RasterFile("outputs/raster/reprojected.tif");
}
setMetadata(handler, {
inputs: { source: RasterFile, resolution: "number" },
output: RasterFile,
});
await run(handler);Both approaches store the same metadata and produce identical behavior at runtime.
Next steps🔗
- Types -- all available Spade types
- Handler Functions -- handler patterns, async
run(), secrets, and multiple outputs - Manifest Generation -- auto-generating
block.yamlfrom metadata - Examples -- complete worked examples