@bigdreamsweb3/wordbin 1.0.3 → 1.0.5

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/README.md CHANGED
@@ -36,15 +36,27 @@ import { WordBin } from "@bigdreamsweb3/wordbin";
36
36
  // Use latest dictionary (v1 bundled, v2 if built)
37
37
  const wb = await WordBin.create();
38
38
 
39
- const phrase = "abandon ability able about above";
39
+ const phrase =
40
+ "pet either learn purse candy leader craft undo spoil forum slot spirit";
40
41
  const encoded = await wb.encode(phrase);
41
42
 
42
- console.log("Base64 payload:", encoded.encodedBase64);
43
+ console.log("Base64 payload:", encoded.payload);
44
+ // → Base64 payload: Aru6lPEGao2lRWajTRYITVtmNVVD8BWvHGhOtBplWKaJmQ==
45
+
46
+ console.log("Dictionary Version used (header byte):", encoded.dictVersion);
47
+ // → Dictionary Version used (header byte):: 2
48
+
43
49
  console.log("Encoded bytes:", encoded.encodedBytes);
50
+ // → Base64 payload: Encoded bytes: 34
51
+
44
52
  console.log("Original bytes:", encoded.originalBytes);
53
+ // → Original bytes: 70
54
+
55
+ console.log("Bytes saved:", encoded.bytesSaved);
56
+ // → Bytes saved: 36
45
57
 
46
58
  const decoded = await wb.decode(encoded.encoded);
