{"id":15357133,"url":"https://github.com/chocolateboy/enumerator","last_synced_at":"2026-07-02T02:32:26.466Z","repository":{"id":53787622,"uuid":"325338877","full_name":"chocolateboy/enumerator","owner":"chocolateboy","description":"Generate a series of tuples in lexicographical order","archived":false,"fork":false,"pushed_at":"2021-06-05T16:13:12.000Z","size":384,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-30T15:40:33.913Z","etag":null,"topics":["alphabet","cartesian-product","combinatorics","cross-product","enumerable","generator","iterable","lexicographic","lexicographical","n-tuple","odometer","permutation","permutations","sequence","symbols","tuple"],"latest_commit_sha":null,"homepage":"","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/chocolateboy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-29T16:47:02.000Z","updated_at":"2021-11-02T22:20:17.000Z","dependencies_parsed_at":"2022-09-04T17:11:15.474Z","dependency_job_id":null,"html_url":"https://github.com/chocolateboy/enumerator","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/chocolateboy/enumerator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Fenumerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Fenumerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Fenumerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Fenumerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chocolateboy","download_url":"https://codeload.github.com/chocolateboy/enumerator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chocolateboy%2Fenumerator/sbom","scorecard":{"id":278555,"data":{"date":"2025-08-11","repo":{"name":"github.com/chocolateboy/enumerator","commit":"e1a163660eb84df3ef0ddf922c44d746657a6583"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/25 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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":6,"reason":"dependency not pinned by hash detected -- score normalized to 6","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/chocolateboy/enumerator/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/chocolateboy/enumerator/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/chocolateboy/enumerator/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/chocolateboy/enumerator/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/chocolateboy/enumerator/test.yml/master?enable=pin","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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/f6ed084d17c9236477efd66e5b258b9d4cc7b389/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 1 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"35 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-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j","Warn: Project is vulnerable to: GHSA-7r28-3m3f-r2pr","Warn: Project is vulnerable to: GHSA-r8j5-h5cx-65gg","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq","Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488","Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g","Warn: Project is vulnerable to: GHSA-5v2h-r2cx-5xgj","Warn: Project is vulnerable to: GHSA-rrrm-qjm4-v8hf","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-px4h-xg32-q955","Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-566m-qj78-rww5","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-hwj9-h5mp-3pm3","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-38fc-wpqx-33j7"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T15:08:36.798Z","repository_id":53787622,"created_at":"2025-08-17T15:08:36.799Z","updated_at":"2025-08-17T15:08:36.799Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35030920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"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":["alphabet","cartesian-product","combinatorics","cross-product","enumerable","generator","iterable","lexicographic","lexicographical","n-tuple","odometer","permutation","permutations","sequence","symbols","tuple"],"created_at":"2024-10-01T12:33:22.123Z","updated_at":"2026-07-02T02:32:26.437Z","avatar_url":"https://github.com/chocolateboy.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# enumerator\n\n[![Build Status](https://github.com/chocolateboy/enumerator/workflows/test/badge.svg)](https://github.com/chocolateboy/enumerator/actions?query=workflow%3Atest)\n[![NPM Version](https://img.shields.io/npm/v/@chocolatey/enumerator.svg)](https://www.npmjs.org/package/@chocolatey/enumerator)\n\n\u003c!-- TOC --\u003e\n\n- [NAME](#name)\n- [FEATURES](#features)\n- [INSTALLATION](#installation)\n- [SYNOPSIS](#synopsis)\n- [DESCRIPTION](#description)\n  - [Why?](#why)\n- [EXPORTS](#exports)\n  - [enumerate](#enumerate)\n  - [enumerator](#enumerator)\n  - [unfold](#unfold)\n- [EXAMPLES](#examples)\n  - [Generating passwords](#generating-passwords)\n  - [Combining options](#combining-options)\n- [DEVELOPMENT](#development)\n- [COMPATIBILITY](#compatibility)\n- [SEE ALSO](#see-also)\n- [VERSION](#version)\n- [AUTHOR](#author)\n- [COPYRIGHT AND LICENSE](#copyright-and-license)\n\n\u003c!-- TOC END --\u003e\n\n# NAME\n\nenumerator - generate a series of tuples in lexicographical order\n\n# FEATURES\n\n- no dependencies\n- ~500 B minified + gzipped\n- fully typed (TypeScript)\n- CDN builds (UMD): [jsDelivr][], [unpkg][]\n\n# INSTALLATION\n\n```\n$ npm install @chocolatey/enumerator\n```\n\n# SYNOPSIS\n\n```javascript\nimport { enumerate, enumerator } from '@chocolatey/enumerator'\n\nconst bits = [0, 1]\nconst words = ['foo', 'bar', 'baz', 'quux']\n\n// generator\nfor (const value of enumerator([words, bits])) {\n    console.log(value) // [\"foo\", 0], [\"foo\", 1], [\"bar\", 0] ... [\"quux\", 1]\n}\n\n// array\nenumerate(bits, 2) // [[0, 0], [0, 1], [1, 0], [1, 1]]\n```\n\n# DESCRIPTION\n\nEnumerator generates a series of tuples in lexicographical order. Each tuple is\nan array of values drawn from a custom alphabet for each position. Values can\nbe of any type.\n\nThe mechanism for generating the values is the same as an odometer, i.e. the\nrightmost dial/column is incremented for each result, moving left each time a\ndial rolls over, and halting when the leftmost dial rolls over, e.g.:\n\n```javascript\nenumerate([[0, 1], [0, 1]]) // [[0, 0], [0, 1], [1, 0], [1, 1]]\n```\n\nIn this example, the same alphabet is used for each position. As a shorthand, a\nsingle alphabet can be repeated n times by supplying n as the second argument,\ne.g.:\n\n```javascript\nenumerate([0, 1], 2) // [[0, 0], [0, 1], [1, 0], [1, 1]]\n```\n\n## Why?\n\n\u003e Because we often face problems in which an exhaustive examination of all\n\u003e cases is necessary or desirable.\n\n— Donald Knuth, *The Art of Computer Programming*, Section 7.2.1.1, Generating All \u003ci\u003en\u003c/i\u003e-Tuples.\n\n# EXPORTS\n\n## enumerate\n\n- **Type**:\n  - `\u003cT\u003e(alphabet: T[], length: number) =\u003e Array\u003cT[]\u003e`\n  - `\u003cT\u003e(alphabets: T[][]) =\u003e Array\u003cT[]\u003e`\n- **Alias**: `generate`\n\n```javascript\nimport { enumerate } from '@chocolatey/enumerator'\n\nenumerate([0, 1], 2) // [[0, 0], [0, 1], [1, 0], [1, 1]]\n```\n\nTakes an array of alphabets, or a single alphabet and a length (number of times\nto repeat the alphabet), and returns an array of all the permutations of\nvalues from each alphabet in lexicographical order.\n\nThis is a wrapper around [`enumerator`](#enumerator-1) which gathers the generated\nvalues into an array, i.e. the following are equivalent:\n\n```javascript\nconst array1 = enumerate(...args)\nconst array2 = Array.from(enumerator(...args))\n```\n\n## enumerator\n\n- **Type**:\n  - `\u003cT\u003e(alphabet: T[], length: number) =\u003e Generator\u003cT[]\u003e`\n  - `\u003cT\u003e(alphabets: T[][]) =\u003e Generator\u003cT[]\u003e`\n- **Alias**: `generator`\n\n```javascript\nimport { enumerator } from '@chocolatey/enumerator'\n\nfor (const value of enumerator([0, 1], 2)) {\n    console.log(value) // [0, 0], [0, 1], [1, 0], [1, 1]\n}\n```\n\nTakes an array of alphabets, or a single alphabet and a length (number of times\nto repeat the alphabet), and yields all the permutations of values from each\nalphabet in lexicographical order.\n\n## unfold\n\n- **Type**: `\u003cV\u003e(obj: Record\u003cstring, V | V[]\u003e) =\u003e [string, V][][]`\n\n```javascript\nimport { unfold } from '@chocolatey/enumerator'\n\nconst options = {\n    color: ['black', 'pink'],\n    size: ['small', 'large'],\n    discount: false,\n}\n\nconst alphabets = unfold(options)\n```\n\n```javascript\n[\n    [[\"color\", \"black\"], [\"color\", \"pink\"]], // 0\n    [[\"size\", \"small\"], [\"size\", \"large\"]],  // 1\n    [[\"discount\", false]]                    // 2\n]\n```\n\nTakes a plain object and flattens it into an array of arrays of key/value pairs\nsuitable for use as alphabets. The object is unchanged. The object's values are\ncoerced to arrays, so if a single value is already an array, it will need to be\nwrapped in another array, e.g.:\n\n```javascript\n// before x\nconst data = {\n    loc: [x, y],\n}\n\n// after ✔\nconst data = {\n    loc: [[x, y]],\n}\n```\n\n# EXAMPLES\n\n## Generating passwords\n\nSuppose you've protected a Word document or zipfile with the password\n\"rosebud\", but can't remember if any letters were uppercase, if it was one word\nor two, or if there were any substitutions. A list of candidate passwords can\nbe generated by:\n\n```javascript\nconst alphabets = [\n    ['r', 'R'],\n    ['o', 'O', '0'],\n    ['s', 'S', '5'],\n    ['e', 'E', '3'],\n    ['', ' '],\n    ['b', 'B'],\n    ['u', 'U'],\n    ['d', 'D'],\n]\n\nconst passwords = enumerate(alphabets).map(it =\u003e it.join(''))\n```\n\nThis generates 864 different candidates, including \"rosebud\", \"r053buD\",\n\"Rose Bud\", and \"ROSEBUD\".\n\n## Combining options\n\nAlthough any types can be used as values, a specific task may require some\ndata munging to encode its choices as alphabets. To this end, a helper\nfunction, [`unfold`](#unfold), is available which translates a plain object\ninto an array of alphabets of key/value pairs representing an option or\nfeature.\n\nFor example, if a product is available with the following options:\n\n- color: red, black, pink\n- size: small, medium, large\n\n\\- the permutations can be generated with:\n\n```javascript\nimport { enumerate, unfold } from '@chocolatey/enumerator'\n\nconst options = {\n    color: ['red', 'black', 'pink'],\n    size: ['small', 'medium', 'large'],\n}\n\nconst alphabets = unfold(options)\nconst products = enumerate(alphabets).map(Object.fromEntries)\n```\n\n\\- which yields the following result:\n\n```javascript\n[\n    { color: 'red', size: 'small' },\n    { color: 'red', size: 'medium' },\n    { color: 'red', size: 'large' },\n    { color: 'black', size: 'small' },\n    { color: 'black', size: 'medium' },\n    { color: 'black', size: 'large' },\n    { color: 'pink', size: 'small' },\n    { color: 'pink', size: 'medium' },\n    { color: 'pink', size: 'large' }\n]\n```\n\n# DEVELOPMENT\n\n\u003cdetails\u003e\n\n\u003c!-- TOC:ignore --\u003e\n## NPM Scripts\n\nThe following NPM scripts are available:\n\n- build - compile the library for testing and save to the target directory\n- build:doc - generate the README's TOC (table of contents)\n- build:release - compile the library for release and save to the target directory\n- clean - remove the target directory and its contents\n- rebuild - clean the target directory and recompile the library\n- repl - launch a node REPL with the library loaded\n- test - recompile the library and run the test suite\n- test:run - run the test suite\n- typecheck - sanity check the library's type definitions\n\n\u003c/details\u003e\n\n# COMPATIBILITY\n\n- [Maintained Node.js versions](https://github.com/nodejs/Release#readme) and compatible browsers\n\n# SEE ALSO\n\n\u003c!-- TOC:ignore --\u003e\n## JavaScript\n\n- [@kingjs/enumerable.from-each](https://www.npmjs.com/package/%40kingjs%2Fenumerable.from-each)\n- [@kingjs/odometer](https://www.npmjs.com/package/@kingjs/odometer)\n\n\u003c!-- TOC:ignore --\u003e\n## Perl\n\n- [Algorithm::Odometer::Tiny](https://metacpan.org/pod/Algorithm::Odometer::Tiny)\n\n# VERSION\n\n1.1.1\n\n# AUTHOR\n\n[chocolateboy](https://github.com/chocolateboy)\n\n# COPYRIGHT AND LICENSE\n\nCopyright © 2020-2021 by chocolateboy.\n\nThis is free software; you can redistribute it and/or modify it under the terms\nof the [MIT license](https://opensource.org/licenses/MIT).\n\n[jsDelivr]: https://cdn.jsdelivr.net/npm/@chocolatey/enumerator\n[unpkg]: https://unpkg.com/@chocolatey/enumerator\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchocolateboy%2Fenumerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchocolateboy%2Fenumerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchocolateboy%2Fenumerator/lists"}