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

meos.js

v1.0.2

Published

JavaScript/TypeScript bindings for MobilityDB MEOS via WebAssembly

Downloads

200

Readme

MEOS.js

npm version docs WebAssembly Memory64

TypeScript/JavaScript bindings for MEOS, the C library that powers MobilityDB spatiotemporal types.

MEOS is compiled to WebAssembly (wasm64/MEMORY64) via Emscripten. MEOS.js wraps the resulting .wasm module in a typed TypeScript API so you can work with temporal values, spans, sets, and bounding boxes in Node.js or the browser.

npm install meos.js

Documentation · Examples · MobilityDB

Requires a runtime with WebAssembly MEMORY64 (Node.js 22+, or a recent browser).

Table of contents

Requirements

  • Docker: only needed to build the WASM module from source. Not needed if you use the prebuilt files.

  • A JS engine with WebAssembly MEMORY64 support: needed to run MEOS.js, because meos.wasm is compiled with -sMEMORY64=1. In practice:

    • server-side: Node.js 22+
    • browser-side: recent Chromium-based browsers or Firefox with the MEMORY64 proposal enabled

    initMeos() probes for MEMORY64 at startup and throws a clear error if the engine doesn't support it.

Node.js 22+ is additionally required to run the tests, the code generator, the TypeScript build and the docs. Not needed for the WASM build itself.

Project Structure

MEOS.js/
├── codegen/                         ← Code generator
│   ├── res/
│   │   ├── meos-idl.json            ← MEOS API description
│   │   ├── meos.h, meos_geo.h       ← Cached upstream headers
│   │   ├── bindings_c_header.c.template
│   │   └── functions_ts_header.ts.template
│   └── FunctionsGenerator.ts        ← Eemits the C glue + TS bindings
├── core/
│   ├── c-src/
│   │   └── bindings.c               ← Generated C glue
│   ├── functions/
│   │   ├── functions.generated.ts   ← Generated TS bindings
│   │   ├── errors.ts                ← MEOS error code handling
│   │   └── ptr_array.ts             ← Pointer-array marshalling helpers
│   ├── runtime/
│   │   └── meos.ts                  ← WASM module loader
│   ├── types/                       ← High-level typed wrappers
│   │   ├── basic/                   ← TBool, TInt, TFloat, TText...
│   │   ├── boxes/                   ← TBox, STBox
│   │   ├── collections/             ← Span, SpanSet, MeoSet...
│   │   └── temporal/                ← Temporal base class + factory
│   └── index.ts                     ← Public exports
├── wasm/                            ← Build output (meos.js, meos.wasm)
├── test/                            ← Unit tests (node:test + tsx)
├── docs/                            ← TypeDoc + VitePress sources & HTML
├── Dockerfile                       ← Multi-stage build: MEOS → WASM
└── package.json

The two-layer architecture consists of:

  • codegen/: reads codegen/res/meos-idl.json and generates core/c-src/bindings.c and core/functions/functions.generated.ts.
  • core/: implements the high-level typed wrappers on top of the generated bindings, plus the runtime that loads the WASM module.

Installation

Use meos.js in your project

npm install meos.js

The published package bundles the compiled WASM module, so you need neither Docker nor a source checkout. The optional deck.gl integration is available under meos.js/deckgl (see DeckGL integration).

Requires a runtime with WebAssembly MEMORY64 (Node.js 22+, or a recent browser). See Requirements.

Develop MEOS.js from source

Only needed to work on MEOS.js itself.

1. Get the WASM module

docker build --output type=local,dest=./wasm --target wasm .

This produces wasm/meos.js and wasm/meos.wasm. The first build may take a while as it compiles GEOS, PROJ, SQLite, GSL, JSON-C, and MobilityDB from source.

2. Install dependencies

npm install

3. Run the tests

npm test

Using from JavaScript

MEOS.js is written in TypeScript for maintainability but ships as plain JavaScript (ES2022 / ESM) with bundled type declarations. You can use it from any JavaScript project without TypeScript in your toolchain.

