Package Exports
- gtfs-sqljs
- gtfs-sqljs/adapters/better-sqlite3
- gtfs-sqljs/adapters/sql-js
Readme
gtfs-sqljs
A TypeScript library for loading GTFS (General Transit Feed Specification) data into a SQLite database for querying in browser, Node.js, and React Native environments. Ships with adapters for sql.js (browser / Node WASM) and better-sqlite3 (Node native); bring your own for op-sqlite, expo-sqlite, etc.
Live Demo — A fully static demo website with GTFS and GTFS-RT data running in a Web Worker, with no backend.
Author
Théophile Helleboid / SysDevRun
- Email: contact@sys-dev-run.fr
- Website: https://www.sys-dev-run.fr/
This project is greatly inspired by node-gtfs, also MIT licensed. The main difference is that gtfs-sqljs aims to run on both browser and Node.js environments.
Documentation & Demo
- Documentation and Interactive Demo
- Usage Guide — detailed examples for all features
- API Reference — full TypeDoc-generated API docs
- LLM Skill File — Claude Code skill for LLM code agents
Features
GTFS Static Data
- Load GTFS data from ZIP files (URL or
ArrayBuffer) or existing SQLite databases - Pluggable database adapter — sql.js, better-sqlite3 (built-in), or your own for op-sqlite / expo-sqlite
- Attach to a pre-opened database — ideal for file-backed native drivers where the caller controls the file path, readonly flag, etc.
- High-performance loading with optimized bulk inserts
- Progress tracking - Real-time progress callbacks (0-100%)
- Skip importing specific files (e.g., shapes.txt) to reduce memory usage
- Export databases to
ArrayBufferfor persistence (sql.js / in-memory better-sqlite3) - Flexible filter-based query API - combine multiple filters easily
- Full TypeScript support with comprehensive types
- Works in browser, Node.js, and React Native
GTFS Realtime Support
- Load GTFS-RT data from protobuf feeds (URLs or local files)
- Support for Alerts, Trip Updates, and Vehicle Positions
- Automatic staleness filtering (configurable threshold)
- Merge realtime data with static schedules
Smart Caching
- Optional caching - Copy cache implementations from
examples/cache/ - Platform-specific stores - IndexedDBCacheStore (browser) or FileSystemCacheStore (Node.js)
- Smart invalidation - Based on file checksum, size, version, and library version
- Dramatic speed improvement - Subsequent loads in <1 second
Installation
npm install gtfs-sqljsInstall the adapter(s) you want as peer dependencies. Install one or both depending on where the library runs:
# Browser or Node (WASM-backed, in-memory)
npm install sql.js
# Node (native, can be file-backed)
npm install better-sqlite3Note (v0.6 breaking change): the core library no longer hard-depends on sql.js. You must pass an adapter to
fromZip/fromZipData/fromDatabase, or hand a pre-opened handle toGtfsSqlJs.attach(). All query methods are nowasyncand returnPromise<T>.
Quick Start
sql.js (browser / Node WASM)
import { GtfsSqlJs } from 'gtfs-sqljs';
import { createSqlJsAdapter } from 'gtfs-sqljs/adapters/sql-js';
// Load GTFS data from a ZIP URL
const gtfs = await GtfsSqlJs.fromZip('https://example.com/gtfs.zip', {
adapter: await createSqlJsAdapter(),
});
// Query routes
const routes = await gtfs.getRoutes();
// Query stops with filters
const stops = await gtfs.getStops({ name: 'Central Station' });
// Get trips for a route on a specific date
const trips = await gtfs.getTrips({
routeId: 'ROUTE_1',
date: '20240115',
directionId: 0,
});
// Get stop times for a trip
const stopTimes = await gtfs.getStopTimes({ tripId: trips[0].trip_id });
// Clean up
await gtfs.close();better-sqlite3 (Node native)
import BetterSqlite3 from 'better-sqlite3';
import { GtfsSqlJs } from 'gtfs-sqljs';
import { wrapBetterSqlite3 } from 'gtfs-sqljs/adapters/better-sqlite3';
// Open a file-backed DB yourself, then attach.
const raw = new BetterSqlite3('./gtfs.db');
const gtfs = await GtfsSqlJs.attach(wrapBetterSqlite3(raw));
const routes = await gtfs.getRoutes();
// `attach()` does not own the handle by default — you close both.
await gtfs.close();
raw.close();See the Usage Guide for detailed examples covering fromDatabase, fromZipData, GTFS-RT, and caching.
Adapters
gtfs-sqljs talks to a narrow async GtfsDatabase interface (prepare, run, export, close). Pick the adapter that matches your runtime:
| Adapter | Subpath | Typical use |
|---|---|---|
| sql.js | gtfs-sqljs/adapters/sql-js |
Browser; Node without native deps; always in-memory |
| better-sqlite3 | gtfs-sqljs/adapters/better-sqlite3 |
Node; file-backed persistence; fastest native performance |
| op-sqlite | (user-provided — see Usage Guide) | React Native (JSI) |
| expo-sqlite | (user-provided — see Usage Guide) | Expo / React Native |
Two entry points cover every scenario:
- Factory path —
fromZip/fromZipData/fromDatabasetakeoptions.adapter: GtfsDatabaseAdapter. The library creates / opens the DB for you. Best for in-memory drivers (sql.js, in-memory better-sqlite3). - Pre-opened handle —
GtfsSqlJs.attach(db, options?)takes a liveGtfsDatabaseyou already built. Best for file-backed drivers where the caller owns the file path, journal mode, etc.
API Reference
Full API documentation: API Reference
All GtfsSqlJs instance methods return Promise<T> — use await.
Static Methods
GtfsSqlJs.fromZip(zipPath, options)— Create instance from a GTFS ZIP URL.options.adapteris required.GtfsSqlJs.fromZipData(zipData, options)— Create instance from pre-loaded ZIP bytes (ArrayBufferorUint8Array).options.adapteris required.GtfsSqlJs.fromDatabase(database, options)— Create instance from existing SQLite bytes (ArrayBuffer).options.adapteris required.GtfsSqlJs.attach(db, options?)— Attach to a pre-openedGtfsDatabasehandle. Noadapterneeded (the handle is the adapter output). PassskipSchema: truewhen the attached DB already has the GTFS schema; passownsDatabase: trueto haveclose()release the underlying handle.
Instance Methods
GTFS Static Data Methods
All methods support flexible filtering with both single values and arrays:
getAgencies(filters?)- Get agencies (filters: agencyId, limit)getStops(filters?)- Get stops (filters: stopId, stopCode, name, tripId, limit)getRoutes(filters?)- Get routes (filters: routeId, agencyId, limit)getTrips(filters?)- Get trips (filters: tripId, routeId, serviceIds, directionId, agencyId, includeRealtime, limit, date)getStopTimes(filters?)- Get stop times (filters: tripId, stopId, routeId, serviceIds, directionId, agencyId, includeRealtime, limit, date)getShapes(filters?)- Get shape points (filters: shapeId, routeId, tripId, limit)getShapesToGeojson(filters?, precision?)- Get shapes as GeoJSON FeatureCollection (same filters, precision default: 6)buildOrderedStopList(tripIds)- Build an ordered list of stops from multiple trips (handles express/local variations)
Calendar Methods
getActiveServiceIds(date)- Get active service IDs for a date (YYYYMMDD format)getCalendars(filters?)- Get calendars (filters: serviceId, limit)getCalendarDates(serviceId)- Get calendar date exceptions for a servicegetCalendarDatesForDate(date)- Get calendar exceptions for a specific date
GTFS Realtime Methods
fetchRealtimeData(urls?)- Fetch and load RT data from protobuf feedsclearRealtimeData()- Clear all realtime data from databasesetRealtimeFeedUrls(urls)- Configure RT feed URLsgetRealtimeFeedUrls()- Get configured RT feed URLssetStalenessThreshold(seconds)- Set staleness threshold (default: 120 seconds)getStalenessThreshold()- Get current staleness thresholdgetLastRealtimeFetchTimestamp()- Get Unix timestamp (seconds) of last successful RT fetch, or null if never fetchedgetAlerts(filters?)- Get alerts (filters: alertId, routeId, stopId, tripId, activeOnly, cause, effect, limit)getVehiclePositions(filters?)- Get vehicle positions (filters: tripId, routeId, vehicleId, limit)getTripUpdates(filters?)- Get trip updates (filters: tripId, routeId, limit)getStopTimeUpdates(filters?)- Get stop time updates (filters: tripId, stopId, stopSequence, limit)
Database Methods
export()- Export database to ArrayBuffer (includes RT data)getDatabase()- Get direct access to sql.js database for advanced queriesclose()- Close database connection
Debug Methods
debugExportAllAlerts()- Export all alerts without staleness filteringdebugExportAllVehiclePositions()- Export all vehicle positions without staleness filteringdebugExportAllTripUpdates()- Export all trip updates without staleness filteringdebugExportAllStopTimeUpdates()- Export all stop time updates without staleness filtering
TypeScript Support
This library is written in TypeScript and provides full type definitions for all GTFS entities, filter options, GTFS-RT types, and progress tracking:
import type {
// Adapter surface
GtfsDatabase, GtfsDatabaseAdapter, GtfsStatement, Row, SqlValue,
// Static GTFS types
Stop, Route, Trip, StopTime, Shape,
TripFilters, StopTimeFilters, ShapeFilters,
// GeoJSON types
GeoJsonFeatureCollection,
// GTFS-RT types
Alert, VehiclePosition, TripWithRealtime, StopTimeWithRealtime,
AlertFilters, VehiclePositionFilters,
// GTFS-RT enums
AlertCause, AlertEffect, ScheduleRelationship,
// Progress tracking types
ProgressInfo, ProgressCallback
} from 'gtfs-sqljs';
import { ExportNotSupportedError } from 'gtfs-sqljs';GTFS Specification
This library implements:
- GTFS Schedule Reference with proper handling of required and optional fields
- GTFS Realtime Reference v2.0 with support for Alerts, Trip Updates, and Vehicle Positions
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Issues
If you encounter any problems or have suggestions, please open an issue.