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

@uk-energy/neso

v0.1.1

Published

Typed client for the NESO Data Portal (CKAN): datastore search and SQL, thermal constraint costs, constraint breakdown and forecasts, day-ahead boundary flows, Demand Flexibility Service, daily balancing costs. Part of uk-energy-sdk.

Readme

@uk-energy/neso

Typed client for the NESO Data Portal: transmission constraint costs and forecasts, day-ahead boundary flows, Demand Flexibility Service and daily balancing costs, plus the raw CKAN datastore and SQL endpoints for the other ~800 datasets. No API key.

Supported by National Energy SO Open Data. Keep this line wherever you show the data: it is the attribution the NESO Open Data Licence v1.0 (OGL v3-based; commercial use and redistribution allowed) requires.

Python mirror: uk_energy.neso in the uk-energy distribution.

pnpm add @uk-energy/neso

Usage

import { NesoClient } from "@uk-energy/neso";

const neso = new NesoClient();

// Thermal constraint cost per boundary per day (£) — SCOTEX, SSHARN, SEIMP are the Scottish export boundaries
const costs = await neso.constraints.thermalCosts("2025-04-01", "2025-04-30");
const scotex = costs.filter((r) => r["Constraint Group"] === "SCOTEX").reduce((s, r) => s + r["Daily Cost (GBP)"], 0);

// Daily constraint cost and volume by type (thermal, voltage, inertia, largest loss)
const breakdown = await neso.constraints.breakdown("2025-04-01", "2025-04-30");

// NESO's forward view: £m per month for 24 months, and MW limits per boundary per week
const forecast = await neso.constraints.forecast24m();
const limits = await neso.constraints.limits24m();

// Day-ahead forecast flow vs limit, half-hourly, per boundary (filterable)
const flows = await neso.constraints.dayAheadFlows("2026-10-15", "2026-10-15", "SCOTEX");

// Demand Flexibility Service: requirements, bids per unit, and per-event summary
const dfs = await neso.dfs.summary("2026-10-20", "2026-10-22");

// Anything else on the portal: CKAN datastore paging or read-only SQL over a resource
const pkg = await neso.ckan.packageShow("interconnector-register");
const rows = await neso.ckan.datastoreAll(pkg.resources[0].id);
const top = await neso.ckan.sql(`SELECT * FROM "407f3e9d-5c38-4a64-98f5-923dc4d64fb2" WHERE "Daily Cost (GBP)" > 1000000 ORDER BY "Daily Cost (GBP)" DESC LIMIT 10`);

Rows keep the portal's own column names, spaces and all (r["Daily Cost (GBP)"]), so they match the CSV downloads and the SQL endpoint. Every method is async; CKAN's { success: false } throws UkEnergyError, HTTP errors throw HttpError with the CKAN error object in body (404 for an unknown resource, 409 for bad SQL).

Surface

| Namespace | Methods | | --- | --- | | ckan | packageShow(id), packageSearch(q, rows), resourceShow(id), datastoreSearch(resourceId, { limit, offset, sort, filters, fields, q }), datastoreAll(resourceId, opts), sql(query, extraNumeric?) | | resources | datastore(packageId), forFinancialYear(packageId, 2025), byName(packageId, name \| RegExp) | | constraints | thermalCosts(from, to, group?), breakdown(from, to), forecast24m(), limits24m(), dayAheadFlows(from, to, group?), dailyBalancingCosts(from, to) | | dfs | requirements(from, to), utilisation(from, to), summary(from, to) |

action(name, query) runs any other CKAN action. rangeSql, ident, literal and normaliseRows are exported for building your own queries; PACKAGES lists the dataset names the helpers use.

Things to know about the portal

  • One resource per financial year. Thermal costs, the breakdown and daily balancing costs are split into resources named like "Thermal Constraint Costs Data 25-26" (April–March). The date-range helpers resolve the right resource(s), spanning years when needed; the pre-2021 thermal cost resources are XLSX and not in the datastore.
  • SQL returns numerics as strings ("252") while datastore_search returns numbers. Both paths are normalised using the column types in fields; the _full_text search column is dropped. "Thermal constraints cost" in the breakdown is typed text in some years and is coerced too.
  • Local dates. Settlement and delivery dates are GB calendar days and Date_ Time GMT_BST in the day-ahead flows is GB local time with no offset. The helpers take "YYYY-MM-DD" strings as given and read Date inputs as Europe/London calendar days.
  • A range reaching into a year NESO hasn't published yet (1 April before the new "26-27" resource appears) throws rather than returning the rows that do exist; narrow to.
  • Page size. datastore_search returns everything up to 32,000 rows per request; the day-ahead flows table is ~750k rows, so always filter it (the helper does, via SQL).
  • Rate limits. None published; the licence only reserves the right to throttle excessive use. Default 5 rps / burst 10 per host; package metadata is memoised for 10 minutes.
  • Dataset names can change when NESO reorganises the portal; PACKAGES is one place to fix.

Options

new NesoClient({
  rateLimit: { requestsPerSecond: 5, burst: 10 }, // default
  cache: new MemoryCache(),                        // optional response cache; TTL defaults to 10 minutes
  cacheTtlMs: 10 * 60 * 1000,                      // also the package metadata memo TTL
  retry: { retries: 3 }, timeoutMs: 30_000, fetch, // forwarded to @uk-energy/core HttpClient
});