@bigdreamsweb3/wordbin 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +155 -0
- package/README.md +141 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.mjs +146 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/core/id.d.ts +5 -0
- package/dist/core/tiers.d.ts +4 -0
- package/dist/core.d.ts +16 -0
- package/dist/data/wordbin-v1-bip39.json +6148 -0
- package/dist/dictionary-D3gr2Ala.js +114 -0
- package/dist/dictionary-D3gr2Ala.js.map +1 -0
- package/dist/dictionary-loader.d.ts +19 -0
- package/dist/dictionary.d.ts +19 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +232 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types.d.ts +21 -0
- package/dist/utils/buffer.d.ts +11 -0
- package/package.json +83 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Here's the **CONTRIBUTING.md** file ready for you to download and use in your project.
|
|
2
|
+
|
|
3
|
+
You can copy the content below and save it as `CONTRIBUTING.md` in the root of your repository.
|
|
4
|
+
|
|
5
|
+
```markdown
|
|
6
|
+
# Contributing to WordBin
|
|
7
|
+
|
|
8
|
+
Thank you for your interest in contributing to WordBin!
|
|
9
|
+
We welcome all kinds of help — bug reports, documentation improvements, new features, dictionary variants, tests, or even small fixes.
|
|
10
|
+
|
|
11
|
+
This guide explains how to contribute effectively and what would be most valuable to the project right now.
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Code of Conduct](#code-of-conduct)
|
|
16
|
+
- [How to Contribute](#how-to-contribute)
|
|
17
|
+
- [Reporting Bugs](#reporting-bugs)
|
|
18
|
+
- [Suggesting Features or Improvements](#suggesting-features-or-improvements)
|
|
19
|
+
- [Submitting Pull Requests](#submitting-pull-requests)
|
|
20
|
+
- [Good First Issues](#good-first-issues)
|
|
21
|
+
- [Development Setup](#development-setup)
|
|
22
|
+
- [Current Priorities (2026)](#current-priorities-2026)
|
|
23
|
+
- [Code Style & Conventions](#code-style--conventions)
|
|
24
|
+
- [License](#license)
|
|
25
|
+
|
|
26
|
+
## Code of Conduct
|
|
27
|
+
|
|
28
|
+
This project follows the [Contributor Covenant Code of Conduct v2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/).
|
|
29
|
+
Be respectful, inclusive, and constructive in all interactions.
|
|
30
|
+
|
|
31
|
+
## How to Contribute
|
|
32
|
+
|
|
33
|
+
### Reporting Bugs
|
|
34
|
+
|
|
35
|
+
If you find a bug:
|
|
36
|
+
|
|
37
|
+
1. Check if it's already reported in [existing issues](https://github.com/bigdreamsweb3/wordbin/issues).
|
|
38
|
+
2. If not, open a new issue and include:
|
|
39
|
+
- Clear, descriptive title
|
|
40
|
+
- Steps to reproduce
|
|
41
|
+
- Expected vs actual behavior
|
|
42
|
+
- Node.js / browser version
|
|
43
|
+
- Dictionary version used (v1/v2/custom)
|
|
44
|
+
- Minimal code snippet or test case
|
|
45
|
+
|
|
46
|
+
Use the **Bug report** template when available.
|
|
47
|
+
|
|
48
|
+
### Suggesting Features or Improvements
|
|
49
|
+
|
|
50
|
+
Have an idea for a new feature, better performance, UX improvement, or new dictionary type?
|
|
51
|
+
|
|
52
|
+
Open an issue with:
|
|
53
|
+
- Problem or opportunity you're addressing
|
|
54
|
+
- Proposed solution (as detailed as you want)
|
|
55
|
+
- Any alternatives you've considered
|
|
56
|
+
- Rough estimate of impact/benefit
|
|
57
|
+
|
|
58
|
+
Use the **Feature request** template if it exists.
|
|
59
|
+
|
|
60
|
+
### Submitting Pull Requests
|
|
61
|
+
|
|
62
|
+
Want to submit code? Awesome!
|
|
63
|
+
|
|
64
|
+
1. **Fork** the repository and **clone** your fork
|
|
65
|
+
2. Create a new branch:
|
|
66
|
+
`git checkout -b fix/lowercase-normalization`
|
|
67
|
+
or `feat/add-top-20k-dictionary`
|
|
68
|
+
3. Make your changes
|
|
69
|
+
4. Add or update tests if applicable
|
|
70
|
+
5. Run the test suite:
|
|
71
|
+
`npm test` or `npm run vitest`
|
|
72
|
+
6. Commit with clear messages (semantic style preferred):
|
|
73
|
+
`fix: normalize words to lowercase in buildDictionary`
|
|
74
|
+
`feat: add CLI flag for lowercase normalization`
|
|
75
|
+
`docs: improve contributing guide`
|
|
76
|
+
`test: add cases for empty input and literals`
|
|
77
|
+
7. Push your branch and open a pull request against `main`
|
|
78
|
+
|
|
79
|
+
Small, focused PRs are usually merged quickly.
|
|
80
|
+
Larger changes might be reviewed in stages — feel free to open a draft PR early to discuss.
|
|
81
|
+
|
|
82
|
+
### Good First Issues
|
|
83
|
+
|
|
84
|
+
Looking for an easy entry point? These tasks are beginner-friendly:
|
|
85
|
+
|
|
86
|
+
- Improve/fix documentation or README examples
|
|
87
|
+
- Add case normalization (lowercase) to dictionary building
|
|
88
|
+
- Create a smaller curated dictionary (e.g. top 10k–50k English words)
|
|
89
|
+
- Add more helpful messages or progress indicators to the CLI
|
|
90
|
+
- Write tests for edge cases (empty strings, very long phrases, invalid base64)
|
|
91
|
+
- Create a simple browser demo (CodeSandbox, StackBlitz, or static HTML)
|
|
92
|
+
|
|
93
|
+
Look for issues labeled **[good first issue]** on GitHub.
|
|
94
|
+
|
|
95
|
+
## Development Setup
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# 1. Fork & clone the repo
|
|
99
|
+
git clone https://github.com/bigdreamsweb3/wordbin.git
|
|
100
|
+
cd wordbin
|
|
101
|
+
|
|
102
|
+
# 2. Install dependencies
|
|
103
|
+
npm install
|
|
104
|
+
|
|
105
|
+
# 3. Build the library
|
|
106
|
+
npm run build
|
|
107
|
+
|
|
108
|
+
# 4. Run tests
|
|
109
|
+
npm test
|
|
110
|
+
# or watch mode:
|
|
111
|
+
npm run vitest
|
|
112
|
+
|
|
113
|
+
# 5. Build dictionaries (optional)
|
|
114
|
+
npx wordbin build --version 2
|
|
115
|
+
# or interactive mode:
|
|
116
|
+
npx wordbin build
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Main source code lives in `src/`.
|
|
120
|
+
Generated dictionaries appear in `data/`.
|
|
121
|
+
|
|
122
|
+
## Current Priorities (2026)
|
|
123
|
+
|
|
124
|
+
These improvements would have the biggest impact right now:
|
|
125
|
+
|
|
126
|
+
- Case-insensitive dictionaries (normalize to lowercase during build)
|
|
127
|
+
- Smaller curated dictionaries (top 10k–50k words, programming keywords, domain-specific lists…)
|
|
128
|
+
- Performance & compression benchmarks across dictionaries and phrase lengths
|
|
129
|
+
- Interactive browser demo (CodeSandbox / StackBlitz / simple HTML page)
|
|
130
|
+
- CLI enhancements (progress bars, `--lowercase`, `--output-dir`, better help)
|
|
131
|
+
- Better error handling & messages (missing dictionary, invalid input, etc.)
|
|
132
|
+
|
|
133
|
+
If you're unsure where to begin — feel free to ask in an issue or draft PR!
|
|
134
|
+
|
|
135
|
+
## Code Style & Conventions
|
|
136
|
+
|
|
137
|
+
- ESM syntax (`import` / `export`)
|
|
138
|
+
- TypeScript where possible
|
|
139
|
+
- Vitest for testing
|
|
140
|
+
- Prefer async/await
|
|
141
|
+
- Small, focused functions
|
|
142
|
+
- JSDoc comments for public APIs
|
|
143
|
+
|
|
144
|
+
We use **Prettier** + **ESLint** — run these before committing:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm run lint
|
|
148
|
+
npm run format
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
By contributing your code to this project, you agree that it will be licensed under the same [MIT License](./LICENSE) as the rest of the project.
|
|
154
|
+
|
|
155
|
+
Thank you for helping make WordBin better!
|
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# WordBin – Encode words & short phrases into tiny, reversible binary
|
|
2
|
+
|
|
3
|
+
  
|
|
4
|
+
|
|
5
|
+
**WordBin** is a deterministic, reversible word-to-binary encoder/decoder that compresses short human-readable phrases into **tiny, predictable binary payloads**.
|
|
6
|
+
|
|
7
|
+
Optimized for **Web3, blockchain, QR codes, IoT, URLs, and other space-sensitive applications**, WordBin ensures short sequences of words can be stored efficiently and recovered reliably.
|
|
8
|
+
|
|
9
|
+
**npm description (for publishing):**
|
|
10
|
+
|
|
11
|
+
> Deterministic word-to-binary encoder: compress short phrases for blockchain, Web3, IoT, QR codes, or space-sensitive storage.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Why WordBin
|
|
16
|
+
|
|
17
|
+
- Compress short phrases (crypto seeds, tags, keywords) into **2–4 byte IDs per word**.
|
|
18
|
+
- Fully **deterministic & collision-safe** — same dictionary = same encoding.
|
|
19
|
+
- Minimal payload → perfect for **blockchain metadata, NFC/QR codes, and low-bandwidth IoT**.
|
|
20
|
+
- Works in **Node.js & browser**, no runtime dependencies.
|
|
21
|
+
- Bundled **small dictionary (BIP-39)** with optional **large/custom dictionaries**.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick Install
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @bigdreamsweb3/wordbin
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
> The small **v1 (BIP-39)** dictionary is included — ready to encode/decode immediately.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Quick Start (Node.js / Browser)
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import { WordBin } from "@bigdreamsweb3/wordbin";
|
|
39
|
+
|
|
40
|
+
// Use latest dictionary (v1 bundled, v2 if built)
|
|
41
|
+
const wb = await WordBin.create();
|
|
42
|
+
|
|
43
|
+
const phrase = "abandon ability able about above";
|
|
44
|
+
const encoded = await wb.encode(phrase);
|
|
45
|
+
|
|
46
|
+
console.log("Base64 payload:", encoded.encodedBase64);
|
|
47
|
+
console.log("Encoded bytes:", encoded.encodedBytes);
|
|
48
|
+
console.log("Original bytes:", encoded.originalBytes);
|
|
49
|
+
|
|
50
|
+
const decoded = await wb.decode(encoded.encoded);
|
|
51
|
+
console.log("Decoded:", decoded); // → "abandon ability able about above"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Browser Example
|
|
55
|
+
|
|
56
|
+
```html
|
|
57
|
+
<script type="module">
|
|
58
|
+
import { WordBin } from "https://esm.sh/@bigdreamsweb3/wordbin";
|
|
59
|
+
const wb = await WordBin.create();
|
|
60
|
+
</script>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## CLI – Build Larger or Custom Dictionaries
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Interactive mode
|
|
69
|
+
npx wordbin build
|
|
70
|
+
|
|
71
|
+
# Direct commands
|
|
72
|
+
npx wordbin build --version 1 # BIP-39 (small, bundled)
|
|
73
|
+
npx wordbin build --version 2 # dwyl/english-words (~466k)
|
|
74
|
+
npx wordbin build --all # Both v1 + v2
|
|
75
|
+
npx wordbin build --custom https://example.com/mywords.txt
|
|
76
|
+
npx wordbin build --custom ./my-local-words.txt
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> All generated files go to `./data/` in your current directory.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Dictionary Versions
|
|
84
|
+
|
|
85
|
+
| Version | Filename | Words | Source | ID bytes | Best for |
|
|
86
|
+
| ------- | --------------------- | ----- | ------------------ | -------- | --------------------------------------- |
|
|
87
|
+
| v1 | wordbin-v1-bip39.json | 2,048 | BIP-39 English | ~2 | Crypto recovery seeds, high reliability |
|
|
88
|
+
| v2 | wordbin-v2-dwyl.json | ~466k | dwyl/english-words | 2–4 | General English, tags, keywords |
|
|
89
|
+
|
|
90
|
+
> **v2 note**: The dwyl list contains capitalized words. Encoding/decoding is case-sensitive. Normalize to lowercase for case-insensitive behavior.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## How It Works
|
|
95
|
+
|
|
96
|
+
1. Each word → SHA-256 → first **2–4 bytes** = deterministic ID.
|
|
97
|
+
2. Encoded payload: `[MAGIC_BYTES ('WB') | VERSION | WORD_IDS...]`
|
|
98
|
+
3. Decoding reverses IDs → original words using the same dictionary.
|
|
99
|
+
4. Optimized for **short sequences**, not arbitrary long text.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Real-World Use Cases
|
|
104
|
+
|
|
105
|
+
| Use Case | Typical Savings | Dictionary |
|
|
106
|
+
| ------------------------------------- | --------------- | ---------- |
|
|
107
|
+
| Crypto recovery phrases (12–24 words) | 50–65% | v1 |
|
|
108
|
+
| Short tags / keywords | 40–70% | v2 |
|
|
109
|
+
| Tiny QR codes / NFC labels | 50–80% | v1 or v2 |
|
|
110
|
+
| Short links / URL-friendly tags | 45–65% | v2 |
|
|
111
|
+
| On-chain metadata (Ethereum, Solana) | 40–70% | v2 |
|
|
112
|
+
| LoRa / low-bandwidth IoT labels | 50–75% | v2 |
|
|
113
|
+
| Offline phrase storage / search | 35–60% | v2 |
|
|
114
|
+
|
|
115
|
+
> Not suitable for long texts, arbitrary binary files, or when dictionaries cannot be shared reliably.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Loading Specific Dictionary Versions
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
import { loadDictionaryByVersion } from "@bigdreamsweb3/wordbin";
|
|
123
|
+
|
|
124
|
+
const dictV1 = await loadDictionaryByVersion(1); // always available
|
|
125
|
+
const wbV1 = new WordBin(dictV1);
|
|
126
|
+
|
|
127
|
+
const dictV2 = await loadDictionaryByVersion(2); // throws if not built
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
MIT
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
Want to help improve WordBin?
|
|
141
|
+
Read our [CONTRIBUTING.md](./CONTRIBUTING.md) guide.
|
package/dist/cli.d.ts
ADDED
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { mkdir, writeFile, readFile } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import { stdout, stdin } from "node:process";
|
|
6
|
+
import { wordlists } from "bip39";
|
|
7
|
+
import { b as buildDictionary } from "./dictionary-D3gr2Ala.js";
|
|
8
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
9
|
+
const help = `
|
|
10
|
+
WordBin CLI – Dictionary Builder
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
npx wordbin build [options]
|
|
14
|
+
|
|
15
|
+
Options:
|
|
16
|
+
--version <num> Build specific version (1 or 2)
|
|
17
|
+
--all Build all versions
|
|
18
|
+
--custom <source> Build from custom URL or local file path
|
|
19
|
+
--help Show this help
|
|
20
|
+
|
|
21
|
+
If no options provided, enters interactive mode.
|
|
22
|
+
`;
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
const cmd = args[0];
|
|
25
|
+
async function prompt(question) {
|
|
26
|
+
return new Promise((resolve2) => {
|
|
27
|
+
rl.question(question, resolve2);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async function saveDict(version, desc, words, filename) {
|
|
31
|
+
const dict = await buildDictionary(words, {
|
|
32
|
+
version,
|
|
33
|
+
description: desc
|
|
34
|
+
});
|
|
35
|
+
const outDir = resolve(process.cwd(), "data");
|
|
36
|
+
await mkdir(outDir, { recursive: true });
|
|
37
|
+
const outPath = resolve(outDir, filename);
|
|
38
|
+
await writeFile(outPath, JSON.stringify(dict, null, 2), "utf8");
|
|
39
|
+
console.log(`Saved ${filename} (${words.length} words) to ${outPath}`);
|
|
40
|
+
}
|
|
41
|
+
async function fetchWordsFromUrl(url) {
|
|
42
|
+
const res = await fetch(url);
|
|
43
|
+
if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`);
|
|
44
|
+
const text = await res.text();
|
|
45
|
+
return text.split("\n").map((w) => w.trim()).filter(Boolean);
|
|
46
|
+
}
|
|
47
|
+
async function readWordsFromFile(path) {
|
|
48
|
+
const text = await readFile(path, "utf8");
|
|
49
|
+
return text.split("\n").map((w) => w.trim()).filter(Boolean);
|
|
50
|
+
}
|
|
51
|
+
async function buildV1() {
|
|
52
|
+
const words = wordlists.english;
|
|
53
|
+
if (!Array.isArray(words) || words.length !== 2048) {
|
|
54
|
+
throw new Error("Invalid BIP-39 wordlist");
|
|
55
|
+
}
|
|
56
|
+
await saveDict(
|
|
57
|
+
1,
|
|
58
|
+
"WordBin dictionary v1 – BIP-39 English (2048 words)",
|
|
59
|
+
words,
|
|
60
|
+
"wordbin-v1-bip39.json"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
async function buildV2() {
|
|
64
|
+
console.log("Downloading dwyl/english-words...");
|
|
65
|
+
const url = "https://raw.githubusercontent.com/dwyl/english-words/master/words.txt";
|
|
66
|
+
const words = await fetchWordsFromUrl(url);
|
|
67
|
+
await saveDict(
|
|
68
|
+
2,
|
|
69
|
+
`WordBin dictionary v2 – dwyl/english-words (${words.length} words)`,
|
|
70
|
+
words,
|
|
71
|
+
"wordbin-v2-dwyl.json"
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
async function buildCustom(source) {
|
|
75
|
+
let words;
|
|
76
|
+
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
77
|
+
console.log(`Fetching from URL: ${source}`);
|
|
78
|
+
words = await fetchWordsFromUrl(source);
|
|
79
|
+
} else {
|
|
80
|
+
console.log(`Reading from local file: ${source}`);
|
|
81
|
+
words = await readWordsFromFile(source);
|
|
82
|
+
}
|
|
83
|
+
const version = 3;
|
|
84
|
+
const desc = `WordBin custom dictionary v${version} – from ${source} (${words.length} words)`;
|
|
85
|
+
await saveDict(version, desc, words, `wordbin-v${version}-custom.json`);
|
|
86
|
+
}
|
|
87
|
+
async function interactiveMode() {
|
|
88
|
+
console.log("Interactive Dictionary Builder");
|
|
89
|
+
console.log("Options: 1 (BIP-39), 2 (dwyl large), all, custom, or q to quit");
|
|
90
|
+
const choice = await prompt("Choose dictionary to build (default: 2): ") || "2";
|
|
91
|
+
if (choice === "q") {
|
|
92
|
+
rl.close();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (choice === "1") await buildV1();
|
|
96
|
+
else if (choice === "2") await buildV2();
|
|
97
|
+
else if (choice === "all") {
|
|
98
|
+
await buildV1();
|
|
99
|
+
await buildV2();
|
|
100
|
+
} else if (choice === "custom") {
|
|
101
|
+
const source = await prompt("Enter URL or local file path: ");
|
|
102
|
+
if (source) await buildCustom(source);
|
|
103
|
+
} else {
|
|
104
|
+
console.error("Invalid choice");
|
|
105
|
+
}
|
|
106
|
+
rl.close();
|
|
107
|
+
}
|
|
108
|
+
async function main() {
|
|
109
|
+
if (cmd === "--help" || cmd === "-h") {
|
|
110
|
+
console.log(help);
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
if (cmd === "build") {
|
|
114
|
+
if (args.length === 1) {
|
|
115
|
+
await interactiveMode();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const option = args[1];
|
|
119
|
+
if (option === "--version") {
|
|
120
|
+
const ver = parseInt(args[2]);
|
|
121
|
+
if (ver === 1) await buildV1();
|
|
122
|
+
else if (ver === 2) await buildV2();
|
|
123
|
+
else console.error("Invalid version");
|
|
124
|
+
} else if (option === "--all") {
|
|
125
|
+
await buildV1();
|
|
126
|
+
await buildV2();
|
|
127
|
+
} else if (option === "--custom") {
|
|
128
|
+
const source = args[2];
|
|
129
|
+
if (!source) {
|
|
130
|
+
console.error("Provide URL or file path");
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
await buildCustom(source);
|
|
134
|
+
} else {
|
|
135
|
+
console.log(help);
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
console.log(help);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
main().catch((err) => {
|
|
143
|
+
console.error("Error:", err);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
});
|
|
146
|
+
//# sourceMappingURL=cli.mjs.map
|
package/dist/cli.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.mjs","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\r\n\r\nimport { writeFile, mkdir, readFile } from \"node:fs/promises\";\r\nimport { resolve } from \"node:path\";\r\nimport { createInterface } from \"node:readline\";\r\nimport { stdin as input, stdout as output } from \"node:process\";\r\nimport { wordlists } from \"bip39\";\r\nimport { buildDictionary } from \"./index\";\r\n\r\nconst rl = createInterface({ input, output });\r\n\r\nconst help = `\r\nWordBin CLI – Dictionary Builder\r\n\r\nUsage:\r\n npx wordbin build [options]\r\n\r\nOptions:\r\n --version <num> Build specific version (1 or 2)\r\n --all Build all versions\r\n --custom <source> Build from custom URL or local file path\r\n --help Show this help\r\n\r\nIf no options provided, enters interactive mode.\r\n`;\r\n\r\nconst args = process.argv.slice(2);\r\nconst cmd = args[0];\r\n\r\nasync function prompt(question: string): Promise<string> {\r\n return new Promise((resolve) => {\r\n rl.question(question, resolve);\r\n });\r\n}\r\n\r\nasync function saveDict(\r\n version: number,\r\n desc: string,\r\n words: string[],\r\n filename: string,\r\n) {\r\n const dict = await buildDictionary(words, {\r\n version,\r\n description: desc,\r\n });\r\n\r\n const outDir = resolve(process.cwd(), \"data\");\r\n await mkdir(outDir, { recursive: true });\r\n\r\n const outPath = resolve(outDir, filename);\r\n await writeFile(outPath, JSON.stringify(dict, null, 2), \"utf8\");\r\n\r\n console.log(`Saved ${filename} (${words.length} words) to ${outPath}`);\r\n}\r\n\r\nasync function fetchWordsFromUrl(url: string) {\r\n const res = await fetch(url);\r\n if (!res.ok) throw new Error(`Failed to fetch: ${res.status}`);\r\n\r\n const text = await res.text();\r\n return text\r\n .split(\"\\n\")\r\n .map((w) => w.trim())\r\n .filter(Boolean);\r\n}\r\n\r\nasync function readWordsFromFile(path: string) {\r\n const text = await readFile(path, \"utf8\");\r\n return text\r\n .split(\"\\n\")\r\n .map((w) => w.trim())\r\n .filter(Boolean);\r\n}\r\n\r\nasync function buildV1() {\r\n const words = wordlists.english;\r\n\r\n if (!Array.isArray(words) || words.length !== 2048) {\r\n throw new Error(\"Invalid BIP-39 wordlist\");\r\n }\r\n\r\n await saveDict(\r\n 1,\r\n \"WordBin dictionary v1 – BIP-39 English (2048 words)\",\r\n words,\r\n \"wordbin-v1-bip39.json\",\r\n );\r\n}\r\n\r\nasync function buildV2() {\r\n console.log(\"Downloading dwyl/english-words...\");\r\n\r\n const url =\r\n \"https://raw.githubusercontent.com/dwyl/english-words/master/words.txt\";\r\n\r\n const words = await fetchWordsFromUrl(url);\r\n\r\n await saveDict(\r\n 2,\r\n `WordBin dictionary v2 – dwyl/english-words (${words.length} words)`,\r\n words,\r\n \"wordbin-v2-dwyl.json\",\r\n );\r\n}\r\n\r\nasync function buildCustom(source: string) {\r\n let words: string[];\r\n\r\n if (source.startsWith(\"http://\") || source.startsWith(\"https://\")) {\r\n console.log(`Fetching from URL: ${source}`);\r\n words = await fetchWordsFromUrl(source);\r\n } else {\r\n console.log(`Reading from local file: ${source}`);\r\n words = await readWordsFromFile(source);\r\n }\r\n\r\n const version = 3;\r\n const desc = `WordBin custom dictionary v${version} – from ${source} (${words.length} words)`;\r\n\r\n await saveDict(version, desc, words, `wordbin-v${version}-custom.json`);\r\n}\r\n\r\nasync function interactiveMode() {\r\n console.log(\"Interactive Dictionary Builder\");\r\n console.log(\"Options: 1 (BIP-39), 2 (dwyl large), all, custom, or q to quit\");\r\n\r\n const choice =\r\n (await prompt(\"Choose dictionary to build (default: 2): \")) || \"2\";\r\n\r\n if (choice === \"q\") {\r\n rl.close();\r\n return;\r\n }\r\n\r\n if (choice === \"1\") await buildV1();\r\n else if (choice === \"2\") await buildV2();\r\n else if (choice === \"all\") {\r\n await buildV1();\r\n await buildV2();\r\n } else if (choice === \"custom\") {\r\n const source = await prompt(\"Enter URL or local file path: \");\r\n if (source) await buildCustom(source);\r\n } else {\r\n console.error(\"Invalid choice\");\r\n }\r\n\r\n rl.close();\r\n}\r\n\r\nasync function main() {\r\n if (cmd === \"--help\" || cmd === \"-h\") {\r\n console.log(help);\r\n process.exit(0);\r\n }\r\n\r\n if (cmd === \"build\") {\r\n if (args.length === 1) {\r\n await interactiveMode();\r\n return;\r\n }\r\n\r\n const option = args[1];\r\n\r\n if (option === \"--version\") {\r\n const ver = parseInt(args[2]);\r\n if (ver === 1) await buildV1();\r\n else if (ver === 2) await buildV2();\r\n else console.error(\"Invalid version\");\r\n } else if (option === \"--all\") {\r\n await buildV1();\r\n await buildV2();\r\n } else if (option === \"--custom\") {\r\n const source = args[2];\r\n if (!source) {\r\n console.error(\"Provide URL or file path\");\r\n process.exit(1);\r\n }\r\n await buildCustom(source);\r\n } else {\r\n console.log(help);\r\n }\r\n\r\n return;\r\n }\r\n\r\n console.log(help);\r\n process.exit(1);\r\n}\r\n\r\nmain().catch((err) => {\r\n console.error(\"Error:\", err);\r\n process.exit(1);\r\n});\r\n"],"names":["input","output","resolve"],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function getIdByteLength(wordLength: number): number;
|
|
2
|
+
export declare function getWrapByteLength(wordLength: number): number;
|
|
3
|
+
export declare function getTextEncoder(): Promise<TextEncoder>;
|
|
4
|
+
export declare function wrapBase64(data: string): Promise<Uint8Array>;
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EncodeResult, WordBinDictionary } from './types';
|
|
2
|
+
export declare class WordBin {
|
|
3
|
+
private primaryDictVersion;
|
|
4
|
+
constructor(initialDict?: WordBinDictionary, options?: {
|
|
5
|
+
debug?: boolean;
|
|
6
|
+
});
|
|
7
|
+
private log;
|
|
8
|
+
static createFromWords(words: string[]): Promise<WordBin>;
|
|
9
|
+
static createFromJson(dictJson: WordBinDictionary): Promise<WordBin>;
|
|
10
|
+
static create(): Promise<WordBin>;
|
|
11
|
+
private getReverseMapForVersion;
|
|
12
|
+
encode(text: string | EncodeResult | Uint8Array, options?: {
|
|
13
|
+
dictVersion?: number;
|
|
14
|
+
}): Promise<EncodeResult>;
|
|
15
|
+
decode(data: Uint8Array | string): Promise<string>;
|
|
16
|
+
}
|