stegdoc 5.0.1 → 5.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stegdoc",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "description": "Hide files inside Office documents (XLSX/DOCX) with AES-256 encryption and steganography",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -14,7 +14,7 @@ const { isCompressedMime, createCompressStream, createBrotliCompressStream } = r
14
14
  const { resetTimeWindow } = require('../lib/decoy-generator');
15
15
  const { resetTimeState, BYTES_PER_DATA_LINE, calculateDataLineCount } = require('../lib/log-generator');
16
16
  const { shouldRunInteractive, promptEncodeOptions } = require('../lib/interactive');
17
- const { Base64EncodeTransform, ChunkCollector, BinaryChunkCollector } = require('../lib/streams');
17
+ const { Base64EncodeTransform, ChunkCollector, BinaryChunkCollector, ProgressTransform } = require('../lib/streams');
18
18
 
19
19
  /**
20
20
  * Zip a folder into a buffer
@@ -268,6 +268,19 @@ async function encodeCommand(inputFile, options) {
268
268
  const collector = new BinaryChunkCollector(binaryChunkSize, onBinaryChunkReady);
269
269
 
270
270
  const streams = [fs.createReadStream(streamSource)];
271
+
272
+ // Add progress tracking before compression (tracks input bytes read)
273
+ if (!quiet) {
274
+ const progressStream = new ProgressTransform(fileSize, (processed, total) => {
275
+ const pct = Math.min(100, Math.round((processed / total) * 100));
276
+ const processedFmt = formatBytes(processed);
277
+ const totalFmt = formatBytes(total);
278
+ const phase = useCompression ? 'Compressing' : 'Processing';
279
+ spinner.text = `${phase}... ${processedFmt} / ${totalFmt} (${pct}%)`;
280
+ });
281
+ streams.push(progressStream);
282
+ }
283
+
271
284
  if (useCompression) {
272
285
  streams.push(createBrotliCompressStream());
273
286
  }
@@ -396,6 +409,12 @@ async function encodeLegacyXlsx(inputPath, filename, extension, fileSize, option
396
409
 
397
410
  const collector = new BinaryChunkCollector(binaryChunkSize, onBinaryChunkReady);
398
411
  const streams = [fs.createReadStream(inputPath)];
412
+ if (!quiet) {
413
+ streams.push(new ProgressTransform(fileSize, (processed, total) => {
414
+ const pct = Math.min(100, Math.round((processed / total) * 100));
415
+ spinner.text = `Compressing (legacy v4)... ${formatBytes(processed)} / ${formatBytes(total)} (${pct}%)`;
416
+ }));
417
+ }
399
418
  if (useCompression) streams.push(createCompressStream());
400
419
  streams.push(collector);
401
420
  await pipeline(...streams);
@@ -438,6 +457,12 @@ async function encodeLegacyXlsx(inputPath, filename, extension, fileSize, option
438
457
 
439
458
  const collector = new ChunkCollector(chunkSizeBytes, onChunkReady);
440
459
  const streams = [fs.createReadStream(inputPath)];
460
+ if (!quiet) {
461
+ streams.push(new ProgressTransform(fileSize, (processed, total) => {
462
+ const pct = Math.min(100, Math.round((processed / total) * 100));
463
+ spinner.text = `Encoding (legacy v4)... ${formatBytes(processed)} / ${formatBytes(total)} (${pct}%)`;
464
+ }));
465
+ }
441
466
  if (useCompression) streams.push(createCompressStream());
442
467
  streams.push(new Base64EncodeTransform());
443
468
  streams.push(collector);
@@ -188,10 +188,43 @@ class BinaryChunkCollector extends Writable {
188
188
  }
189
189
  }
190
190
 
191
+ /**
192
+ * Transform stream that passes data through unchanged while reporting progress.
193
+ * Calls onProgress(bytesProcessed, totalBytes) periodically.
194
+ */
195
+ class ProgressTransform extends Transform {
196
+ constructor(totalBytes, onProgress, intervalMs = 200) {
197
+ super();
198
+ this._totalBytes = totalBytes;
199
+ this._bytesProcessed = 0;
200
+ this._onProgress = onProgress;
201
+ this._lastReport = 0;
202
+ this._intervalMs = intervalMs;
203
+ }
204
+
205
+ _transform(chunk, encoding, callback) {
206
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding);
207
+ this._bytesProcessed += buf.length;
208
+ const now = Date.now();
209
+ if (now - this._lastReport >= this._intervalMs) {
210
+ this._lastReport = now;
211
+ this._onProgress(this._bytesProcessed, this._totalBytes);
212
+ }
213
+ this.push(buf);
214
+ callback();
215
+ }
216
+
217
+ _flush(callback) {
218
+ this._onProgress(this._bytesProcessed, this._totalBytes);
219
+ callback();
220
+ }
221
+ }
222
+
191
223
  module.exports = {
192
224
  Base64EncodeTransform,
193
225
  Base64DecodeTransform,
194
226
  HashPassthrough,
195
227
  ChunkCollector,
196
228
  BinaryChunkCollector,
229
+ ProgressTransform,
197
230
  };