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

node-red-contrib-tdn-sts-gen2

v1.1.1

Published

Node-RED nodes for cloud POS transaction and reporting APIs: PKCE OAuth2 token, closed-check pollers, menu and tender reference tables

Readme

node-red-contrib-tdn-sts-gen2

Node-RED nodes for working with a cloud POS transaction API:

  • sts-oidc-token — authenticates against an OpenID Connect provider using the OAuth2 Authorization Code Flow with PKCE
  • sts-gen2-poller — watches enabled locations and revenue centres for newly closed (paid) checks and emits each one exactly once
  • bi-reference — builds menu item and tender name lookup tables from the reporting API's dimensions endpoints
  • bi-checks-poller — polls the reporting API for closed guest checks, resolving names from those tables

Both pollers emit the same message shape, so one downstream formatter serves either source.

Install

From your Node-RED user directory (typically ~/.node-red):

npm install node-red-contrib-tdn-sts-gen2

Both nodes appear in your palette after install and a restart of Node-RED.

Token node (sts-oidc-token)

The token node performs the full six-step authentication flow on each incoming message:

  1. Generates a PKCE code verifier + SHA-256 challenge
  2. GET /oidc-provider/v1/oauth2/authorize — captures session cookies
  3. Replays the cookies to POST /oidc-provider/v1/oauth2/signin with your API account credentials
  4. Extracts the authorization code from the returned redirectUrl
  5. POST /oidc-provider/v1/oauth2/token with the code + verifier
  6. Caches the token in node context and reuses it until expiry — repeated messages do not re-authenticate while the cached token is valid

Usage

Send a message with a msg.credentials object:

msg.credentials = {
    authHost:     "https://<your-auth-host>",  // OIDC provider host only, no path
    clientId:     "<client-id>",
    username:     "<api-account-username>",
    password:     "<api-account-password>",
    orgShortName: "<org-short-name>"
};
return msg;

All five fields are required; the node reports a specific error and status for any missing field.

On success the message passes through with the token attached:

msg.tokenOut = {
    access_token:  "...",
    id_token:      "...",   // typically used as the Bearer token for API calls
    refresh_token: "...",
    expires_in:    "...",
    token_type:    "Bearer"
}

Use msg.tokenOut.id_token in the Authorization: Bearer header for downstream API requests.

Node status

The node shows its exact state in the editor: validating input, requesting token, cookies stored, token stored, token valid, token expired, or a specific error state.

Poller node (sts-gen2-poller)

The poller node runs its own non-overlapping poll loop (default every 15 s) and queries the checks endpoint once per enabled (location, revenue centre) pair, capped at a configurable number of parallel requests. It emits only closed checks, exactly once each — checks without payment tenders or line items are held back so no partial receipt is ever dispatched downstream.

It is driven entirely from global context:

global.set("cfg", { apiBase: "https://<api-host>/api", orgShortName: "..." });
global.set("locations", [
  { locRef: "loc1", name: "Site 1", enabled: true,
    rvcRefs: [ { rvcRef: 101, name: "Bar", enabled: true } ] }
]);

The work list is rebuilt from locations on every cycle, so enabling or disabling a location or revenue centre takes effect on the next poll without a redeploy.

Token handling: wire the token node's output into the poller's input — any message carrying msg.tokenOut is consumed as a token push. The poller can also fall back to a configurable global context key. On a 401/403 it drops the cached token, emits a token-kind error, and keeps polling with backoff.

Outputs (4): status, closed checks, open checks (off by default), errors. Closed-check messages carry msg.payload (full check), msg.summary (flat record with location/revenue-centre refs, totals, and tenders), and msg.topic = locRef/rvcRef for routing.

Input commands (msg.topic or string payload): poll, start, stop, reset.

Why closed-only polling works: the API's sinceTime filter matches check creation time, so every check created inside the configurable lookback window (default 240 min) reappears in each poll until it ages out. Whenever it closes, the next poll sees the closed status and emits it. Set the lookback longer than the longest-lived open check.

Reporting API nodes (bi-reference, bi-checks-poller)

The reporting API is an alternative source for closed checks. It differs from the transaction API in two ways that matter:

  • its change filter matches modification time, so a check that opens at 09:00 and closes at 10:00 reappears when it closes — no large lookback window is needed
  • its check detail lines carry only numbers (menu item number, tender number), never names

bi-reference solves the second point: it loads menu item and tender name tables per location and stores them in global context, keyed by number, so a lookup is a direct index. Run it once at startup (menus change rarely). The dimensions endpoints return no prices, so the poller computes each unit price from the transaction itself (line total ÷ quantity) and can write those learned prices back into the table.

bi-checks-poller then polls closed guest checks per enabled location, filters to enabled revenue centres, resolves names from the tables, and emits each newly closed check exactly once — normalised to the same msg.summary and msg.payload.menuItems shape as the transaction poller. Because the API requires a business date and venues roll over well after midnight, it queries the last two business dates each cycle by default.

global.set("cfg", {
    biBase: "https://<reporting-host>",
    apiBase: "https://<api-host>/api",
    orgShortName: "..."
});

Notes

  • Credentials should come from context or a secure store — never hard-code them in a flow.
  • Some providers expire API account passwords on a fixed schedule and lock the account temporarily after repeated failed sign-ins — handle credential rotation accordingly.
  • The token is cached per node instance (node context) and re-requested only after expires_in elapses.

License

MIT