text-compress 2.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.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -0
  3. package/dist/api/folder.d.ts +38 -0
  4. package/dist/api/folder.d.ts.map +1 -0
  5. package/dist/api/folder.js +50 -0
  6. package/dist/api/folder.js.map +1 -0
  7. package/dist/api/text.d.ts +30 -0
  8. package/dist/api/text.d.ts.map +1 -0
  9. package/dist/api/text.js +38 -0
  10. package/dist/api/text.js.map +1 -0
  11. package/dist/archive/collect.d.ts +26 -0
  12. package/dist/archive/collect.d.ts.map +1 -0
  13. package/dist/archive/collect.js +38 -0
  14. package/dist/archive/collect.js.map +1 -0
  15. package/dist/archive/format.d.ts +62 -0
  16. package/dist/archive/format.d.ts.map +1 -0
  17. package/dist/archive/format.js +143 -0
  18. package/dist/archive/format.js.map +1 -0
  19. package/dist/archive/types.d.ts +25 -0
  20. package/dist/archive/types.d.ts.map +1 -0
  21. package/dist/archive/types.js +10 -0
  22. package/dist/archive/types.js.map +1 -0
  23. package/dist/archive/unpack.d.ts +21 -0
  24. package/dist/archive/unpack.d.ts.map +1 -0
  25. package/dist/archive/unpack.js +41 -0
  26. package/dist/archive/unpack.js.map +1 -0
  27. package/dist/cli/analytics.d.ts +10 -0
  28. package/dist/cli/analytics.d.ts.map +1 -0
  29. package/dist/cli/analytics.js +22 -0
  30. package/dist/cli/analytics.js.map +1 -0
  31. package/dist/cli/args.d.ts +43 -0
  32. package/dist/cli/args.d.ts.map +1 -0
  33. package/dist/cli/args.js +152 -0
  34. package/dist/cli/args.js.map +1 -0
  35. package/dist/cli/commands/compress.d.ts +9 -0
  36. package/dist/cli/commands/compress.d.ts.map +1 -0
  37. package/dist/cli/commands/compress.js +62 -0
  38. package/dist/cli/commands/compress.js.map +1 -0
  39. package/dist/cli/commands/decompress.d.ts +9 -0
  40. package/dist/cli/commands/decompress.d.ts.map +1 -0
  41. package/dist/cli/commands/decompress.js +69 -0
  42. package/dist/cli/commands/decompress.js.map +1 -0
  43. package/dist/cli/detect.d.ts +25 -0
  44. package/dist/cli/detect.d.ts.map +1 -0
  45. package/dist/cli/detect.js +78 -0
  46. package/dist/cli/detect.js.map +1 -0
  47. package/dist/cli/main.d.ts +8 -0
  48. package/dist/cli/main.d.ts.map +1 -0
  49. package/dist/cli/main.js +74 -0
  50. package/dist/cli/main.js.map +1 -0
  51. package/dist/cli/output.d.ts +13 -0
  52. package/dist/cli/output.d.ts.map +1 -0
  53. package/dist/cli/output.js +26 -0
  54. package/dist/cli/output.js.map +1 -0
  55. package/dist/cli/paths.d.ts +13 -0
  56. package/dist/cli/paths.d.ts.map +1 -0
  57. package/dist/cli/paths.js +24 -0
  58. package/dist/cli/paths.js.map +1 -0
  59. package/dist/cli/usage.d.ts +8 -0
  60. package/dist/cli/usage.d.ts.map +1 -0
  61. package/dist/cli/usage.js +73 -0
  62. package/dist/cli/usage.js.map +1 -0
  63. package/dist/cli.d.ts +3 -0
  64. package/dist/cli.d.ts.map +1 -0
  65. package/dist/cli.js +10 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/compression/brotli.d.ts +43 -0
  68. package/dist/compression/brotli.d.ts.map +1 -0
  69. package/dist/compression/brotli.js +56 -0
  70. package/dist/compression/brotli.js.map +1 -0
  71. package/dist/crypto/password.d.ts +22 -0
  72. package/dist/crypto/password.d.ts.map +1 -0
  73. package/dist/crypto/password.js +62 -0
  74. package/dist/crypto/password.js.map +1 -0
  75. package/dist/encoding/base64.d.ts +17 -0
  76. package/dist/encoding/base64.d.ts.map +1 -0
  77. package/dist/encoding/base64.js +21 -0
  78. package/dist/encoding/base64.js.map +1 -0
  79. package/dist/encoding/index.d.ts +29 -0
  80. package/dist/encoding/index.d.ts.map +1 -0
  81. package/dist/encoding/index.js +47 -0
  82. package/dist/encoding/index.js.map +1 -0
  83. package/dist/encoding/z85.d.ts +64 -0
  84. package/dist/encoding/z85.d.ts.map +1 -0
  85. package/dist/encoding/z85.js +99 -0
  86. package/dist/encoding/z85.js.map +1 -0
  87. package/dist/fs/gitignore.d.ts +30 -0
  88. package/dist/fs/gitignore.d.ts.map +1 -0
  89. package/dist/fs/gitignore.js +104 -0
  90. package/dist/fs/gitignore.js.map +1 -0
  91. package/dist/fs/paths.d.ts +22 -0
  92. package/dist/fs/paths.d.ts.map +1 -0
  93. package/dist/fs/paths.js +55 -0
  94. package/dist/fs/paths.js.map +1 -0
  95. package/dist/fs/walk.d.ts +22 -0
  96. package/dist/fs/walk.d.ts.map +1 -0
  97. package/dist/fs/walk.js +49 -0
  98. package/dist/fs/walk.js.map +1 -0
  99. package/dist/index.d.ts +21 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +25 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/payload/tags.d.ts +60 -0
  104. package/dist/payload/tags.d.ts.map +1 -0
  105. package/dist/payload/tags.js +78 -0
  106. package/dist/payload/tags.js.map +1 -0
  107. package/dist/split/parts.d.ts +130 -0
  108. package/dist/split/parts.d.ts.map +1 -0
  109. package/dist/split/parts.js +290 -0
  110. package/dist/split/parts.js.map +1 -0
  111. package/dist/streaming/folder.d.ts +49 -0
  112. package/dist/streaming/folder.d.ts.map +1 -0
  113. package/dist/streaming/folder.js +220 -0
  114. package/dist/streaming/folder.js.map +1 -0
  115. package/dist/streaming.d.ts +16 -0
  116. package/dist/streaming.d.ts.map +1 -0
  117. package/dist/streaming.js +243 -0
  118. package/dist/streaming.js.map +1 -0
  119. package/dist/types.d.ts +18 -0
  120. package/dist/types.d.ts.map +1 -0
  121. package/dist/types.js +11 -0
  122. package/dist/types.js.map +1 -0
  123. package/package.json +60 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * @module streaming/folder
