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

@typeb-digital/nucleus-client

v0.0.6

Published

Browser/cross-platform client SDK for Nucleus — auth, session management, and more

Readme

@typeb-digital/nucleus-client

Browser / cross-platform auth SDK for the Nucleus data platform.

Handles the OIDC sign-in flow, silent token refresh, and session management. Modelled on the Auth0 SPA SDK — if you've used that, this will feel familiar.

This package is auth only. It never calls data endpoints. All data access goes through your app's own backend via @typeb-digital/nucleus-sdk.


Installation

npm install @typeb-digital/nucleus-client
# or
yarn add @typeb-digital/nucleus-client

Works in browsers, React Native, and any environment with the Web Crypto API (Node.js 18+, all modern browsers).


Quick start

import { NucleusClient } from '@typeb-digital/nucleus-client';

export const nucleus = new NucleusClient({
  appId: 'app_xxxxxxxxxxxx', // public identifier — safe to include in frontend code
});

Get your appId from the Nucleus dashboard → Apps → your app.


Auth flow

Nucleus uses Authorization Code + PKCE — the same flow as Auth0's SPA SDK.

// 1. Start sign-in — redirects to Nucleus auth
await nucleus.auth.signIn();

// 2. On your redirect route (e.g. /console/auth/callback):
await nucleus.auth.handleRedirectCallback();

// 3. Get a valid access token anywhere in your app
//    Refreshes silently and transparently when expired
const token = await nucleus.auth.getAccessToken();

// 4. Forward the token to your own backend alongside its API calls
// Your backend uses the app token for data access + this token for user context

For the backend side of this — how your backend receives the token, validates it, and uses the server SDK to read Nucleus data — see the dual-token architecture section in the server SDK README.


API reference

nucleus.auth.signIn(options?)

Redirects the user to Nucleus for authentication. Generates a PKCE challenge internally.

await nucleus.auth.signIn();

// Custom redirect URI (if your app has multiple callback routes)
await nucleus.auth.signIn({ redirectUri: 'https://myapp.com/auth/callback' });

// Mobile / non-browser: supply your own redirect handler
await nucleus.auth.signIn({
  onRedirect: async (url) => {
    // e.g. open an in-app browser
    await Linking.openURL(url);
  },
});

nucleus.auth.handleRedirectCallback(url?)

Call this on your redirect route after Nucleus sends the user back. Reads the authorization code from the URL, exchanges it for tokens, and establishes the session.

// In your /auth/callback route component
await nucleus.auth.handleRedirectCallback();
// User is now signed in

Pass url explicitly when the current URL isn't available from window.location (React Native, SSR):

await nucleus.auth.handleRedirectCallback(incomingUrl);

nucleus.auth.getAccessToken()

Returns a valid access token. Refreshes silently using the rotating refresh token if the current token has expired. Your app calls this whenever it needs to forward a token to your backend — it never needs to manage expiry itself.

const token = await nucleus.auth.getAccessToken();

// Forward to your backend
await fetch('/api/my-data', {
  headers: { 'X-Nucleus-Token': token },
});

nucleus.auth.isAuthenticated()

Returns true if a session is active.

if (await nucleus.auth.isAuthenticated()) {
  // render the app
} else {
  await nucleus.auth.signIn();
}

nucleus.auth.getUser()

Async. Fetches the current user's identity from the Nucleus session endpoint on the first call, then caches the result for the lifetime of the session. Returns null if not authenticated.

const user = await nucleus.auth.getUser();
// user.id, user.displayName, user.firstName, user.lastName,
// user.email, user.pictureUrl, user.jobTitle, user.department

Do not call getUser() in a render loop or hot path — use getSession().user for synchronous reads after the first call.


nucleus.auth.getSession()

Synchronous. Returns the current in-memory session state. Returns null if no session is active.

const session = nucleus.auth.getSession();
if (session) {
  session.accessToken; // string — forward this to your backend
  session.expiresAt; // number (ms) — when the access token expires
  session.user; // NucleusUser | null — null until getUser() has been called at least once
}