47
- console.log("Decoded:", decoded); // → "abandon ability able about above"
59
+ console.log("Decoded:", decoded); // → "pet either learn purse candy leader craft undo spoil forum slot spirit"
48
60
  ```
49
61
 
50
62
  ### Browser Example
package/dist/core.d.ts CHANGED
@@ -7,10 +7,13 @@ export declare class WordBin {
7
7
  private log;
8
8
  static createFromWords(words: string[]): Promise<WordBin>;
9
9
  static createFromJson(dictJson: WordBinDictionary): Promise<WordBin>;
10
- static create(): Promise<WordBin>;
10
+ static create(options?: {
11
+ debug?: boolean;
12
+ }): Promise<WordBin>;
11
13
  private getReverseMapForVersion;
12
14
  encode(text: string | EncodeResult | Uint8Array, options?: {
13
15
  dictVersion?: number;
14
16
  }): Promise<EncodeResult>;
15
17
  decode(data: Uint8Array | string): Promise<string>;
18
+ private tryDecode;
16
19
  }
package/dist/index.mjs CHANGED
@@ -82,7 +82,6 @@ async function loadLatestDictionary() {
82
82
  return loadDictionaryByVersion(latestVersion);
83
83
  }
84
84
  class WordBin {
85
- // private debug: boolean;
86
85
  constructor(initialDict, options) {
87
86
  this.primaryDictVersion = initialDict?.version ?? 2;
88
87
  this.log = options?.debug ? (...args) => console.log("[WordBin]", ...args) : () => {
@@ -96,9 +95,9 @@ class WordBin {
96
95
  static async createFromJson(dictJson) {
97
96
  return new WordBin(dictJson);
98
97
  }
99
- static async create() {
98
+ static async create(options) {
100
99
  const latestDict = await loadLatestDictionary();
101
- return new WordBin(latestDict);
100
+ return new WordBin(latestDict, options);
102
101
  }
103
102
  async getReverseMapForVersion(version) {
104
103
  const dict = await loadDictionaryByVersion(version);
@@ -116,6 +115,7 @@ class WordBin {
116
115
  if (!textStr.trim()) {
117
116
  return {
118
117
  originalText: "",
118
+ dictVersion: 0,
119
119
  encoded: new Uint8Array(0),
120
120
  payload: "",
121
121
  encodedBase64: "",
@@ -129,12 +129,9 @@ class WordBin {
129
129
  this.log(`[encode] Input words (${words.length}):`, words);
130
130
  const useVersion = options.dictVersion ?? this.primaryDictVersion;
131
131
  this.log(`[encode] Using dictionary version: ${useVersion}`);
132
- const header = new Uint8Array([MAGIC[0], MAGIC[1], useVersion]);
132
+ const header = new Uint8Array([useVersion]);
133
133
  this.log(`[encode] Header bytes: [${[...header].join(", ")}]`);
134
134
  this.log(`[encode] Header hex: ${toHex(header)}`);
135
- this.log(
136
- `[encode] Header as text (non-printable chars expected): "${new TextDecoder().decode(header)}"`
137
- );
138
135
  const chunks = [header];
139
136
  const reverseMap = await this.getReverseMapForVersion(useVersion);
140
137
  this.log(`[encode] Reverse map loaded — size: ${reverseMap.size} entries`);
@@ -182,6 +179,7 @@ class WordBin {
182
179
  this.log(`[encode] Base64 starts with: ${base64Result.slice(0, 12)}...`);
183
180
  return {
184
181
  originalText: textStr,
182
+ dictVersion: result[0],
185
183
  encoded: result,
186
184
  payload: base64Result,
187
185
  encodedBase64: base64Result,
@@ -194,53 +192,115 @@ class WordBin {
194
192
  async decode(data) {
195
193
  let buffer;
196
194
  if (typeof data === "string") {
195
+ this.log(
196
+ `[decode] Input is base64 string: "${data.substring(0, 20)}..."`
197
+ );
197
198
  buffer = fromBase64(data);
199
+ this.log(`[decode] Decoded to ${buffer.length} bytes`);
198
200
  } else {
199
201
  buffer = data;
202
+ this.log(`[decode] Input is Uint8Array with ${buffer.length} bytes`);
200
203
  }
201
- if (buffer.length < 3) {
204
+ this.log(`[decode] Full buffer hex: ${toHex(buffer)}`);
205
+ this.log(
206
+ `[decode] First 16 bytes: [${[...buffer.subarray(0, Math.min(16, buffer.length))].join(", ")}]`
207
+ );
208
+ if (buffer.length < 1) {
202
209
  throw new Error("Data too short");
203
210
  }
204
- if (buffer[0] !== MAGIC[0] || buffer[1] !== MAGIC[1]) {
205
- throw new Error("Invalid magic bytes");
211
+ const version = buffer[0];
212
+ this.log(`[decode] Dictionary version from header: ${version}`);
213
+ if (version < 1 || version > 100) {
214
+ this.log(`[decode] Warning: unusual dictionary version ${version}`);
206
215
  }
207
- const version = buffer[2];
208
- let pos = 3;
216
+ let pos = 1;
217
+ this.log(`[decode] Starting decode at position ${pos}`);
209
218
  const reverseMap = await this.getReverseMapForVersion(version);
219
+ this.log(
220
+ `[decode] Reverse map loaded for v${version} — size: ${reverseMap.size} entries`
221
+ );
222
+ this.log(`[decode] ===== STARTING DECODE LOOP =====`);
210
223
  const result = [];
211
- while (pos < buffer.length) {
212
- let matched = false;
213
- if (buffer[pos] === LITERAL) {
214
- const { value: byteLen, bytesRead } = decodeVarint(buffer, pos + 1);
215
- const start = pos + 1 + bytesRead;
216
- const end = start + byteLen;
217
- if (end > buffer.length) {
218
- throw new Error("Truncated literal block");
219
- }
220
- const word = utf8Decode(buffer.subarray(start, end));
221
- result.push(word);
222
- pos = end;
223
- matched = true;
224
+ const decoded = this.tryDecode(pos, buffer, reverseMap, result, 0);
225
+ if (decoded === null) {
226
+ throw new Error(
227
+ "No valid decode path found possible corruption or dictionary mismatch"
228
+ );
229
+ }
230
+ this.log(`
231
+ [decode] ===== DECODE COMPLETE =====`);
232
+ this.log(`[decode] Total words decoded: ${result.length}`);
233
+ this.log(`[decode] Final result: "${decoded}"`);
234
+ return decoded;
235
+ }
236
+ tryDecode(pos, buffer, reverseMap, result, depth) {
237
+ const indent = " ".repeat(depth);
238
+ this.log(`${indent}[tryDecode] At position ${pos} (depth ${depth})`);
239
+ if (pos === buffer.length) {
240
+ this.log(`${indent}[tryDecode] Reached end successfully`);
241
+ return result.join(" ");
242
+ }
243
+ const previewLen = Math.min(8, buffer.length - pos);
244
+ const preview = [...buffer.subarray(pos, pos + previewLen)].map((b) => `0x${b.toString(16).padStart(2, "0")}`).join(" ");
245
+ this.log(`${indent}[tryDecode] Next ${previewLen} bytes: ${preview}`);
246
+ if (buffer[pos] === LITERAL) {
247
+ this.log(
248
+ `${indent}[tryDecode] Found LITERAL marker (0x${LITERAL.toString(16)})`
249
+ );
250
+ const { value: byteLen, bytesRead } = decodeVarint(buffer, pos + 1);
251
+ this.log(
252
+ `${indent}[tryDecode] Varint: value=${byteLen}, bytesRead=${bytesRead}`
253
+ );
254
+ const start = pos + 1 + bytesRead;
255
+ const end = start + byteLen;
256
+ this.log(
257
+ `${indent}[tryDecode] Literal range: [${start}..${end}) (${byteLen} bytes)`
258
+ );
259
+ if (end > buffer.length) {
260
+ this.log(`${indent}[tryDecode] Truncated literal — failing path`);
261
+ return null;
224
262
  }
225
- if (!matched) {
226
- for (const len of [4, 3, 2]) {
227
- if (pos + len > buffer.length) continue;
228
- const slice = buffer.subarray(pos, pos + len);
229
- const key = toHex(slice);
230
- if (reverseMap.has(key)) {
231
- result.push(reverseMap.get(key));
232
- pos += len;
233
- matched = true;
234
- break;
235
- }
236
- }
263
+ const literalBytes = buffer.subarray(start, end);
264
+ const word = utf8Decode(literalBytes);
265
+ this.log(`${indent}[tryDecode] Decoded literal: "${word}"`);
266
+ result.push(word);
267
+ const res = this.tryDecode(end, buffer, reverseMap, result, depth + 1);
268
+ if (res !== null) return res;
269
+ result.pop();
270
+ this.log(`${indent}[tryDecode] Backtracking from literal`);
271
+ return null;
272
+ }
273
+ for (const len of [4, 3, 2]) {
274
+ if (pos + len > buffer.length) {
275
+ this.log(`${indent}[tryDecode] Skipping ${len}-byte (would exceed)`);
276
+ continue;
237
277
  }
238
- if (!matched) {
239
- result.push(`[??:${buffer[pos].toString(16).padStart(2, "0")}]`);
240
- pos += 1;
278
+ const slice = buffer.subarray(pos, pos + len);
279
+ const key = toHex(slice);
280
+ const keyBytes = [...slice].map((b) => `0x${b.toString(16).padStart(2, "0")}`).join(" ");
281
+ this.log(
282
+ `${indent}[tryDecode] Trying ${len}-byte: [${keyBytes}] hex=${key}`
283
+ );
284
+ if (reverseMap.has(key)) {
285
+ const word = reverseMap.get(key);
286
+ this.log(`${indent}[tryDecode] Match: "${word}" (ID: ${key})`);
287
+ result.push(word);
288
+ const res = this.tryDecode(
289
+ pos + len,
290
+ buffer,
291
+ reverseMap,
292
+ result,
293
+ depth + 1
294
+ );
295
+ if (res !== null) return res;
296
+ result.pop();
297
+ this.log(`${indent}[tryDecode] Backtracking from "${word}"`);
298
+ } else {
299
+ this.log(`${indent}[tryDecode] No match for ${key}`);
241
300
  }
242
301
  }
243
- return result.join(" ");
302
+ this.log(`${indent}[tryDecode] No valid branches — failing path`);
303
+ return null;
244
304
  }
245
305
  }
246
306
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/constants.ts","../src/dictionary-loader.ts","../src/core.ts"],"sourcesContent":["// wordbin\\src\\constants.ts\r\nexport const MAGIC = new Uint8Array([87, 66]) // 'W''B'\r\nexport const LITERAL = 0xff\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { fileURLToPath } from \"url\";\r\nimport type { WordBinDictionary } from \"./types.js\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n// 1️⃣ Bundled dictionaries inside the package (dist/data)\r\nconst PACKAGE_DATA_DIR = path.join(__dirname, \"data\");\r\n\r\n// 2️⃣ User project dictionaries (built via CLI)\r\nconst LOCAL_DATA_DIR = path.join(process.cwd(), \"data\");\r\n\r\n/**\r\n * Get all dictionary directories that exist\r\n * Priority: LOCAL first, then PACKAGE fallback\r\n */\r\nasync function getExistingDataDirs(): Promise<string[]> {\r\n const dirs: string[] = [];\r\n\r\n try {\r\n await fs.access(LOCAL_DATA_DIR);\r\n dirs.push(LOCAL_DATA_DIR);\r\n } catch {}\r\n\r\n try {\r\n await fs.access(PACKAGE_DATA_DIR);\r\n dirs.push(PACKAGE_DATA_DIR);\r\n } catch {}\r\n\r\n return dirs;\r\n}\r\n\r\n/**\r\n * Scan all available dictionary versions from all data dirs\r\n */\r\nexport async function getAllAvailableDictionaryVersions(): Promise<number[]> {\r\n const dirs = await getExistingDataDirs();\r\n const versions = new Set<number>();\r\n\r\n for (const dir of dirs) {\r\n try {\r\n const files = await fs.readdir(dir);\r\n\r\n for (const file of files) {\r\n const match = file.match(/wordbin-v(\\d+)/i);\r\n if (match) {\r\n versions.add(parseInt(match[1], 10));\r\n }\r\n }\r\n } catch {\r\n // Ignore invalid dirs silently\r\n }\r\n }\r\n\r\n return Array.from(versions).sort((a, b) => a - b);\r\n}\r\n\r\n/**\r\n * Load a specific dictionary version\r\n * LOCAL dictionaries override PACKAGE ones\r\n */\r\nexport async function loadDictionaryByVersion(\r\n version: number,\r\n): Promise<WordBinDictionary> {\r\n const dirs = await getExistingDataDirs();\r\n\r\n if (dirs.length === 0) {\r\n throw new Error(\r\n `No dictionary directories found. Expected ./data or bundled package data.`,\r\n );\r\n }\r\n\r\n for (const dir of dirs) {\r\n const files = await fs.readdir(dir);\r\n\r\n const versionFile = files.find((f) =>\r\n f.match(new RegExp(`wordbin-v${version}(?:\\\\.|-)`, \"i\")),\r\n );\r\n\r\n if (versionFile) {\r\n const filePath = path.join(dir, versionFile);\r\n const data = await fs.readFile(filePath, \"utf-8\");\r\n const dict = JSON.parse(data) as WordBinDictionary;\r\n\r\n if (dict.version !== version) {\r\n throw new Error(\r\n `Version mismatch: file ${versionFile} claims v${dict.version} but expected v${version}`,\r\n );\r\n }\r\n\r\n return dict;\r\n }\r\n }\r\n\r\n const available = await getAllAvailableDictionaryVersions();\r\n\r\n throw new Error(\r\n `Dictionary version ${version} not found. Available versions: ${available.join(\", \")}`,\r\n );\r\n}\r\n\r\n/**\r\n * Load the latest available dictionary version\r\n */\r\nexport async function loadLatestDictionary(): Promise<WordBinDictionary> {\r\n const versions = await getAllAvailableDictionaryVersions();\r\n\r\n if (versions.length === 0) {\r\n throw new Error(\r\n `No dictionary files found. Run \"npx wordbin build\" or use bundled v1.`,\r\n );\r\n }\r\n\r\n const latestVersion = Math.max(...versions);\r\n\r\n console.log(\r\n `Loading latest dictionary: v${latestVersion} (available: ${versions.join(\", \")})`,\r\n );\r\n\r\n return loadDictionaryByVersion(latestVersion);\r\n}\r\n\r\n/**\r\n * Check if a specific version exists\r\n */\r\nexport async function hasDictionaryVersion(version: number): Promise<boolean> {\r\n const versions = await getAllAvailableDictionaryVersions();\r\n return versions.includes(version);\r\n}\r\n","import { MAGIC, LITERAL } from \"./constants.js\";\r\nimport { generateWordId } from \"./core/id.js\";\r\nimport {\r\n toHex,\r\n toBase64,\r\n fromBase64,\r\n encodeVarint,\r\n decodeVarint,\r\n utf8Encode,\r\n utf8Decode,\r\n} from \"./utils/buffer.js\";\r\nimport type { EncodeResult, WordBinDictionary } from \"./types\";\r\nimport { buildDictionary } from \"./dictionary.js\";\r\nimport {\r\n loadDictionaryByVersion,\r\n loadLatestDictionary,\r\n} from \"./dictionary-loader.js\";\r\n\r\nexport class WordBin {\r\n private primaryDictVersion: number;\r\n // private debug: boolean;\r\n\r\n constructor(initialDict?: WordBinDictionary, options?: { debug?: boolean }) {\r\n this.primaryDictVersion = initialDict?.version ?? 2;\r\n this.log = options?.debug\r\n ? (...args) => console.log(\"[WordBin]\", ...args)\r\n : () => {};\r\n }\r\n\r\n private log: (...args: any[]) => void;\r\n\r\n static async createFromWords(words: string[]): Promise<WordBin> {\r\n console.warn(\"Building dictionary from scratch – consider pre-built files\");\r\n const dict = await buildDictionary(words);\r\n return new WordBin(dict);\r\n }\r\n\r\n static async createFromJson(dictJson: WordBinDictionary): Promise<WordBin> {\r\n return new WordBin(dictJson);\r\n }\r\n\r\n static async create(): Promise<WordBin> {\r\n const latestDict = await loadLatestDictionary();\r\n return new WordBin(latestDict);\r\n }\r\n\r\n private async getReverseMapForVersion(\r\n version: number,\r\n ): Promise<Map<string, string>> {\r\n const dict = await loadDictionaryByVersion(version);\r\n const reverseMap = new Map<string, string>();\r\n for (const [hex, words] of Object.entries(dict.words)) {\r\n if (words.length > 0) reverseMap.set(hex, words[0]);\r\n }\r\n return reverseMap;\r\n }\r\n\r\n async encode(\r\n text: string | EncodeResult | Uint8Array,\r\n options: { dictVersion?: number } = {},\r\n ): Promise<EncodeResult> {\r\n let textStr: string;\r\n if (typeof text === \"string\") textStr = text;\r\n else if (text instanceof Uint8Array) textStr = toBase64(text);\r\n else textStr = text.encodedBase64;\r\n\r\n if (!textStr.trim()) {\r\n return {\r\n originalText: \"\",\r\n encoded: new Uint8Array(0),\r\n payload: \"\",\r\n encodedBase64: \"\",\r\n originalBytes: 0,\r\n encodedBytes: 0,\r\n bytesSaved: 0,\r\n ratioPercent: 100,\r\n };\r\n }\r\n\r\n const words = textStr.split(/\\s+/).filter(Boolean);\r\n this.log(`[encode] Input words (${words.length}):`, words);\r\n\r\n const useVersion = options.dictVersion ?? this.primaryDictVersion;\r\n this.log(`[encode] Using dictionary version: ${useVersion}`);\r\n\r\n // ──────────────────────────────────────────────\r\n // Header creation\r\n // ──────────────────────────────────────────────\r\n const header = new Uint8Array([MAGIC[0], MAGIC[1], useVersion]);\r\n this.log(`[encode] Header bytes: [${[...header].join(\", \")}]`);\r\n this.log(`[encode] Header hex: ${toHex(header)}`);\r\n this.log(\r\n `[encode] Header as text (non-printable chars expected): \"${new TextDecoder().decode(header)}\"`,\r\n );\r\n\r\n const chunks: Uint8Array[] = [header];\r\n\r\n const reverseMap = await this.getReverseMapForVersion(useVersion);\r\n this.log(`[encode] Reverse map loaded — size: ${reverseMap.size} entries`);\r\n\r\n // ──────────────────────────────────────────────\r\n // Process each word → show ID mapping\r\n // ──────────────────────────────────────────────\r\n this.log(\"[encode] Word → ID mapping:\");\r\n\r\n for (const w of words) {\r\n const id = await generateWordId(w); // Uint8Array (usually 2–4 bytes)\r\n const key = toHex(id); // hex string for lookup\r\n\r\n this.log(` \"${w}\" → ID bytes: [${[...id].join(\", \")}] | hex: ${key}`);\r\n\r\n if (reverseMap.has(key)) {\r\n const mappedWord = reverseMap.get(key);\r\n this.log(` → Found in dictionary → using ${id.length}-byte ID`);\r\n chunks.push(id);\r\n } else {\r\n const utf8 = utf8Encode(w);\r\n const lenVarint = encodeVarint(utf8.length);\r\n this.log(` → NOT in dictionary → literal mode`);\r\n this.log(\r\n ` Literal length varint bytes: [${[...lenVarint].join(\", \")}] (value = ${utf8.length})`,\r\n );\r\n this.log(` Word UTF-8 bytes length: ${utf8.length}`);\r\n\r\n const out = new Uint8Array(1 + lenVarint.length + utf8.length);\r\n out[0] = LITERAL;\r\n out.set(lenVarint, 1);\r\n out.set(utf8, 1 + lenVarint.length);\r\n\r\n this.log(` Literal chunk bytes: [${[...out].join(\", \")}]`);\r\n chunks.push(out);\r\n }\r\n }\r\n\r\n // ──────────────────────────────────────────────\r\n // Final assembly\r\n // ──────────────────────────────────────────────\r\n const totalLength = chunks.reduce((n, c) => n + c.length, 0);\r\n const result = new Uint8Array(totalLength);\r\n\r\n this.log(`[encode] Total encoded length: ${totalLength} bytes`);\r\n\r\n let off = 0;\r\n chunks.forEach((chunk, i) => {\r\n result.set(chunk, off);\r\n off += chunk.length;\r\n this.log(\r\n ` Chunk ${i}: ${chunk.length} bytes → offset ${off - chunk.length}`,\r\n );\r\n });\r\n\r\n this.log(\r\n `[encode] Final encoded bytes (first 32): [${[...result.subarray(0, Math.min(32, result.length))].join(\", \")}]`,\r\n );\r\n\r\n const originalBytes = new TextEncoder().encode(textStr).length;\r\n\r\n const base64Result = toBase64(result);\r\n this.log(`[encode] Base64 starts with: ${base64Result.slice(0, 12)}...`);\r\n\r\n return {\r\n originalText: textStr,\r\n encoded: result,\r\n payload: base64Result,\r\n encodedBase64: base64Result,\r\n originalBytes,\r\n encodedBytes: totalLength,\r\n bytesSaved: originalBytes - totalLength,\r\n ratioPercent:\r\n totalLength === 0\r\n ? 100\r\n : Math.round((totalLength / originalBytes) * 100),\r\n };\r\n }\r\n\r\n async decode(data: Uint8Array | string): Promise<string> {\r\n let buffer: Uint8Array;\r\n if (typeof data === \"string\") {\r\n buffer = fromBase64(data);\r\n } else {\r\n buffer = data;\r\n }\r\n\r\n if (buffer.length < 3) {\r\n throw new Error(\"Data too short\");\r\n }\r\n\r\n if (buffer[0] !== MAGIC[0] || buffer[1] !== MAGIC[1]) {\r\n throw new Error(\"Invalid magic bytes\");\r\n }\r\n\r\n const version = buffer[2];\r\n let pos = 3; // start right after version byte\r\n\r\n const reverseMap = await this.getReverseMapForVersion(version);\r\n\r\n const result: string[] = [];\r\n\r\n while (pos < buffer.length) {\r\n let matched = false;\r\n\r\n // Literal block\r\n if (buffer[pos] === LITERAL) {\r\n const { value: byteLen, bytesRead } = decodeVarint(buffer, pos + 1);\r\n const start = pos + 1 + bytesRead;\r\n const end = start + byteLen;\r\n\r\n if (end > buffer.length) {\r\n throw new Error(\"Truncated literal block\");\r\n }\r\n\r\n const word = utf8Decode(buffer.subarray(start, end));\r\n result.push(word);\r\n pos = end;\r\n matched = true;\r\n }\r\n\r\n // Known word reference\r\n if (!matched) {\r\n for (const len of [4, 3, 2]) {\r\n if (pos + len > buffer.length) continue;\r\n const slice = buffer.subarray(pos, pos + len);\r\n const key = toHex(slice);\r\n\r\n if (reverseMap.has(key)) {\r\n result.push(reverseMap.get(key)!);\r\n pos += len;\r\n matched = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!matched) {\r\n result.push(`[??:${buffer[pos].toString(16).padStart(2, \"0\")}]`);\r\n pos += 1;\r\n }\r\n }\r\n\r\n return result.join(\" \");\r\n }\r\n}\r\n"],"names":["__filename","__dirname"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/constants.ts","../src/dictionary-loader.ts","../src/core.ts"],"sourcesContent":["// wordbin\\src\\constants.ts\r\nexport const MAGIC = new Uint8Array([87, 66]) // 'W''B'\r\nexport const LITERAL = 0xff\r\n","import fs from \"fs/promises\";\r\nimport path from \"path\";\r\nimport { fileURLToPath } from \"url\";\r\nimport type { WordBinDictionary } from \"./types.js\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n// 1️⃣ Bundled dictionaries inside the package (dist/data)\r\nconst PACKAGE_DATA_DIR = path.join(__dirname, \"data\");\r\n\r\n// 2️⃣ User project dictionaries (built via CLI)\r\nconst LOCAL_DATA_DIR = path.join(process.cwd(), \"data\");\r\n\r\n/**\r\n * Get all dictionary directories that exist\r\n * Priority: LOCAL first, then PACKAGE fallback\r\n */\r\nasync function getExistingDataDirs(): Promise<string[]> {\r\n const dirs: string[] = [];\r\n\r\n try {\r\n await fs.access(LOCAL_DATA_DIR);\r\n dirs.push(LOCAL_DATA_DIR);\r\n } catch {}\r\n\r\n try {\r\n await fs.access(PACKAGE_DATA_DIR);\r\n dirs.push(PACKAGE_DATA_DIR);\r\n } catch {}\r\n\r\n return dirs;\r\n}\r\n\r\n/**\r\n * Scan all available dictionary versions from all data dirs\r\n */\r\nexport async function getAllAvailableDictionaryVersions(): Promise<number[]> {\r\n const dirs = await getExistingDataDirs();\r\n const versions = new Set<number>();\r\n\r\n for (const dir of dirs) {\r\n try {\r\n const files = await fs.readdir(dir);\r\n\r\n for (const file of files) {\r\n const match = file.match(/wordbin-v(\\d+)/i);\r\n if (match) {\r\n versions.add(parseInt(match[1], 10));\r\n }\r\n }\r\n } catch {\r\n // Ignore invalid dirs silently\r\n }\r\n }\r\n\r\n return Array.from(versions).sort((a, b) => a - b);\r\n}\r\n\r\n/**\r\n * Load a specific dictionary version\r\n * LOCAL dictionaries override PACKAGE ones\r\n */\r\nexport async function loadDictionaryByVersion(\r\n version: number,\r\n): Promise<WordBinDictionary> {\r\n const dirs = await getExistingDataDirs();\r\n\r\n if (dirs.length === 0) {\r\n throw new Error(\r\n `No dictionary directories found. Expected ./data or bundled package data.`,\r\n );\r\n }\r\n\r\n for (const dir of dirs) {\r\n const files = await fs.readdir(dir);\r\n\r\n const versionFile = files.find((f) =>\r\n f.match(new RegExp(`wordbin-v${version}(?:\\\\.|-)`, \"i\")),\r\n );\r\n\r\n if (versionFile) {\r\n const filePath = path.join(dir, versionFile);\r\n const data = await fs.readFile(filePath, \"utf-8\");\r\n const dict = JSON.parse(data) as WordBinDictionary;\r\n\r\n if (dict.version !== version) {\r\n throw new Error(\r\n `Version mismatch: file ${versionFile} claims v${dict.version} but expected v${version}`,\r\n );\r\n }\r\n\r\n return dict;\r\n }\r\n }\r\n\r\n const available = await getAllAvailableDictionaryVersions();\r\n\r\n throw new Error(\r\n `Dictionary version ${version} not found. Available versions: ${available.join(\", \")}`,\r\n );\r\n}\r\n\r\n/**\r\n * Load the latest available dictionary version\r\n */\r\nexport async function loadLatestDictionary(): Promise<WordBinDictionary> {\r\n const versions = await getAllAvailableDictionaryVersions();\r\n\r\n if (versions.length === 0) {\r\n throw new Error(\r\n `No dictionary files found. Run \"npx wordbin build\" or use bundled v1.`,\r\n );\r\n }\r\n\r\n const latestVersion = Math.max(...versions);\r\n\r\n console.log(\r\n `Loading latest dictionary: v${latestVersion} (available: ${versions.join(\", \")})`,\r\n );\r\n\r\n return loadDictionaryByVersion(latestVersion);\r\n}\r\n\r\n/**\r\n * Check if a specific version exists\r\n */\r\nexport async function hasDictionaryVersion(version: number): Promise<boolean> {\r\n const versions = await getAllAvailableDictionaryVersions();\r\n return versions.includes(version);\r\n}\r\n","import { LITERAL } from \"./constants.js\";\r\nimport { generateWordId } from \"./core/id.js\";\r\nimport {\r\n toHex,\r\n toBase64,\r\n fromBase64,\r\n encodeVarint,\r\n decodeVarint,\r\n utf8Encode,\r\n utf8Decode,\r\n} from \"./utils/buffer.js\";\r\nimport type { EncodeResult, WordBinDictionary } from \"./types\";\r\nimport { buildDictionary } from \"./dictionary.js\";\r\nimport {\r\n loadDictionaryByVersion,\r\n loadLatestDictionary,\r\n} from \"./dictionary-loader.js\";\r\n\r\nexport class WordBin {\r\n private primaryDictVersion: number;\r\n\r\n constructor(initialDict?: WordBinDictionary, options?: { debug?: boolean }) {\r\n this.primaryDictVersion = initialDict?.version ?? 2;\r\n this.log = options?.debug\r\n ? (...args) => console.log(\"[WordBin]\", ...args)\r\n : () => {};\r\n }\r\n\r\n private log: (...args: any[]) => void;\r\n\r\n static async createFromWords(words: string[]): Promise<WordBin> {\r\n console.warn(\"Building dictionary from scratch – consider pre-built files\");\r\n const dict = await buildDictionary(words);\r\n return new WordBin(dict);\r\n }\r\n\r\n static async createFromJson(dictJson: WordBinDictionary): Promise<WordBin> {\r\n return new WordBin(dictJson);\r\n }\r\n\r\n static async create(options?: { debug?: boolean }): Promise<WordBin> {\r\n const latestDict = await loadLatestDictionary();\r\n return new WordBin(latestDict, options);\r\n }\r\n\r\n private async getReverseMapForVersion(\r\n version: number,\r\n ): Promise<Map<string, string>> {\r\n const dict = await loadDictionaryByVersion(version);\r\n const reverseMap = new Map<string, string>();\r\n for (const [hex, words] of Object.entries(dict.words)) {\r\n if (words.length > 0) reverseMap.set(hex, words[0]);\r\n }\r\n return reverseMap;\r\n }\r\n\r\n async encode(\r\n text: string | EncodeResult | Uint8Array,\r\n options: { dictVersion?: number } = {},\r\n ): Promise<EncodeResult> {\r\n let textStr: string;\r\n if (typeof text === \"string\") textStr = text;\r\n else if (text instanceof Uint8Array) textStr = toBase64(text);\r\n else textStr = text.encodedBase64;\r\n\r\n if (!textStr.trim()) {\r\n return {\r\n originalText: \"\",\r\n dictVersion: 0,\r\n encoded: new Uint8Array(0),\r\n payload: \"\",\r\n encodedBase64: \"\",\r\n originalBytes: 0,\r\n encodedBytes: 0,\r\n bytesSaved: 0,\r\n ratioPercent: 100,\r\n };\r\n }\r\n\r\n const words = textStr.split(/\\s+/).filter(Boolean);\r\n this.log(`[encode] Input words (${words.length}):`, words);\r\n\r\n const useVersion = options.dictVersion ?? this.primaryDictVersion;\r\n this.log(`[encode] Using dictionary version: ${useVersion}`);\r\n\r\n // ──────────────────────────────────────────────\r\n // Header: just the version byte (no magic bytes)\r\n // ──────────────────────────────────────────────\r\n const header = new Uint8Array([useVersion]);\r\n\r\n this.log(`[encode] Header bytes: [${[...header].join(\", \")}]`);\r\n this.log(`[encode] Header hex: ${toHex(header)}`);\r\n\r\n const chunks: Uint8Array[] = [header];\r\n\r\n const reverseMap = await this.getReverseMapForVersion(useVersion);\r\n this.log(`[encode] Reverse map loaded — size: ${reverseMap.size} entries`);\r\n\r\n // ──────────────────────────────────────────────\r\n // Process each word\r\n // ──────────────────────────────────────────────\r\n this.log(\"[encode] Word → ID mapping:\");\r\n\r\n for (const w of words) {\r\n const id = await generateWordId(w);\r\n const key = toHex(id);\r\n\r\n this.log(` \"${w}\" → ID bytes: [${[...id].join(\", \")}] | hex: ${key}`);\r\n\r\n if (reverseMap.has(key)) {\r\n const mappedWord = reverseMap.get(key);\r\n this.log(` → Found in dictionary → using ${id.length}-byte ID`);\r\n chunks.push(id);\r\n } else {\r\n const utf8 = utf8Encode(w);\r\n const lenVarint = encodeVarint(utf8.length);\r\n this.log(` → NOT in dictionary → literal mode`);\r\n this.log(\r\n ` Literal length varint bytes: [${[...lenVarint].join(\", \")}] (value = ${utf8.length})`,\r\n );\r\n this.log(` Word UTF-8 bytes length: ${utf8.length}`);\r\n\r\n const out = new Uint8Array(1 + lenVarint.length + utf8.length);\r\n out[0] = LITERAL;\r\n out.set(lenVarint, 1);\r\n out.set(utf8, 1 + lenVarint.length);\r\n\r\n this.log(` Literal chunk bytes: [${[...out].join(\", \")}]`);\r\n chunks.push(out);\r\n }\r\n }\r\n\r\n // ──────────────────────────────────────────────\r\n // Final assembly\r\n // ──────────────────────────────────────────────\r\n const totalLength = chunks.reduce((n, c) => n + c.length, 0);\r\n const result = new Uint8Array(totalLength);\r\n\r\n this.log(`[encode] Total encoded length: ${totalLength} bytes`);\r\n\r\n let off = 0;\r\n chunks.forEach((chunk, i) => {\r\n result.set(chunk, off);\r\n off += chunk.length;\r\n this.log(\r\n ` Chunk ${i}: ${chunk.length} bytes → offset ${off - chunk.length}`,\r\n );\r\n });\r\n\r\n this.log(\r\n `[encode] Final encoded bytes (first 32): [${[...result.subarray(0, Math.min(32, result.length))].join(\", \")}]`,\r\n );\r\n\r\n const originalBytes = new TextEncoder().encode(textStr).length;\r\n\r\n const base64Result = toBase64(result);\r\n this.log(`[encode] Base64 starts with: ${base64Result.slice(0, 12)}...`);\r\n\r\n return {\r\n originalText: textStr,\r\n dictVersion: result[0],\r\n encoded: result,\r\n payload: base64Result,\r\n encodedBase64: base64Result,\r\n originalBytes,\r\n encodedBytes: totalLength,\r\n bytesSaved: originalBytes - totalLength,\r\n ratioPercent:\r\n totalLength === 0\r\n ? 100\r\n : Math.round((totalLength / originalBytes) * 100),\r\n };\r\n }\r\n\r\n async decode(data: Uint8Array | string): Promise<string> {\r\n let buffer: Uint8Array;\r\n if (typeof data === \"string\") {\r\n this.log(\r\n `[decode] Input is base64 string: \"${data.substring(0, 20)}...\"`,\r\n );\r\n buffer = fromBase64(data);\r\n this.log(`[decode] Decoded to ${buffer.length} bytes`);\r\n } else {\r\n buffer = data;\r\n this.log(`[decode] Input is Uint8Array with ${buffer.length} bytes`);\r\n }\r\n\r\n this.log(`[decode] Full buffer hex: ${toHex(buffer)}`);\r\n this.log(\r\n `[decode] First 16 bytes: [${[...buffer.subarray(0, Math.min(16, buffer.length))].join(\", \")}]`,\r\n );\r\n\r\n if (buffer.length < 1) {\r\n throw new Error(\"Data too short\");\r\n }\r\n\r\n const version = buffer[0];\r\n this.log(`[decode] Dictionary version from header: ${version}`);\r\n\r\n // Optional: basic sanity check (you can adjust or remove)\r\n if (version < 1 || version > 100) {\r\n this.log(`[decode] Warning: unusual dictionary version ${version}`);\r\n // You can throw here if you want strict validation:\r\n // throw new Error(`Unreasonable dictionary version: ${version}`);\r\n }\r\n\r\n let pos = 1; // payload starts right after the version byte\r\n this.log(`[decode] Starting decode at position ${pos}`);\r\n\r\n const reverseMap = await this.getReverseMapForVersion(version);\r\n this.log(\r\n `[decode] Reverse map loaded for v${version} — size: ${reverseMap.size} entries`,\r\n );\r\n\r\n this.log(`[decode] ===== STARTING DECODE LOOP =====`);\r\n\r\n const result: string[] = [];\r\n const decoded = this.tryDecode(pos, buffer, reverseMap, result, 0);\r\n\r\n if (decoded === null) {\r\n throw new Error(\r\n \"No valid decode path found — possible corruption or dictionary mismatch\",\r\n );\r\n }\r\n\r\n this.log(`\\n[decode] ===== DECODE COMPLETE =====`);\r\n this.log(`[decode] Total words decoded: ${result.length}`);\r\n this.log(`[decode] Final result: \"${decoded}\"`);\r\n\r\n return decoded;\r\n }\r\n\r\n private tryDecode(\r\n pos: number,\r\n buffer: Uint8Array,\r\n reverseMap: Map<string, string>,\r\n result: string[],\r\n depth: number,\r\n ): string | null {\r\n const indent = \" \".repeat(depth);\r\n this.log(`${indent}[tryDecode] At position ${pos} (depth ${depth})`);\r\n\r\n if (pos === buffer.length) {\r\n this.log(`${indent}[tryDecode] Reached end successfully`);\r\n return result.join(\" \");\r\n }\r\n\r\n const previewLen = Math.min(8, buffer.length - pos);\r\n const preview = [...buffer.subarray(pos, pos + previewLen)]\r\n .map((b) => `0x${b.toString(16).padStart(2, \"0\")}`)\r\n .join(\" \");\r\n this.log(`${indent}[tryDecode] Next ${previewLen} bytes: ${preview}`);\r\n\r\n // Try literal first\r\n if (buffer[pos] === LITERAL) {\r\n this.log(\r\n `${indent}[tryDecode] Found LITERAL marker (0x${LITERAL.toString(16)})`,\r\n );\r\n\r\n const { value: byteLen, bytesRead } = decodeVarint(buffer, pos + 1);\r\n this.log(\r\n `${indent}[tryDecode] Varint: value=${byteLen}, bytesRead=${bytesRead}`,\r\n );\r\n\r\n const start = pos + 1 + bytesRead;\r\n const end = start + byteLen;\r\n this.log(\r\n `${indent}[tryDecode] Literal range: [${start}..${end}) (${byteLen} bytes)`,\r\n );\r\n\r\n if (end > buffer.length) {\r\n this.log(`${indent}[tryDecode] Truncated literal — failing path`);\r\n return null;\r\n }\r\n\r\n const literalBytes = buffer.subarray(start, end);\r\n const word = utf8Decode(literalBytes);\r\n this.log(`${indent}[tryDecode] Decoded literal: \"${word}\"`);\r\n\r\n result.push(word);\r\n const res = this.tryDecode(end, buffer, reverseMap, result, depth + 1);\r\n if (res !== null) return res;\r\n result.pop();\r\n this.log(`${indent}[tryDecode] Backtracking from literal`);\r\n return null;\r\n }\r\n\r\n // Try dictionary matches (longest first)\r\n for (const len of [4, 3, 2]) {\r\n if (pos + len > buffer.length) {\r\n this.log(`${indent}[tryDecode] Skipping ${len}-byte (would exceed)`);\r\n continue;\r\n }\r\n\r\n const slice = buffer.subarray(pos, pos + len);\r\n const key = toHex(slice);\r\n const keyBytes = [...slice]\r\n .map((b) => `0x${b.toString(16).padStart(2, \"0\")}`)\r\n .join(\" \");\r\n\r\n this.log(\r\n `${indent}[tryDecode] Trying ${len}-byte: [${keyBytes}] hex=${key}`,\r\n );\r\n\r\n if (reverseMap.has(key)) {\r\n const word = reverseMap.get(key)!;\r\n this.log(`${indent}[tryDecode] Match: \"${word}\" (ID: ${key})`);\r\n\r\n result.push(word);\r\n const res = this.tryDecode(\r\n pos + len,\r\n buffer,\r\n reverseMap,\r\n result,\r\n depth + 1,\r\n );\r\n if (res !== null) return res;\r\n result.pop();\r\n this.log(`${indent}[tryDecode] Backtracking from \"${word}\"`);\r\n } else {\r\n this.log(`${indent}[tryDecode] No match for ${key}`);\r\n }\r\n }\r\n\r\n this.log(`${indent}[tryDecode] No valid branches — failing path`);\r\n return null;\r\n }\r\n}\r\n"],"names":["__filename","__dirname"],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -7,6 +7,7 @@ export interface EncodeResult {
7
7
  originalText: string;
8
8
  payload: string;
9
9
  encoded: Uint8Array;
10
+ dictVersion: number;
10
11
  encodedBase64: string;
11
12
  originalBytes: number;
12
13
  encodedBytes: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigdreamsweb3/wordbin",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "WordBin – Encode words & short text into tiny, reversible binary for storage, URLs, IoT, QR codes, metadata, blockchain, or Web3 apps.",
5
5
  "author": "Agbaka Daniel Ugonna <99cratson@gmail.com>",
6
6
  "license": "MIT",