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

token-provider

v1.0.7

Published

A token provider to sync api key state across multiple instances.

Readme

Token Provider

This library helps developers adhere to rate limits imposed by third-party providers across multiple running processes at once.

Example

The Gitlab API has strict rate limits of:

10 requests / second
600 requests / minute

Let's say your users supply your backend with their personal Gitlab token to make API calls on their behalf. Let's also say you have more than one backend server that can use the token at any given time (dosesn't have to be literal servers, it could also just be multiple running Pods in a Kubernetes cluster).

You (as the developer) want to adhere to the rate limits imposed by Gitlab. But you also want to let the work be managed by any (often simultaneous) backend instances.

How do you sync the usage of the users personal token across all of your backend instances?

This library gives developers a TokenProvider instance that returns a new Token object for a given api key. The usage of this Token is synced across all of your instances. It uses a Promise when you want to use the token to release it when it can be used.

Let's look at a code example:

import { TokenProvider, Token, RedisStorageProvider } from 'token-provider'

async function main() {
    // Create the token provider
    const tokenProvider = new TokenProvider({
        name: "Gitlab Token Provider",
        quotas: [
            {
                numberOfRequests: 10,
                duration: "1s",
            },
            {
                numberOfRequests: 600,
                duration: "1m",
            },
        ],
        storage: new RedisStorageProvider({}),
    })

    // Fetch the users token
    const token: Token = tokenProvider.getToken('<API TOKEN HERE>')

    // Use the token a bunch
    for (let i = 0; i < 1000; i++) {
        const startTime = new Date().getTime()

        const res = await axios({
            method: 'GET',
            url: 'https://gitlab.com/api/v4/user',
            headers: {
                'PRIVATE-TOKEN': await token.use()
            }
        })

        console.log(`${new Date().getTime() - startTime}ms`)
    }
}

main().then(() => console.log('finished'))

The TokenProvider takes configuration data about the rate limits it needs to restrict usage by, a friendly name, and the backend storage provider to use (Redis in this case).

We use TokenProvider.getToken(tokenKey: string) to fetch the corresponding Token object.

When we want to use the token, we call token.use(). This returns a Promise that only resolves when the Token can be used again. It also adds to the usage counter. This usage state is synced across all instances that are connected to the same TokenStorageProvider (Redis in this case.).

Documentation

TokenProvider

This is the root instance of the library. Use it to get the corresponding Token instance for each key you are using.

Constructor

Below is the configuration for a new TokenProvider. It uses parse-duration for duration fields.

new TokenProvider({
    name: 'Name Here', // Just a friendly name of the provider. REQUIRED.
    quotas: [ // A list of the rate limit quotas we need to adhere by. REQUIRED
        {
            numberOfRequests: 0, // Number, how many requests can be made?
            duration: '1m' // String, what is the duration? Uses parse-duration syntax. e.g. 1m = 1 minute, 1h = 1h, 30s = 30 seconds...
        }
    ],
    storage: new MemoryStorageProvider() // Instantiated storage provider. Currently only RedisStorageProvider and MemoryStorageProvider are allowed.
})

getToken

.getToken(tokenKey: string) -> Only requires a string, returns the Token object.

const token: Token = tokenProvider.getToken('<API KEY HERE>');

Token

This represents a users token.

use

token.use() -> Returns a Promise that resolves when the token can be used. It can be used in two different ways:

Option 1, async:

const res = await axios({
    method: 'GET',
    url: '... some url',
    headers: {
        'PRIVATE-TOKEN': await token.use()
    }
})

Option 2, callback:

token.use(async (tokenKey: string) => {
    const res = await axios({
        method: 'GET',
        url: '... some url',
        headers: {
            'PRIVATE-TOKEN': tokenKey
        }
    })
})

Storage Providers

Storage Providers are the backing storage for the usage state. Currently there are two flavors, and only one that syncs across multiple instances.

RedisStorageProvider

This Storage Provider uses Redis as the backing data state.

Constructor

This uses the redis package as the Redis client. The input configuration matches this clients ClientOpts exactly.

const redisStorageProvider = new RedisStorageProvider({
    ... redis ClientOpts
})

It uses a hashing algorithm to hash the TokenProvider.name, Quota.uid (generated), and the Token.key for storage. While the token value is hashed, I wouldn't call it encrypted. Please keep your Redis instance secured.

MemoryStorageProvider

This just uses in-memory variables to handle the usage state. This is fine for a single application but it will not scale to multiple instances.

Constructor

No options.

const memoryStorageProvider = new MemoryStorageProvider()