session.user may be null even when authenticated if getUser() has not yet been called. Call await nucleus.auth.getUser() once (e.g. on app load after handleRedirectCallback) to populate the user cache; use getSession().user for synchronous reads thereafter.


nucleus.auth.signOut()

Revokes the refresh token family server-side and clears all local tokens.

await nucleus.auth.signOut();
// User is signed out; tokens are cleared

nucleus.auth.onAuthStateChange(callback)

Subscribe to auth state changes. Fires on sign-in, sign-out, token refresh, and expiry. Returns an unsubscribe function.

const unsubscribe = nucleus.auth.onAuthStateChange((session) => {
  if (session) {
    console.log('Signed in as', session.user?.email);
  } else {
    console.log('Signed out');
    redirectToLogin();
  }
});

// Later, to stop listening:
unsubscribe();

Silent refresh

Token refresh is automatic and transparent. The SDK:

  1. Proactively refreshes 60 seconds before the access token expires (configurable)
  2. Refreshes inline if getAccessToken() is called after expiry
  3. Uses rotating refresh tokens — each refresh issues a new refresh token and invalidates the previous one
  4. Detects refresh token reuse (stolen token signal) and revokes the entire token family

You never need to manage token lifetimes in your app code.


Token storage

Tokens are stored in-memory by default — the safest option for browsers (no XSS exposure via localStorage).

For mobile / native apps, supply a custom storage adapter backed by Keychain (iOS) or Keystore (Android):

import { NucleusClient, type NucleusStorage } from '@typeb-digital/nucleus-client';

const secureStorage: NucleusStorage = {
  get: (key) => Keychain.getItem(key),
  set: (key, value) => Keychain.setItem(key, value),
  remove: (key) => Keychain.removeItem(key),
  clear: () => Keychain.clear(),
};

const nucleus = new NucleusClient({
  appId: 'app_xxxxxxxxxxxx',
  storage: secureStorage,
});

Configuration

new NucleusClient({
  appId: 'app_xxxxxxxxxxxx', // required — from Nucleus dashboard
  baseUrl: 'https://nucleus.typeb-lab.online', // optional, defaults to platform URL
  redirectUri: 'https://myapp.com/auth/callback', // optional default redirect URI
  useRefreshTokens: true, // default true — enable silent refresh
  refreshLeewaySeconds: 60, // default 60 — refresh this many seconds before expiry
  storage: customStorageAdapter, // default: in-memory
});

React example

import { useEffect, useState } from 'react';
import { nucleus } from './nucleus'; // your NucleusClient instance

function App() {
  const [ready, setReady] = useState(false);

  useEffect(() => {
    // Handle auth callback on the redirect route
    if (window.location.pathname === '/auth/callback') {
      nucleus.auth.handleRedirectCallback().then(() => {
        window.location.replace('/');
      });
      return;
    }

    nucleus.auth.isAuthenticated().then((ok) => {
      if (!ok) nucleus.auth.signIn();
      else setReady(true);
    });

    return nucleus.auth.onAuthStateChange((session) => {
      setReady(session !== null);
    });
  }, []);

  if (!ready) return <div>Loading...</div>;
  return <MainApp />;
}

Error handling

The client SDK throws on errors rather than returning result objects (unlike the server SDK's isError pattern). Wrap auth calls in try/catch:

try {
  await nucleus.auth.handleRedirectCallback();
} catch (err) {
  // Token exchange failed, state mismatch, network error, etc.
  console.error('Auth callback failed:', err);
  await nucleus.auth.signIn(); // re-start the flow
}

try {
  const token = await nucleus.auth.getAccessToken();
} catch (err) {
  // Access token expired and refresh failed (token revoked, network down, etc.)
  await nucleus.auth.signIn();
}

The two methods that do not throw are:

  • getUser() — returns null on failure (unauthenticated or network error)
  • getSession() — returns null if no session is active (synchronous, no network call)

License

MIT — Type B Digital