3
+ *
4
+ * Memory-efficient folder compression pipeline.
5
+ *
6
+ * Large directory trees may exceed available RAM if every file is loaded
7
+ * into a single buffer. This module streams each stage to disk:
8
+ *
9
+ * ```
10
+ * walk tree → temp archive file
11
+ * → stream Brotli → temp compressed file
12
+ * → stream encode → output .txt (possibly split)
13
+ * ```
14
+ *
15
+ * ## Pattern: staged pipeline with temp files
16
+ *
17
+ * Each stage reads from the previous stage's output file and writes to
18
+ * the next, keeping peak memory bounded by chunk buffer sizes rather than
19
+ * total archive size.
20
+ *
21
+ * ## Chunk sizes
22
+ *
23
+ * - `COPY_CHUNK` (1 MiB) — file content copied into the archive.
24
+ * - `ENCODE_READ_CHUNK` (3 MiB) — binary read buffer for Base64 streaming.
25
+ * Base64 encoding is applied per-chunk for `encoding === 64`; Z85 requires
26
+ * the full padded buffer and is loaded once (trade-off for correctness).
27
+ */
28
+ import { closeSync, createReadStream, createWriteStream, mkdtempSync, openSync, readFileSync, readSync, rmSync, statSync, writeFileSync, writeSync, } from "node:fs";
29
+ import { tmpdir } from "node:os";
30
+ import { join } from "node:path";
31
+ import { Readable } from "node:stream";
32
+ import { pipeline } from "node:stream/promises";
33
+ import { writeDirEntry, writeFileEntry } from "../archive/format.js";
34
+ import { createMaxQualityBrotliCompress } from "../compression/brotli.js";
35
+ import { encryptBuffer } from "../crypto/password.js";
36
+ import { encodeBase64 } from "../encoding/base64.js";
37
+ import { estimatedEncodedLength } from "../encoding/index.js";
38
+ import { encodeBase85 } from "../encoding/z85.js";
39
+ import { walkDirectory } from "../fs/walk.js";
40
+ import { TAG_FOLDER } from "../payload/tags.js";
41
+ import { createSplitChunkHeader, formatSplitOutputPath, resolveSplitChunkSize, } from "../split/parts.js";
42
+ /** Buffer size when copying file content into the archive. */
43
+ const COPY_CHUNK = 1024 * 1024;
44
+ /** Buffer size when reading compressed bytes for Base64 encoding. */
45
+ const ENCODE_READ_CHUNK = 3 * 1024 * 1024;
46
+ /**
47
+ * Depth-first walk that writes archive entries directly to a file.
48
+ *
49
+ * Same traversal order as `collectEntries`, but streams to disk.
50
+ */
51
+ function buildArchiveFile(rootDir, archivePath) {
52
+ const fd = openSync(archivePath, "w");
53
+ let fileCount = 0;
54
+ let dirCount = 0;
55
+ let originalBytes = 0;
56
+ try {
57
+ walkDirectory(rootDir, {
58
+ onDirectory: (_absDir, relDir) => {
59
+ writeDirEntry(fd, relDir);
60
+ dirCount++;
61
+ },
62
+ onFile: (abs, rel) => {
63
+ originalBytes += writeFileEntry(fd, rel, abs, COPY_CHUNK);
64
+ fileCount++;
65
+ },
66
+ });
67
+ }
68
+ finally {
69
+ closeSync(fd);
70
+ }
71
+ return {
72
+ fileCount,
73
+ dirCount,
74
+ originalBytes,
75
+ archiveBytes: statSync(archivePath).size,
76
+ };
77
+ }
78
+ /**
79
+ * Create a readable stream that prepends the folder tag byte before file bytes.
80
+ *
81
+ * Pattern: **prefix transform** — prepends metadata without copying the
82
+ * entire file into memory.
83
+ */
84
+ function prependTagStream(tag, filePath) {
85
+ const tagBuf = Buffer.from([tag]);
86
+ const file = createReadStream(filePath);
87
+ return Readable.from((async function* () {
88
+ yield tagBuf;
89
+ for await (const chunk of file) {
90
+ yield chunk;
91
+ }
92
+ })());
93
+ }
94
+ /**
95
+ * Stream Brotli-compress a file (with tag prefix) to another file.
96
+ */
97
+ async function brotliCompressFile(inputPath, outputPath) {
98
+ await pipeline(prependTagStream(TAG_FOLDER, inputPath), createMaxQualityBrotliCompress(statSync(inputPath).size + 1), createWriteStream(outputPath));
99
+ }
100
+ /** Open one numbered part file for split output. */
101
+ function openPart(outputPath, partIndex, totalParts) {
102
+ const path = formatSplitOutputPath(outputPath, partIndex, totalParts);
103
+ const fd = openSync(path, "w");
104
+ writeSync(fd, createSplitChunkHeader(partIndex, totalParts));
105
+ return { path, fd };
106
+ }
107
+ /**
108
+ * Stream-read a binary file and write encoded text to one or more output files.
109
+ *
110
+ * Handles optional character-based splitting across part files.
111
+ */
112
+ function encodeBinaryFileToTextFiles(inputPath, outputPath, encoding, split) {
113
+ const binaryBytes = statSync(inputPath).size;
114
+ const srcFd = openSync(inputPath, "r");
115
+ const readAndEncode = (writeEncoded) => {
116
+ if (encoding === 64) {
117
+ const buf = Buffer.alloc(ENCODE_READ_CHUNK);
118
+ let pos = 0;
119
+ while (pos < binaryBytes) {
120
+ const toRead = Math.min(buf.length, binaryBytes - pos);
121
+ const n = readSync(srcFd, buf, 0, toRead, pos);
122
+ if (n <= 0)
123
+ break;
124
+ writeEncoded(encodeBase64(buf.subarray(0, n)));
125
+ pos += n;
126
+ }
127
+ }
128
+ else {
129
+ const raw = Buffer.alloc(binaryBytes);
130
+ let pos = 0;
131
+ while (pos < binaryBytes) {
132
+ const n = readSync(srcFd, raw, pos, binaryBytes - pos, pos);
133
+ if (n <= 0)
134
+ break;
135
+ pos += n;
136
+ }
137
+ writeEncoded(encodeBase85(raw));
138
+ }
139
+ };
140
+ if (!split) {
141
+ const outFd = openSync(outputPath, "w");
142
+ try {
143
+ readAndEncode((text) => writeSync(outFd, text));
144
+ }
145
+ finally {
146
+ closeSync(srcFd);
147
+ closeSync(outFd);
148
+ }
149
+ return [outputPath];
150
+ }
151
+ const encodedLength = estimatedEncodedLength(binaryBytes, encoding);
152
+ const totalParts = Math.ceil(encodedLength / split);
153
+ const paths = [];
154
+ let partIndex = 1;
155
+ let part = openPart(outputPath, partIndex, totalParts);
156
+ paths.push(part.path);
157
+ let partChars = 0;
158
+ const flushPart = () => {
159
+ closeSync(part.fd);
160
+ if (partIndex < totalParts) {
161
+ partIndex++;
162
+ part = openPart(outputPath, partIndex, totalParts);
163
+ paths.push(part.path);
164
+ partChars = 0;
165
+ }
166
+ };
167
+ const writeEncoded = (text) => {
168
+ let offset = 0;
169
+ while (offset < text.length) {
170
+ const remaining = split - partChars;
171
+ if (remaining <= 0) {
172
+ flushPart();
173
+ continue;
174
+ }
175
+ const slice = text.slice(offset, offset + remaining);
176
+ writeSync(part.fd, slice);
177
+ partChars += slice.length;
178
+ offset += slice.length;
179
+ if (partChars >= split && offset < text.length)
180
+ flushPart();
181
+ }
182
+ };
183
+ try {
184
+ readAndEncode(writeEncoded);
185
+ }
186
+ finally {
187
+ closeSync(srcFd);
188
+ closeSync(part.fd);
189
+ }
190
+ return paths;
191
+ }
192
+ /**
193
+ * Compress a folder to encoded text file(s) using the streaming pipeline.
194
+ *
195
+ * Creates a temporary working directory that is always cleaned up in `finally`.
196
+ */
197
+ export async function compressFolderToPath(dirPath, outputPath, encoding = 64, split, password) {
198
+ const tempDir = mkdtempSync(join(tmpdir(), "text-compress-"));
199
+ const archivePath = join(tempDir, "archive.bin");
200
+ const compressedPath = join(tempDir, "compressed.bin");
201
+ try {
202
+ const stats = buildArchiveFile(dirPath, archivePath);
203
+ await brotliCompressFile(archivePath, compressedPath);
204
+ let encodeInputPath = compressedPath;
205
+ if (password) {
206
+ const encryptedPath = join(tempDir, "encrypted.bin");
207
+ writeFileSync(encryptedPath, encryptBuffer(readFileSync(compressedPath), password));
208
+ encodeInputPath = encryptedPath;
209
+ }
210
+ const compressedBytes = statSync(encodeInputPath).size;
211
+ const encodedLength = estimatedEncodedLength(compressedBytes, encoding);
212
+ const splitChunkSize = resolveSplitChunkSize(encodedLength, split);
213
+ const outputPaths = encodeBinaryFileToTextFiles(encodeInputPath, outputPath, encoding, splitChunkSize);
214
+ return { ...stats, compressedBytes, outputPaths, splitChunkSize };
215
+ }
216
+ finally {
217
+ rmSync(tempDir, { recursive: true, force: true });
218
+ }
219
+ }
220
+ //# sourceMappingURL=folder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder.js","sourceRoot":"","sources":["../../src/streaming/folder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type Encoding } from "./index.js";
2
+ interface ArchiveStats {
3
+ fileCount: number;
4
+ dirCount: number;
5
+ originalBytes: number;
6
+ archiveBytes: number;
7
+ }
8
+ export interface CompressFolderToPathResult extends ArchiveStats {
9
+ outputPaths: string[];
10
+ compressedBytes: number;
11
+ splitChunkSize?: number;
12
+ }
13
+ export declare function compressFolderToPath(dirPath: string, outputPath: string, encoding?: Encoding, split?: number): Promise<CompressFolderToPathResult>;
14
+ export declare function brotliCompressBuffer(input: Buffer): Buffer;
15
+ export {};
16
+ //# sourceMappingURL=streaming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAqBA,OAAO,EACN,KAAK,QAAQ,EAIb,MAAM,YAAY,CAAC;AAKpB,UAAU,YAAY;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACrB;AAoPD,MAAM,WAAW,0BAA2B,SAAQ,YAAY;IAC/D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,oBAAoB,CACzC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,QAAQ,GAAE,QAAa,EACvB,KAAK,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,0BAA0B,CAAC,CAqBrC;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ1D"}
@@ -0,0 +1,243 @@
1
+ import { closeSync, createReadStream, createWriteStream, mkdtempSync, openSync, readdirSync, readSync, rmSync, statSync, writeSync, } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { Readable } from "node:stream";
5
+ import { pipeline } from "node:stream/promises";
6
+ import { brotliCompressSync, createBrotliCompress, constants as zlibConstants, } from "node:zlib";
7
+ import { formatSplitOutputPath, resolveSplitChunkSize, TAG_FOLDER, } from "./index.js";
8
+ const COPY_CHUNK = 1024 * 1024;
9
+ const ENCODE_READ_CHUNK = 3 * 1024 * 1024;
10
+ function writeDirEntry(fd, relPath) {
11
+ const pathBuf = Buffer.from(relPath, "utf-8");
12
+ const pathLenBuf = Buffer.alloc(4);
13
+ pathLenBuf.writeUInt32LE(pathBuf.length, 0);
14
+ writeSync(fd, Buffer.from([0x44]));
15
+ writeSync(fd, pathLenBuf);
16
+ writeSync(fd, pathBuf);
17
+ }
18
+ function writeFileEntry(fd, relPath, filePath) {
19
+ const pathBuf = Buffer.from(relPath, "utf-8");
20
+ const pathLenBuf = Buffer.alloc(4);
21
+ pathLenBuf.writeUInt32LE(pathBuf.length, 0);
22
+ const contentLen = statSync(filePath).size;
23
+ const contentLenBuf = Buffer.alloc(4);
24
+ contentLenBuf.writeUInt32LE(contentLen, 0);
25
+ writeSync(fd, Buffer.from([0x46]));
26
+ writeSync(fd, pathLenBuf);
27
+ writeSync(fd, pathBuf);
28
+ writeSync(fd, contentLenBuf);
29
+ const srcFd = openSync(filePath, "r");
30
+ try {
31
+ const buf = Buffer.alloc(COPY_CHUNK);
32
+ let copied = 0;
33
+ while (copied < contentLen) {
34
+ const toRead = Math.min(buf.length, contentLen - copied);
35
+ const n = readSync(srcFd, buf, 0, toRead, copied);
36
+ if (n <= 0)
37
+ break;
38
+ writeSync(fd, buf, 0, n);
39
+ copied += n;
40
+ }
41
+ }
42
+ finally {
43
+ closeSync(srcFd);
44
+ }
45
+ return contentLen;
46
+ }
47
+ function buildArchiveFile(rootDir, archivePath) {
48
+ const fd = openSync(archivePath, "w");
49
+ let fileCount = 0;
50
+ let dirCount = 0;
51
+ let originalBytes = 0;
52
+ function walk(absDir, relDir) {
53
+ if (relDir !== "") {
54
+ writeDirEntry(fd, relDir);
55
+ dirCount++;
56
+ }
57
+ const dirents = readdirSync(absDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
58
+ for (const dirent of dirents) {
59
+ const abs = join(absDir, dirent.name);
60
+ const rel = relDir ? `${relDir}/${dirent.name}` : dirent.name;
61
+ if (dirent.isDirectory()) {
62
+ walk(abs, rel);
63
+ }
64
+ else if (dirent.isFile()) {
65
+ originalBytes += writeFileEntry(fd, rel, abs);
66
+ fileCount++;
67
+ }
68
+ }
69
+ }
70
+ try {
71
+ walk(rootDir, "");
72
+ }
73
+ finally {
74
+ closeSync(fd);
75
+ }
76
+ return {
77
+ fileCount,
78
+ dirCount,
79
+ originalBytes,
80
+ archiveBytes: statSync(archivePath).size,
81
+ };
82
+ }
83
+ function prependTagStream(tag, filePath) {
84
+ const tagBuf = Buffer.from([tag]);
85
+ const file = createReadStream(filePath);
86
+ return Readable.from((async function* () {
87
+ yield tagBuf;
88
+ for await (const chunk of file) {
89
+ yield chunk;
90
+ }
91
+ })());
92
+ }
93
+ async function brotliCompressFile(inputPath, outputPath) {
94
+ await pipeline(prependTagStream(TAG_FOLDER, inputPath), createBrotliCompress({
95
+ params: {
96
+ [zlibConstants.BROTLI_PARAM_QUALITY]: zlibConstants.BROTLI_MAX_QUALITY,
97
+ [zlibConstants.BROTLI_PARAM_LGWIN]: zlibConstants.BROTLI_MAX_WINDOW_BITS,
98
+ [zlibConstants.BROTLI_PARAM_SIZE_HINT]: statSync(inputPath).size + 1,
99
+ },
100
+ }), createWriteStream(outputPath));
101
+ }
102
+ function estimatedEncodedLength(binaryBytes, encoding) {
103
+ if (encoding === 64)
104
+ return Math.ceil(binaryBytes / 3) * 4;
105
+ const padded = 1 + binaryBytes + ((4 - ((binaryBytes + 1) % 4)) % 4);
106
+ return (padded / 4) * 5;
107
+ }
108
+ const Z85_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#";
109
+ function z85EncodeBuffer(buffer) {
110
+ let out = "";
111
+ for (let i = 0; i < buffer.length; i += 4) {
112
+ let value = buffer[i] * 16777216 +
113
+ buffer[i + 1] * 65536 +
114
+ buffer[i + 2] * 256 +
115
+ buffer[i + 3];
116
+ const chars = new Array(5);
117
+ for (let j = 4; j >= 0; j--) {
118
+ chars[j] = Z85_ALPHABET[value % 85];
119
+ value = Math.floor(value / 85);
120
+ }
121
+ out += chars.join("");
122
+ }
123
+ return out;
124
+ }
125
+ function openPart(outputPath, partIndex, totalParts) {
126
+ const path = formatSplitOutputPath(outputPath, partIndex, totalParts);
127
+ const fd = openSync(path, "w");
128
+ return { path, fd };
129
+ }
130
+ function encodeBinaryFileToTextFiles(inputPath, outputPath, encoding, split) {
131
+ const binaryBytes = statSync(inputPath).size;
132
+ const srcFd = openSync(inputPath, "r");
133
+ const readAndEncode = (writeEncoded) => {
134
+ if (encoding === 64) {
135
+ const buf = Buffer.alloc(ENCODE_READ_CHUNK);
136
+ let pos = 0;
137
+ while (pos < binaryBytes) {
138
+ const toRead = Math.min(buf.length, binaryBytes - pos);
139
+ const n = readSync(srcFd, buf, 0, toRead, pos);
140
+ if (n <= 0)
141
+ break;
142
+ writeEncoded(buf.subarray(0, n).toString("base64"));
143
+ pos += n;
144
+ }
145
+ }
146
+ else {
147
+ const raw = Buffer.alloc(binaryBytes);
148
+ let pos = 0;
149
+ while (pos < binaryBytes) {
150
+ const n = readSync(srcFd, raw, pos, binaryBytes - pos, pos);
151
+ if (n <= 0)
152
+ break;
153
+ pos += n;
154
+ }
155
+ const padLength = (4 - ((raw.length + 1) % 4)) % 4;
156
+ const padded = Buffer.concat([
157
+ Buffer.from([padLength]),
158
+ raw,
159
+ Buffer.alloc(padLength),
160
+ ]);
161
+ writeEncoded(z85EncodeBuffer(padded));
162
+ }
163
+ };
164
+ if (!split) {
165
+ const outFd = openSync(outputPath, "w");
166
+ try {
167
+ readAndEncode((text) => writeSync(outFd, text));
168
+ }
169
+ finally {
170
+ closeSync(srcFd);
171
+ closeSync(outFd);
172
+ }
173
+ return [outputPath];
174
+ }
175
+ const encodedLength = estimatedEncodedLength(binaryBytes, encoding);
176
+ const totalParts = Math.ceil(encodedLength / split);
177
+ const paths = [];
178
+ let partIndex = 1;
179
+ let part = openPart(outputPath, partIndex, totalParts);
180
+ paths.push(part.path);
181
+ let partChars = 0;
182
+ const flushPart = () => {
183
+ closeSync(part.fd);
184
+ if (partIndex < totalParts) {
185
+ partIndex++;
186
+ part = openPart(outputPath, partIndex, totalParts);
187
+ paths.push(part.path);
188
+ partChars = 0;
189
+ }
190
+ };
191
+ const writeEncoded = (text) => {
192
+ let offset = 0;
193
+ while (offset < text.length) {
194
+ const remaining = split - partChars;
195
+ if (remaining <= 0) {
196
+ flushPart();
197
+ continue;
198
+ }
199
+ const slice = text.slice(offset, offset + remaining);
200
+ writeSync(part.fd, slice);
201
+ partChars += slice.length;
202
+ offset += slice.length;
203
+ if (partChars >= split && offset < text.length)
204
+ flushPart();
205
+ }
206
+ };
207
+ try {
208
+ readAndEncode(writeEncoded);
209
+ }
210
+ finally {
211
+ closeSync(srcFd);
212
+ closeSync(part.fd);
213
+ }
214
+ return paths;
215
+ }
216
+ export async function compressFolderToPath(dirPath, outputPath, encoding = 64, split) {
217
+ const tempDir = mkdtempSync(join(tmpdir(), "text-compress-"));
218
+ const archivePath = join(tempDir, "archive.bin");
219
+ const compressedPath = join(tempDir, "compressed.bin");
220
+ try {
221
+ const stats = buildArchiveFile(dirPath, archivePath);
222
+ await brotliCompressFile(archivePath, compressedPath);
223
+ const compressedBytes = statSync(compressedPath).size;
224
+ const encodedLength = estimatedEncodedLength(compressedBytes, encoding);
225
+ const splitChunkSize = resolveSplitChunkSize(encodedLength, split);
226
+ const outputPaths = encodeBinaryFileToTextFiles(compressedPath, outputPath, encoding, splitChunkSize);
227
+ return { ...stats, compressedBytes, outputPaths, splitChunkSize };
228
+ }
229
+ finally {
230
+ rmSync(tempDir, { recursive: true, force: true });
231
+ }
232
+ }
233
+ // Small in-memory brotli helper kept for tests / text mode parity checks.
234
+ export function brotliCompressBuffer(input) {
235
+ return brotliCompressSync(input, {
236
+ params: {
237
+ [zlibConstants.BROTLI_PARAM_QUALITY]: zlibConstants.BROTLI_MAX_QUALITY,
238
+ [zlibConstants.BROTLI_PARAM_LGWIN]: zlibConstants.BROTLI_MAX_WINDOW_BITS,
239
+ [zlibConstants.BROTLI_PARAM_SIZE_HINT]: input.length,
240
+ },
241
+ });
242
+ }
243
+ //# sourceMappingURL=streaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @module types
3
+ *
4
+ * Shared type definitions for the text-compress library.
5
+ *
6
+ * Keeping types in a dedicated module avoids circular imports between
7
+ * encoding, compression, and API layers — each domain imports only what
8
+ * it needs from here.
9
+ */
10
+ /**
11
+ * Text encoding applied to the Brotli-compressed binary blob.
12
+ *
13
+ * - `64` — standard Base64 (`A-Za-z0-9+/=`). Universally paste-safe.
14
+ * - `85` — Z85 Base85 (ZeroMQ RFC 32). ~8 % smaller; uses punctuation
15
+ * that is safe in code blocks but not in all chat clients.
16
+ */
17
+ export type Encoding = 64 | 85;
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,EAAE,GAAG,EAAE,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @module types
3
+ *
4
+ * Shared type definitions for the text-compress library.
5
+ *
6
+ * Keeping types in a dedicated module avoids circular imports between
7
+ * encoding, compression, and API layers — each domain imports only what
8
+ * it needs from here.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "text-compress",
3
+ "version": "2.0.0",
4
+ "description": "Brotli-compress text or folders to base64/base85 strings for easy sharing",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "text-compress": "./dist/cli.js"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "check": "biome check --write . && tsc",
23
+ "dev": "tsx src/cli.ts",
24
+ "test": "vitest run",
25
+ "pretest": "npm run build",
26
+ "test:watch": "vitest",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "brotli",
31
+ "compression",
32
+ "base64",
33
+ "base85",
34
+ "z85",
35
+ "text",
36
+ "archive"
37
+ ],
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/startdo-ing/text-compress-cli.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/startdo-ing/text-compress-cli/issues"
44
+ },
45
+ "homepage": "https://github.com/startdo-ing/text-compress-cli#readme",
46
+ "license": "MIT",
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "devDependencies": {
51
+ "@biomejs/biome": "^2.5.2",
52
+ "@types/node": "^26.1.0",
53
+ "tsx": "^4.19.4",
54
+ "typescript": "7.0.1-rc",
55
+ "vitest": "^4.1.9"
56
+ },
57
+ "dependencies": {
58
+ "ignore": "^7.0.5"
59
+ }
60
+ }