roxify 1.1.5 → 1.1.6

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/dist/cli.js CHANGED
@@ -127,6 +127,7 @@ async function encodeCommand(args) {
127
127
  : undefined;
128
128
  const firstInput = inputPaths[0];
129
129
  if (!firstInput) {
130
+ console.log(' ');
130
131
  console.error('Error: Input file required');
131
132
  console.log('Usage: npx rox encode <input> [output] [options]');
132
133
  process.exit(1);
@@ -259,6 +260,7 @@ async function encodeCommand(args) {
259
260
  console.log(' ');
260
261
  }
261
262
  catch (err) {
263
+ console.log(' ');
262
264
  console.error('Error: Failed to encode file. Use --verbose for details.');
263
265
  if (parsed.verbose)
264
266
  console.error('Details:', err.stack || err.message);
@@ -269,6 +271,7 @@ async function decodeCommand(args) {
269
271
  const parsed = parseArgs(args);
270
272
  const [inputPath, outputPath] = parsed._;
271
273
  if (!inputPath) {
274
+ console.log(' ');
272
275
  console.error('Error: Input PNG file required');
273
276
  console.log('Usage: npx rox decode <input> [output] [options]');
274
277
  process.exit(1);
@@ -317,7 +320,7 @@ async function decodeCommand(args) {
317
320
  });
318
321
  decodeBar.stop();
319
322
  if (result.files) {
320
- const baseDir = parsed.output || outputPath || 'extracted';
323
+ const baseDir = parsed.output || outputPath || '.';
321
324
  for (const file of result.files) {
322
325
  const fullPath = join(baseDir, file.path);
323
326
  const dir = dirname(fullPath);
@@ -325,20 +328,20 @@ async function decodeCommand(args) {
325
328
  writeFileSync(fullPath, file.buf);
326
329
  }
327
330
  console.log(`\nSuccess!`);
328
- console.log(`Extracted ${result.files.length} files to ${baseDir}`);
331
+ console.log(`Extracted ${result.files.length} files to ${baseDir === '.' ? 'current directory' : baseDir}`);
329
332
  console.log(`Time: ${decodeTime}ms`);
330
333
  }
331
334
  else if (result.buf) {
332
335
  const unpacked = unpackBuffer(result.buf);
333
336
  if (unpacked) {
334
- const baseDir = parsed.output || outputPath || result.meta?.name || 'unpacked';
337
+ const baseDir = parsed.output || outputPath || result.meta?.name || '.';
335
338
  for (const file of unpacked.files) {
336
339
  const fullPath = join(baseDir, file.path);
337
340
  const dir = dirname(fullPath);
338
341
  mkdirSync(dir, { recursive: true });
339
342
  writeFileSync(fullPath, file.buf);
340
343
  }
341
- console.log(`Unpacked ${unpacked.files.length} files to ${baseDir}`);
344
+ console.log(`Unpacked ${unpacked.files.length} files to ${baseDir === '.' ? 'current directory' : baseDir}`);
342
345
  }
343
346
  else {
344
347
  const resolvedOutput = parsed.output || outputPath || result.meta?.name || 'decoded.bin';
@@ -357,10 +360,12 @@ async function decodeCommand(args) {
357
360
  catch (err) {
358
361
  if (err instanceof PassphraseRequiredError ||
359
362
  (err.message && err.message.includes('passphrase') && !parsed.passphrase)) {
363
+ console.log(' ');
360
364
  console.error('File appears to be encrypted. Provide a passphrase with -p');
361
365
  }
362
366
  else if (err instanceof IncorrectPassphraseError ||
363
367
  (err.message && err.message.includes('Incorrect passphrase'))) {
368
+ console.log(' ');
364
369
  console.error('Incorrect passphrase');
365
370
  }
366
371
  else if (err instanceof DataFormatError ||
@@ -370,13 +375,16 @@ async function decodeCommand(args) {
370
375
  err.message.includes('Pixel payload truncated') ||
371
376
  err.message.includes('Marker START not found') ||
372
377
  err.message.includes('Brotli decompression failed')))) {
378
+ console.log(' ');
373
379
  console.error('Data corrupted or unsupported format. Use --verbose for details.');
374
380
  }
375
381
  else {
382
+ console.log(' ');
376
383
  console.error('Failed to decode file. Use --verbose for details.');
377
384
  }
378
- if (parsed.verbose)
385
+ if (parsed.verbose) {
379
386
  console.error('Details:', err.stack || err.message);
387
+ }
380
388
  process.exit(1);
381
389
  }
382
390
  }
@@ -384,6 +392,7 @@ async function listCommand(args) {
384
392
  const parsed = parseArgs(args);
385
393
  const [inputPath] = parsed._;
386
394
  if (!inputPath) {
395
+ console.log(' ');
387
396
  console.error('Error: Input PNG file required');
388
397
  console.log('Usage: npx rox list <input>');
389
398
  process.exit(1);
@@ -403,9 +412,11 @@ async function listCommand(args) {
403
412
  }
404
413
  }
405
414
  catch (err) {
415
+ console.log(' ');
406
416
  console.error('Failed to list files. Use --verbose for details.');
407
- if (parsed.verbose)
417
+ if (parsed.verbose) {
408
418
  console.error('Details:', err.stack || err.message);
419
+ }
409
420
  process.exit(1);
410
421
  }
411
422
  }
@@ -438,6 +449,7 @@ async function main() {
438
449
  }
439
450
  }
440
451
  main().catch((err) => {
452
+ console.log(' ');
441
453
  console.error('Fatal error:', err);
442
454
  process.exit(1);
443
455
  });
package/dist/index.js CHANGED
@@ -1276,7 +1276,18 @@ export function listFilesInPng(pngBuf) {
1276
1276
  const data = Buffer.isBuffer(fileListChunk.data)
1277
1277
  ? fileListChunk.data
1278
1278
  : Buffer.from(fileListChunk.data);
1279
- return JSON.parse(data.toString('utf8'));
1279
+ const files = JSON.parse(data.toString('utf8'));
1280
+ const dirs = new Set();
1281
+ for (const file of files) {
1282
+ const parts = file.split('/');
1283
+ let path = '';
1284
+ for (let i = 0; i < parts.length - 1; i++) {
1285
+ path += parts[i] + '/';
1286
+ dirs.add(path);
1287
+ }
1288
+ }
1289
+ const all = [...dirs, ...files];
1290
+ return all.sort();
1280
1291
  }
1281
1292
  }
1282
1293
  catch (e) { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roxify",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "Encode binary data into PNG images with Zstd compression and decode them back. Supports CLI and programmatic API (Node.js ESM).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",