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

@danimo-hq/core

v0.2.0

Published

Danimo protocol core: OIDC discovery, PKCE, token exchange, refresh and JWT validation. Runtime-neutral (Web Crypto + fetch).

Readme

@danimo-hq/core

Protocol logic for signing in with Danimo: OIDC discovery, PKCE (S256), code exchange, single-flight refresh, revoke, and access/ID token validation. It uses only Web Crypto and fetch, so it runs in Node, Edge runtimes and React Native.

Most apps use a platform package such as @danimo-hq/next instead of this one.

pnpm add @danimo-hq/core
# npm install @danimo-hq/core

Issuer format: https://danimo.zentovar.space/e/<env_id>. Docs: https://danimo.zentovar.space/docs

import { createDanimoClient } from "@danimo-hq/core";

const danimo = createDanimoClient({
  issuer: "https://danimo.zentovar.space/e/<env_id>",
  clientId: "dnm_cl_...",
  redirectUri: "https://app.example.com/callback",
});

// 1. Start: keep `transaction` safe (sealed cookie, secure storage) and send the user to `url`.
const { url, transaction } = await danimo.createAuthorization({ scopes: ["openid", "profile", "email", "offline_access"] });

// 2. Return: checks state, iss, exchanges the code with PKCE, validates the ID token (iss, aud, nonce, exp).
const { tokens, claims } = await danimo.handleCallback(callbackUrlOrParams, transaction);

// 3. Later: refresh (callers sharing a refresh token share one request), revoke, end the session.
const next = await danimo.refresh(tokens.refreshToken!);
await danimo.revoke(next.refreshToken!, "refresh_token");

The SDK reads every endpoint from the issuer's discovery document and requires its issuer to equal the configured one exactly. It never builds Danimo URLs by hand.

Protecting an API

import { verifyAccessToken } from "@danimo-hq/core";

const claims = await verifyAccessToken(bearerToken, { issuer, audience: "https://api.example.com" });

Checks the signature against the issuer's JWKS (ES256 only), iss, aud, exp and nbf (5 s clock tolerance), and typ: at+jwt. Failures throw a DanimoError whose code is one of token_expired, invalid_audience, invalid_issuer, invalid_signature, unknown_key, token_not_yet_valid or invalid_token. Access tokens are verified offline, so a revoked token is accepted until it expires (at most 10 minutes).

Refresh tokens rotate

Danimo treats a second use of a rotated refresh token as theft and ends the session. refresh() therefore shares one request between concurrent callers and hands a late caller that still holds the old token the same result for 30 seconds. This protects one process. If you run several instances, route refreshes for one user to one place or store tokens centrally.

Token storage

TokenStore is the interface platforms implement (cookies, Keychain, memory); getFreshTokens(store, refresh, ...) refreshes before expiry and clears the store when Danimo rejects the refresh token.

Webhooks

import { verifyWebhook } from "@danimo-hq/core";

// rawBody: the request body exactly as received (a string or bytes), before any JSON parsing.
const { timestamp } = await verifyWebhook(rawBody, request.headers.get("danimo-signature"), process.env.DANIMO_WEBHOOK_SECRET!, { toleranceSeconds: 300 });

Checks Danimo-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")> in constant time, accepts any one of several v1= values (a secret being rolled), and rejects a timestamp more than toleranceSeconds (default 300) from now. It throws invalid_webhook_signature (wrong secret, tampered body or header) or webhook_timestamp_expired (a genuine message that arrived too late, or a clock that is off). It uses Web Crypto HMAC, so it needs a server runtime. Answer the sender with a plain 400 either way, and use the event id to ignore repeats.

For SDK authors

  • createSessionController({ client, store }): the session logic @danimo-hq/react and @danimo-hq/react-native share. It holds the access token in memory, saves the refresh token to a RefreshTokenStore, refreshes single-flight before expiry, restores a session (refresh, then userinfo) and signs out (revoke, clear). State is { status, user, session, error } and never contains a token.
  • client.userInfo(accessToken) calls the discovered userinfo endpoint.
  • verifyIdTokenSignature: false on createDanimoClient skips the ID token signature (never its claims) for runtimes that cannot verify ES256, such as stock Hermes. Use it only for tokens received straight from the token endpoint over TLS.
  • verifyAccessToken accepts a list of audiences for an API that serves several clients.