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

@gb-transit/gtfs

v3.7.0

Published

GTFS entities, the GB rail transit model, the schedule transforms and the feed build

Readme

@gb-transit/gtfs

GTFS entities, the GB rail transit model, the schedule transforms and the feed build.

npm install @gb-transit/gtfs

This is the core of the GB rail GTFS toolchain: the shape of every output file, the domain objects the DTD timetable becomes, the transforms that turn one into the other, and the orchestrator that runs a build. It has no IO dependencies — where the schedules come from and where the feed is written are both interfaces.

A consumer building GTFS from something other than this project's MySQL schema needs this package, not the dtd2mysql CLI.

Building a feed

import {BuildFeed, buildContext, dateRange, stationCoordinates} from "@gb-transit/gtfs";
import {CifFileSource, timetableFeeds} from "@gb-transit/dtd-source";
import {FileOutput} from "@gb-transit/gtfs-output";

const context = buildContext(process.argv, process.env);

const feed = new BuildFeed(
  new CifFileSource(timetableFeeds(["./feeds"]), stationCoordinates, dateRange(context)),
  new FileOutput(),
  context
);

await feed.build("./gtfs");

buildContext settles the date the feed is built for and how far ahead it runs, from flags (--today, --range) or the environment (GTFS_TODAY, GTFS_RANGE). Pinning today is what makes a build reproducible: without it the feed is a function of the day it ran and cannot be compared to yesterday's.

What is in it

Entities — a type per output file: Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, Transfer, FixedLink, Area, StopArea, Attribution and FeedInfo, each with its *Row form as written to text.

The transit model — Schedule, ScheduleCalendar, Association and the date and duration helpers. Pure domain objects, no IO.

Transforms — the operations that make a publishable feed out of DTD records: applyOverlays for short-term plan overlays, applyAssociations and linkedTrips for splits and joins, mergeSchedules, createCalendar, mergeTransfers, withStopPoints for platforms, and the identifier schemes in stopId, stationId, agencyId and toRouteRow.

The build — BuildFeed, BuildContext, ScheduleBuilder and buildReport.

The two extension points

A source supplies the timetable:

interface TimetableSource {
  getStops(): Promise<Stop[]>;
  getSchedules(): Promise<ScheduleResults>;
  getAssociations(): Promise<Association[]>;
  getTransfers(): Promise<Transfer[]>;
  getFixedLinks(): Promise<FixedLink[]>;
  getFeedVersion(): Promise<string | null>;
  end(): Promise<any>;
}

An enricher adds detail the DTD does not carry:

interface Enricher<T = unknown> {
  readonly key: string;
  readonly dependsOn: readonly string[];
  readonly priority: number;
  readonly attribution?: Attribution;
  fetch(): Promise<T>;
  apply(feed: MutableFeed, data: T): EnrichmentReport;
}

fetch is separated from apply so the network happens once, up front; dependsOn orders the enrichers, because one cannot join platforms that another has not created yet.

Enrichment records provenance rather than overwriting. Every write carries the enricher that made it and its priority; the higher priority wins and the loser is kept, so a field can always be traced to the source that set it. EnrichmentReport — matched, unmatched and conflict counts — is a first-class output rather than a log line, because it is the best signal that an upstream source has changed under you. @gb-transit/enrich-naptan and @gb-transit/enrich-knowledgebase-stations are the implementations.

An Extension is the other seam: whole files the core build has no concept of, such as the Fares v2 areas.txt written by @gb-transit/extend-station-groups.

Licence composition

The sources a feed can be built from carry different terms — the DTD is under RSP terms, NaPTAN and CORPUS are OGL, OpenStreetMap is ODbL and share-alike. BuildConfig takes a licence tier and a build that would mix a share-alike source into an OGL feed fails rather than producing output whose terms nobody can state.

Requirements

Node.js 22 or later. Date handling uses Temporal, through temporal-polyfill, which hands over to the built-in global on the versions that have one - Node 26 and later.

Contributing

Issues, pull requests and the source live at planarnetwork/gb-transit. This is libs/gtfs in that repository.

License

This software is licensed under GNU GPLv3.

Copyright 2017 Linus Norton.