npm run build:ts emits dist/core/*.js (the runtime) plus dist/core/*.d.ts (the types). From a plain JS file:

import { initMeos, TsTzSpan } from 'meos.js';

await initMeos();
const span = TsTzSpan.fromString('[2020-01-01, 2021-01-01)');
console.log(span.toString());
span.free();

Everything works identically: every class (TBool, TInt, TFloat, TGeomPoint, ...), the factory functions, the using / [Symbol.dispose] lifecycle (ES2023, not TS-specific). The bundled .d.ts files also give you IDE autocompletion and hover-docs in .js files.

The only thing TypeScript users get extra is compile-time type checking at write-time; the runtime surface is the same.

Code Generation

The codegen/ directory contains the generator that produces core/c-src/bindings.c and core/functions/functions.generated.ts from the MEOS API description file (codegen/res/meos-idl.json).

When to regenerate: whenever meos-idl.json is updated (e.g. after a MEOS version upgrade) or whenever FunctionsGenerator.ts / the templates change.

Running the generator

npm run generate

This reads codegen/res/meos-idl.json, applies the templates in codegen/res/, and overwrites both generated files.

Do not edit bindings.c or functions.generated.ts manually: any change will be lost the next time the generator runs. Manual overrides live in the templates (codegen/res/*_header.*.template).

Updating the input file

The canonical meos-idl.json is produced by MEOS-API. To refresh against a newer MEOS surface:

# in a MEOS-API checkout
python setup.py
python run.py
cp output/meos-idl.json /path/to/MEOS.js/codegen/res/meos-idl.json
# back in MEOS.js
npm run generate

Bump the MOBILITYDB_COMMIT pin in the Dockerfile together with the IDL refresh so the WASM build stays in sync with the bindings.

Tests

Unit tests live in test/ and use Node's built-in test runner with tsx for on-the-fly TypeScript transpilation.

Run all tests

npm test

Run a specific test file

node --import tsx/esm --test test/types/boxes/test_TBox.ts

Run a specific test by name

node --import tsx/esm --test --test-name-pattern="fromString" test/types/boxes/test_TBox.ts

Doc

The API reference is generated by TypeDoc and served by VitePress. The published site lives at https://mobilitydb.github.io/MEOS.js/ and is rebuilt by .github/workflows/docs.yml on every push to main.

Build the API reference only

npm run docs:api

This invokes TypeDoc with the config in typedoc.json and writes Markdown pages to docs/api/.

Run the docs site locally (with hot reload)

npm run docs:dev

Build the static docs site

npm run docs:build

The output is placed under docs/.vitepress/dist/, which is what the GitHub Pages workflow deploys.

Preview the built site

npm run docs:preview

Memory management

Every MEOS.js object wraps a raw pointer allocated in WASM memory. This memory is not managed by the JavaScript garbage collector and must be freed explicitly.

Option 1: manual free()

const span = TsTzSpan.fromString('[2020-01-01, 2021-01-01)');
// ... use span ...
span.free();

Option 2: using

All types implement [Symbol.dispose](), so you can use the Explicit Resource Management syntax. The object is freed automatically when the block exits, even if an exception is thrown.

{
    using span = TsTzSpan.fromString('[2020-01-01, 2021-01-01)');
    console.log(span.toString());
} // span.free() called automatically here

using requires TypeScript 5.2+ with "lib": ["ES2022"] or "ESNext" in tsconfig.json.

DeckGL integration

MEOS.js ships an optional, framework-free adapter for rendering temporal points with deck.gl's TripsLayer. It lives in two sub-exports so the core library never depends on deck.gl or React:

| Import | Depends on | Contents | |---|---|---| | meos.js/deckgl | nothing (only MEOS.js) | adapter + browser-side temporal helpers | | meos.js/deckgl/layer | @deck.gl/* (peer) | ready-to-use TripsLayer factory |

@deck.gl/core and @deck.gl/geo-layers are declared as optional peer dependencies: installing meos.js does not pull them in. Install them yourself when you use meos.js/deckgl/layer.

Adapter

tgeompointsToTrips converts temporal points into the { path, timestamps } shape TripsLayer expects, placing every trip on a single shared animation clock:

import { initMeos, TGeomPoint } from 'meos.js';
import { tgeompointsToTrips } from 'meos.js/deckgl';

await initMeos();
const trajectories = [/* TGeomPoint, … */];
const { trips, timeOrigin, timeRange } = tgeompointsToTrips(trajectories);
// trips: { path: [lng, lat][]; timestamps: number[] }[]

A trajectory with temporal gaps (a sequence set) maps to several paths.

Browser-side temporal logic

The same sub-export wraps common MobilityDB operations so the temporal work runs in the browser instead of on a server:

import { atGeometry, atTime, tripsWithSpeed } from 'meos.js/deckgl';

atGeometry(t, 'POLYGON((…))');                            // clip to a zone   (tpoint_at_geom)
atTime(t, '[2024-01-15 09:00+00, 2024-01-15 09:10+00]');  // clip to a period (temporal_at_tstzspan)
tripsWithSpeed(t);                                        // trips + per-vertex speed (tpoint_speed)

Ready-to-use layer

import { tripsLayerFromTGeompoints } from 'meos.js/deckgl/layer';

const layer = tripsLayerFromTGeompoints(trajectories, {
    currentTime,
    trailLength: 180,
    widthMinPixels: 4,
});

The layer renders standalone or interleaved over a MapLibre basemap, so it can sit on top of an existing map.

See the DeckGL guide for the full API.

Use Case Examples

A complete, animated end-to-end demo (MEOS.js → adapter → TripsLayer interleaved over MapLibre, with in-browser zone/time/speed controls) lives in the MEOS.js-examples repository.