Skip to content

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-cli on PATH
  • API: Extent, Crs, TilePlan, Project via NAPI, QGIS backend optional
  • CLI: qgis-cli and qgis-plugin wrappers 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

Terminal window
npm install qgis-rs
# or
yarn add qgis-rs
pnpm add qgis-rs

Pre-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):

Terminal window
git clone https://github.com/Archont561/qgis-rs
cd 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-install
bun x turbo run build --filter=qgis-rs
bun x turbo run test --filter=qgis-rs

TypeScript 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 QGIS
const 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 planning
const 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 backend
try {
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

Terminal window
npx qgis-cli --help
npx qgis-cli info map.qgs --json
npx qgis-cli tiles map.qgs -z 10-14 -b 14,50,15,51 -o ./tiles/ --dry-run
npx qgis-plugin --help
npx qgis-plugin new my_plugin --type processing --rust

The 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 SDK

There 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 from crates/qgis-node/

Conda-forge

For conda, install the runtime the addon needs plus QGIS:

Terminal window
conda install -c conda-forge nodejs qgis
npm install qgis-rs

There 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):

OperationRust (NAPI)JS fallbackSpeedup
Extent parse0.5µs5µs10×
TilePlan 10-140.2ms3ms15×