TypeScript / Node.js
TypeScript / Node.js
qgis-rs for Node.js ships a NAPI-RS native addon (qgis-rs.<platform>.node) at native speed, plus TypeScript types and CLI wrappers (qgis-cli, qgis-plugin) that run the Rust binaries from crates/qgis-cli / crates/qgis-sdk when they are installed.
- npm:
npm install qgis-rs→require('qgis-rs')+qgis-clion PATH - API:
Extent,Crs,TilePlan,Projectvia NAPI, QGIS backend optional - CLI:
qgis-cliandqgis-pluginwrappers that try Rust binary first, fallback to JS
qgis-rs (Python) and qgis-sdk (Python plugin SDK) can stay — this is the TypeScript counterpart, same Rust workspace.
Installation
npm install qgis-rs# oryarn add qgis-rspnpm add qgis-rsPre-built binaries for Linux x64 (gnu + musl) and Linux arm64 (gnu). Falls back to pure JS if no native binary, and you can build from source with bun run build (requires Rust ≥1.96).
From source (the addon builds and tests with bun — in this repository turbo runs the package’s own build/test scripts):
git clone https://github.com/Archont561/qgis-rscd qgis-rs
# The Bun workspace at the root owns resolution; ts-packages/qgis-node is a# member of it, so there is nothing to install in the package directory.pixi run bun-installbun x turbo run build --filter=qgis-rsbun x turbo run test --filter=qgis-rsTypeScript API
import { Project, Extent, TilePlan, ZoomRange, Crs, planTiles, version } from 'qgis-rs';
const project = Project.open('map.qgs');console.log(project.path, project.format);
const info = project.info();console.log(info.toJson());
// Pure-Rust geometry — native speed, no QGISconst extent = Extent.parse('14,50,15,51');console.log(extent.width(), extent.height());
const crs = Crs.fromEpsg(3857);console.log(crs.authId, crs.isProjected());
// Tile planningconst zooms = ZoomRange.parse('10-14');const plan = new TilePlan(extent, zooms);console.log(`Would render ${plan.tileCount()} tiles`); // 4568
const result = planTiles('14,50,15,51', '10-14');console.log(result.total); // 4568
// Rendering through the native QGIS backendtry { const rendered = project.render('output.png', { width: 1920, height: 1080 }); console.log(`Wrote ${rendered.path} (${rendered.bytes} bytes)`);} catch (e) { console.log(`QGIS rendering failed: ${e.message}`);}CommonJS:
const { Project, Extent, TilePlan, ZoomRange } = require('qgis-rs');
const extent = Extent.parse('14,50,15,51');const plan = new TilePlan(extent, ZoomRange.parse('10-14'));console.log(plan.tileCount());CLI
npx qgis-cli --helpnpx qgis-cli info map.qgs --jsonnpx qgis-cli tiles map.qgs -z 10-14 -b 14,50,15,51 -o ./tiles/ --dry-runnpx qgis-plugin --helpnpx qgis-plugin new my_plugin --type processing --rustThe wrappers (bin/qgis-cli.js, bin/qgis-plugin.js) try to find the Rust binary (target/release/qgis-cli, ~/.cargo/bin/qgis-cli, or on PATH) for native speed, otherwise fallback to JS implementation using the NAPI addon (or pure JS fallback).
With Express
import express from 'express';import { Project } from 'qgis-rs';
const app = express();const project = Project.open('map.qgs');
app.get('/info', (req, res) => { res.json(JSON.parse(project.info().toJson()));});
app.listen(3000);Architecture
qgis-rs npm package├── qgis-rs.<platform>.node → NAPI addon (Rust) — exposes one function, invoke(json)├── src/│ ├── index.js → JS wrapper (Extent, Crs, TilePlan, Project…) over that call│ └── index.d.ts → TypeScript types└── bin/ ├── qgis-cli.js → Node wrapper around the Rust binary └── qgis-plugin.js → same for plugin SDKThere is no JavaScript fallback: every value this package returns is computed by Rust, so a platform without a matching addon builds one rather than quietly getting different answers.
- Rust:
crates/qgis-protocol(the wire format),crates/qgis-engine(the dispatcher),crates/qgis-render(pure Rust),crates/qgis-cli,crates/qgis-node(NAPI addon),crates/qgis-sdk - JS:
ts-packages/qgis-node/— npm package (the typed client); the addon is built fromcrates/qgis-node/
Conda-forge
For conda, install the runtime the addon needs plus QGIS:
conda install -c conda-forge nodejs qgisnpm install qgis-rsThere is no Node.js toolchain in this repository — the addon is built, tested and
packed with bun, and the build only needs cargo. The nodejs above is for
consuming the published package, not for building it.
qgis-cli binary from conda-forge qgis-rs Python package is also on $PREFIX/bin.
Performance
Pure-Rust ops (no QGIS):
| Operation | Rust (NAPI) | JS fallback | Speedup |
|---|---|---|---|
| Extent parse | 0.5µs | 5µs | 10× |
| TilePlan 10-14 | 0.2ms | 3ms | 15× |