npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gdal-wasm

v0.0.1

Published

GDAL/OGR compiled to WebAssembly for Node.js and the browser, on the ffi-wasm worker pool.

Readme

clj-gdal

NPM Version Clojars Version

clj-gdal gives GDAL to the JVM and to JavaScript. The Clojars package net.willcohen/gdal has a Clojure API. The npm package gdal-wasm has the same API over a WebAssembly build of GDAL.

clj-gdal is new. A release can still make breaking changes.

net.willcohen/gdal {:mvn/version "0.0.1"}
npm install gdal-wasm

The JVM must be JDK 25 or later, and Node.js must be 22 or later. A Maven profile adds the native library jar of the host: darwin-aarch64, linux-amd64 or linux-aarch64 of net.willcohen/gdal-native. Gradle does not read the profile, and an uberjar gets only the jar of the host that builds it: add each jar yourself, for example net.willcohen:gdal-native:0.0.1:linux-amd64.

Usage

Clojure

(require '[net.willcohen.gdal.gdal :as gdal]
         '[net.willcohen.gdal.fndefs :as fndefs])

(gdal/init!)

(let [ds    (gdal/gdal-open-ex "example.gpkg" fndefs/GDAL_OF_VECTOR nil nil nil)
      layer (gdal/gdal-dataset-get-layer ds 0)]
  (println (gdal/layer-feature-count layer))
  (println (map :fields (gdal/read-vector-features! layer)))
  (gdal/gdal-close ds))

Add --enable-native-access=ALL-UNNAMED to the JVM options.

JavaScript

import * as gdal from 'gdal-wasm';
import { GDAL_OF_VECTOR } from 'gdal-wasm/fndefs';

await gdal.init();
const ds = await gdal.open_from_disk_BANG_('example.gpkg', GDAL_OF_VECTOR);
const layer = await gdal.gdal_dataset_get_layer(ds, 0);
console.log(Number(await gdal.layer_feature_count(layer)));
const records = await gdal.read_vector_features_BANG_(layer);
await gdal.gdal_close(ds);
await gdal.shutdown(); // The worker pool keeps Node.js alive until this call.

In a browser, copy the bytes into the worker, and open the staged path:

import { loadBytesFromBlob } from 'gdal-wasm/gdal-loader';

const { files, name } = await loadBytesFromBlob(file);
const staged = await gdal.stage_files_BANG_(files);
const ds = await gdal.gdal_open_ex(staged[name], GDAL_OF_VECTOR, null, null, null);

loadShapeFamilyFromFiles reads a shapefile and its sidecar files. loadDirectoryFromFiles reads a File Geodatabase: stage its files in a directory with the name of the dataset, for example /work/x.gdb.

A page needs no COOP or COEP headers. A page without a bundler maps each dependency in an import map, and a server on a different origin must send CORS headers:

<script type="importmap">
{
  "imports": {
    "gdal-wasm": "https://cdn.jsdelivr.net/npm/[email protected]/gdal.mjs",
    "gdal-wasm/fndefs": "https://cdn.jsdelivr.net/npm/[email protected]/fndefs.mjs",
    "gdal-wasm/gdal-loader": "https://cdn.jsdelivr.net/npm/[email protected]/gdal-loader.mjs",
    "ffi-wasm": "https://cdn.jsdelivr.net/npm/[email protected]/dist/ffi-wasm.mjs",
    "ffi-wasm/handler-env": "https://cdn.jsdelivr.net/npm/[email protected]/dist/handler_env.mjs",
    "worker-router": "https://cdn.jsdelivr.net/npm/@wcohen/[email protected]/dist/index.mjs",
    "worker-router/worker-bootstrap": "https://cdn.jsdelivr.net/npm/@wcohen/[email protected]/dist/worker-bootstrap.mjs",
    "comlink": "https://cdn.jsdelivr.net/npm/[email protected]/dist/esm/comlink.mjs",
    "resource-tracker": "https://cdn.jsdelivr.net/npm/[email protected]/resource.mjs",
    "squint-cljs/": "https://cdn.jsdelivr.net/npm/[email protected]/"
  }
}
</script>

API

Each C function in net.willcohen.gdal.fndefs has a function with a kebab-case name: GDALOpenEx is gdal-open-ex. Most functions that take a buffer have a helper in their place. Each helper has a docstring:

  • Features: read-vector-features!, layer-feature-count, layer-extent, field-date-time, field-binary, set-field-binary!
  • Geometries: geometry-from-wkb, geometry-from-wkt, geometry->wkb, geometry->iso-wkb, geometry->wkt, geometry->json, feature->wkb, feature->iso-wkb, transform-points, srs-export-to-wkt, srs-export-to-projjson
  • Rasters: read-raster-band, write-raster-band!, get-geo-transform, set-geo-transform!, band-nodata, band-block-size, build-overviews!
  • Apps: translate-vector!, translate-raster!, warp-raster!, raster-info, vector-info
  • Other: metadata, file-list, build-csl-options, stage-files!, read-vsimem-file, read-vsi-dir, force-graal! and graal? (JVM), handler-spec (JavaScript), open-from-disk! (Node.js)

Some buffer functions, for example the OGR list fields, have no helper yet. Close each dataset with gdal-close. When GDAL fails, a helper throws an ex-info with the GDAL error message.

In JavaScript, each function returns a Promise, and its name is the squint name, for example geometry__GT_wkb. A 64-bit integer is a BigInt. Read the data of an error with the ex_data of the squint-cljs of gdal-wasm. To share a worker pool with proj-wasm, register the spec of handler_spec() with ffi.register_handler_BANG_(registry, 'compute', 'net.willcohen.gdal', spec), and give the pool to init as pool. shutdown() does not stop that pool.

Files and HTTP

On FFI, GDAL opens host paths. On GraalVM, an open copies the host file and its sidecar files into MEMFS below /host, and gdal-close copies a written dataset back. In JavaScript, GDAL opens MEMFS and /vsimem paths only.

The GeoJSON, ESRIJSON and TopoJSON drivers read HTTP URLs. Set GDAL_HTTP_HEADERS to add a header. On the JVM, bind net.willcohen.gdal.network/*transport* to change a request.

Platforms

The JVM uses a native libgdal on macOS arm64 and on Linux amd64 and arm64 (glibc 2.28 or later, or musl), and libgdal.wasm on GraalVM on each other platform. JavaScript runs libgdal.wasm in a worker. Each has GDAL 3.11.5, PROJ 9.9.0 and 18 drivers: VRT, GTiff, COG, PNG, JPEG, MEM, GNMFile, GNMDatabase, ESRI Shapefile, GML, GeoJSON, GeoJSONSeq, ESRIJSON, TopoJSON, GPKG, SQLite, OpenFileGDB and FlatGeobuf. On a JDK other than GraalVM 25.3.4.1, the wasm module runs in an interpreter, more slowly.

Known limitations

  • No GEOS, no libcurl (/vsicurl/), no XML parser (GML is write only) and no GDAL data files.
  • On GraalVM, GDAL sees only the dataset file and its sidecar files. A VRT cannot read its sources, and a host file in a /vsizip/ path or after a driver prefix does not open. A read-only close drops a new .ovr or .aux.xml.
  • On Node.js, an HTTP response over 50 MiB or 35 s fails.

License

clj-gdal is under the MIT License. Refer to LICENSE. The binaries contain code and data from other projects, for example GDAL, PROJ, SQLite and the EPSG dataset of IOGP, and no LGPL or GPL library apart from small glibc wrappers with a link exception. Refer to THIRD-PARTY-NOTICES.

This software is based in part on the work of the Independent JPEG Group.