{"id":28545141,"url":"https://github.com/moxystudio/node-token-dealer","last_synced_at":"2025-10-14T00:03:33.934Z","repository":{"id":57377711,"uuid":"52171977","full_name":"moxystudio/node-token-dealer","owner":"moxystudio","description":"Circumvent API rate limits by having several API tokens and let the dealer manage and give them to you","archived":false,"fork":false,"pushed_at":"2020-01-03T10:05:59.000Z","size":674,"stargazers_count":24,"open_issues_count":0,"forks_count":1,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-09-20T02:52:08.849Z","etag":null,"topics":["api","dealer","limits","nodejs","rate-limit","rate-limiting","token"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moxystudio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-20T19:44:06.000Z","updated_at":"2025-03-06T02:29:05.000Z","dependencies_parsed_at":"2022-09-19T03:30:48.018Z","dependency_job_id":null,"html_url":"https://github.com/moxystudio/node-token-dealer","commit_stats":null,"previous_names":["indigounited/node-token-dealer"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/moxystudio/node-token-dealer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxystudio%2Fnode-token-dealer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxystudio%2Fnode-token-dealer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxystudio%2Fnode-token-dealer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxystudio%2Fnode-token-dealer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moxystudio","download_url":"https://codeload.github.com/moxystudio/node-token-dealer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxystudio%2Fnode-token-dealer/sbom","scorecard":{"id":113625,"data":{"date":"2025-08-04","repo":{"name":"github.com/moxystudio/node-token-dealer","commit":"1e6b0ab60d8ff04133fce8e428636d27c0b45961"},"scorecard":{"version":"v5.2.1-28-gc1d103a9","commit":"c1d103a9bb9f635ec7260bf9aa0699466fa4be0e"},"score":1.7,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"51 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-ff7x-qrg7-qggm","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-2cf5-4w76-r9qv","Warn: Project is vulnerable to: GHSA-3cqr-58rm-57f8","Warn: Project is vulnerable to: GHSA-g9r4-xpmj-mj65","Warn: Project is vulnerable to: GHSA-q2c6-c6pm-g3gh","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-h726-x36v-rx45","Warn: Project is vulnerable to: GHSA-779f-wgxg-qr8f","Warn: Project is vulnerable to: GHSA-4xcv-9jjx-gfj3","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-4g88-fppr-53pp","Warn: Project is vulnerable to: GHSA-4jqc-8m5r-9rpr","Warn: Project is vulnerable to: GHSA-7xcx-6wjh-7xp2","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-38fc-wpqx-33j7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c1d103a9bb9f635ec7260bf9aa0699466fa4be0e/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-15T19:40:29.375Z","repository_id":57377711,"created_at":"2025-08-15T19:40:29.375Z","updated_at":"2025-08-15T19:40:29.375Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279017250,"owners_count":26086051,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","dealer","limits","nodejs","rate-limit","rate-limiting","token"],"created_at":"2025-06-09T23:06:40.803Z","updated_at":"2025-10-14T00:03:33.928Z","avatar_url":"https://github.com/moxystudio.png","language":"JavaScript","readme":"# token-dealer\n\n[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][codecov-image]][codecov-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]\n\n[npm-url]:https://npmjs.org/package/token-dealer\n[npm-image]:https://img.shields.io/npm/v/token-dealer.svg\n[downloads-image]:https://img.shields.io/npm/dm/token-dealer.svg\n[travis-url]:https://travis-ci.org/moxystudio/node-token-dealer\n[travis-image]:https://img.shields.io/travis/moxystudio/node-token-dealer/master.svg\n[codecov-url]:https://codecov.io/gh/moxystudio/node-token-dealer\n[codecov-image]:https://img.shields.io/codecov/c/github/moxystudio/node-token-dealer/master.svg\n[david-dm-url]:https://david-dm.org/moxystudio/node-token-dealer\n[david-dm-image]:https://img.shields.io/david/moxystudio/node-token-dealer.svg\n[david-dm-dev-url]:https://david-dm.org/moxystudio/node-token-dealer?type=dev\n[david-dm-dev-image]:https://img.shields.io/david/dev/moxystudio/node-token-dealer.svg\n\nCircumvent API rate limits by having several API tokens and let the dealer manage and give them to you.\n\nSeveral public APIs, such as GitHub and Twitter, have rate limits applied per account. To multiply these rate limits, you must have a farm of tokens associated to multiple accounts, either donated or created by you. This is where `token-dealer` comes in, making it easy to\nmanage these tokens and their usage.\n\n\n## Installation\n\n`$ npm install token-dealer`\n\n\n## Usage\n\n### tokenDealer(tokens, fn, [options])\n\nCalls `fn(token, exhaust)` with the most appropriate `token` from `tokens` and a `exhaust` function that you may call to signal that the token is exhausted.\n\nBasically the only thing you must do is call `exhaust(reset, [retry])` whenever you know that the token may not be used again until `reset` (timestamp in ms). Additionally, you may retry if the operation you were trying to do failed because the token was exhausted, causing `fn` to be called again with another token.\n\nHere's an example from a request to the [GitHub API](https://developer.github.com/v3/#rate-limiting) using [got](https://www.npmjs.com/package/got):\n\n```js\nconst tokenDealer = require('tokenDealer');\nconst got = require('got');\n\nconst tokens = [\n    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',\n    'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',\n];\n\ntokenDealer(tokens, (token, exhaust) =\u003e {\n    const handleRateLimit = (response, err) =\u003e {\n        if (response.headers['x-ratelimit-remaining'] === '0') {\n            const isRateLimitError = err \u0026\u0026 err.statusCode === 403 \u0026\u0026 /rate limit/i.test(response.body.message);\n\n            exhaust(Number(response.headers['x-ratelimit-reset']) * 1000, isRateLimitError);\n        }\n    };\n\n    return got('https://api.github.com/repos/moxystudio/node-cross-spawn', {\n        json: true,\n        headers: { Authorization: `token ${token}` },\n    })\n    .then((response) =\u003e {\n        handleRateLimit(response);\n        return response;\n    }, (err) =\u003e {\n        err.response \u0026\u0026 handleRateLimit(err.response, err);\n        throw err;\n    });\n})\n.then((response) =\u003e {\n    // ...\n}, (err) =\u003e {\n    // If all tokens are exhausted, err.code will be 'EALLTOKENSEXHAUSTED'\n});\n```\n\nAvailable options:\n\n- `group`: The group associated to the tokens; this effectively groups tokens to prevent conflicts (e.g. `github`, defaults to `default`).\n- `wait`: True to wait for a token to be free in case all are exhausted (defaults to `false`); alternatively you may pass a function that will be called with `[token, duration]` so that you can decide to wait dynamically.\n- `lru`: A custom [LRU cache](https://www.npmjs.com/package/lru-cache) instance to be used internally.\n- `onExhausted`: Called with `(token, reset)` whenever a token become exhausted (defaults to `null`).\n\n\nIf `tokens` is nullish or an empty array, the given `token` will be an empty string.\n\n\n### tokenDealer.getTokensUsage(tokens, [options])\n\nGet the tokens usage for `tokens`. The available options are `group` and `lru` which are the same as `tokenDealer()`.\n\n```js\nconst tokenDealer = require('tokenDealer');\n\nconst tokens = [\n    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',\n    'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',\n];\n\nconst usage = tokenDealer.getTokensUsage(tokens);\n\n// `usage` looks like this:\n// {\n//     'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa': {\n//         exhausted: true,       // true if exhausted, false otherwise\n//         reset: 1455996883369,  // the timestamp in which the token will become available again\n//         inflight: 0,           // the number of deliveries (`fn` calls) that still haven't completed\n//     },\n//     'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb': {\n//         // ...\n//     }\n// }\n```\n\n\n## Tests\n\n`$ npm test`   \n`$ npm test -- --watch` during development\n\n\n## License\n\nReleased under the [MIT License](https://www.opensource.org/licenses/mit-license.php).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoxystudio%2Fnode-token-dealer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoxystudio%2Fnode-token-dealer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoxystudio%2Fnode-token-dealer/lists"}