neozip-cli 0.70.0-alpha

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 (43) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/DOCUMENTATION.md +194 -0
  3. package/LICENSE +22 -0
  4. package/README.md +504 -0
  5. package/WHY_NEOZIP.md +212 -0
  6. package/bin/neolist +16 -0
  7. package/bin/neounzip +16 -0
  8. package/bin/neozip +15 -0
  9. package/dist/neozipkit-bundles/blockchain.js +13091 -0
  10. package/dist/neozipkit-bundles/browser.js +5733 -0
  11. package/dist/neozipkit-bundles/core.js +3766 -0
  12. package/dist/neozipkit-bundles/server.js +14996 -0
  13. package/dist/neozipkit-wrappers/blockchain/core/contracts.js +16 -0
  14. package/dist/neozipkit-wrappers/blockchain/index.js +2 -0
  15. package/dist/neozipkit-wrappers/core/ZipDecompress.js +2 -0
  16. package/dist/neozipkit-wrappers/core/components/HashCalculator.js +2 -0
  17. package/dist/neozipkit-wrappers/core/components/Logger.js +2 -0
  18. package/dist/neozipkit-wrappers/core/constants/Errors.js +2 -0
  19. package/dist/neozipkit-wrappers/core/constants/Headers.js +2 -0
  20. package/dist/neozipkit-wrappers/core/encryption/ZipCrypto.js +7 -0
  21. package/dist/neozipkit-wrappers/core/index.js +3 -0
  22. package/dist/neozipkit-wrappers/index.js +13 -0
  23. package/dist/neozipkit-wrappers/server/index.js +2 -0
  24. package/dist/src/config/ConfigSetup.js +455 -0
  25. package/dist/src/config/ConfigStore.js +373 -0
  26. package/dist/src/config/ConfigWizard.js +453 -0
  27. package/dist/src/config/WalletConfig.js +372 -0
  28. package/dist/src/exit-codes.js +210 -0
  29. package/dist/src/index.js +141 -0
  30. package/dist/src/neolist.js +1194 -0
  31. package/dist/src/neounzip.js +2177 -0
  32. package/dist/src/neozip/CommentManager.js +240 -0
  33. package/dist/src/neozip/blockchain.js +383 -0
  34. package/dist/src/neozip/createZip.js +2273 -0
  35. package/dist/src/neozip/file-operations.js +920 -0
  36. package/dist/src/neozip/types.js +6 -0
  37. package/dist/src/neozip/user-interaction.js +256 -0
  38. package/dist/src/neozip/utils.js +96 -0
  39. package/dist/src/neozip.js +785 -0
  40. package/dist/src/server/CommentManager.js +240 -0
  41. package/dist/src/version.js +59 -0
  42. package/env.example +101 -0
  43. package/package.json +175 -0
@@ -0,0 +1,785 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * NEOZIP - Standalone ZIP creation tool with blockchain tokenization
5
+ * Usage: neozip [options] <archive> <files...>
6
+ *
7
+ * Configuration: Use `neozip init` to set up wallet credentials
8
+ * For blockchain features, wallet key can be provided via:
9
+ * 1. CLI flag: -w 0x...
10
+ * 2. Config file: ~/.neozip/wallet.json (recommended)
11
+ * 3. ENV var: NEOZIP_WALLET_PASSKEY
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.main = main;
48
+ exports.parseArgs = parseArgs;
49
+ exports.showHelp = showHelp;
50
+ exports.showExtendedHelp = showExtendedHelp;
51
+ // Load environment variables from .env.local (if it exists)
52
+ // This allows users to set NEOZIP_NETWORK and other config via .env.local
53
+ const dotenv = __importStar(require("dotenv"));
54
+ const path = __importStar(require("path"));
55
+ const fs = __importStar(require("fs"));
56
+ // Try to load .env.local first, then .env as fallback
57
+ const envLocalPath = path.join(process.cwd(), '.env.local');
58
+ const envPath = path.join(process.cwd(), '.env');
59
+ if (fs.existsSync(envLocalPath)) {
60
+ dotenv.config({ path: envLocalPath });
61
+ }
62
+ else if (fs.existsSync(envPath)) {
63
+ dotenv.config({ path: envPath });
64
+ }
65
+ const utils_1 = require("./neozip/utils");
66
+ const user_interaction_1 = require("./neozip/user-interaction");
67
+ const createZip_1 = require("./neozip/createZip");
68
+ const file_operations_1 = require("./neozip/file-operations");
69
+ // ConfigSetup is lazy-loaded only when needed (init/config commands)
70
+ const contracts_1 = require('../neozipkit-wrappers/blockchain/core/contracts');
71
+ const ConfigStore_1 = require("./config/ConfigStore");
72
+ const exit_codes_1 = require("./exit-codes");
73
+ const version_1 = require("./version");
74
+ /**
75
+ * Parse command line arguments
76
+ */
77
+ function parseArgs(args) {
78
+ const options = {
79
+ verbose: false,
80
+ quiet: false,
81
+ level: 6,
82
+ blockchain: false, // Blockchain disabled by default
83
+ blockchainOts: false, // OpenTimestamp disabled by default
84
+ blockchainDefault: false, // Auto-select default option disabled by default
85
+ blockchainMint: false, // Force mint new token disabled by default
86
+ network: 'base-sepolia',
87
+ walletPasskey: process.env.NEOZIP_WALLET_PASSKEY,
88
+ compression: 'zstd',
89
+ blockSize: 128 * 1024, // 128KB default
90
+ enableProgress: true,
91
+ junkPaths: false,
92
+ update: false,
93
+ freshen: false,
94
+ move: false,
95
+ interactiveComments: false,
96
+ walletKey: undefined
97
+ };
98
+ const files = [];
99
+ let archive = '';
100
+ for (let i = 0; i < args.length; i++) {
101
+ const arg = args[i];
102
+ switch (arg) {
103
+ case '-h':
104
+ showHelp();
105
+ process.exit(0);
106
+ break;
107
+ case '-h2':
108
+ case '--help-extended':
109
+ showExtendedHelp();
110
+ process.exit(0);
111
+ break;
112
+ case '--help':
113
+ showHelp();
114
+ process.exit(0);
115
+ break;
116
+ case '-V':
117
+ case '--version':
118
+ console.log(`NeoZip Version: ${version_1.APP_VERSION} (${version_1.APP_RELEASE_DATE})`);
119
+ process.exit(0);
120
+ break;
121
+ case '-v':
122
+ case '--verbose':
123
+ options.verbose = true;
124
+ break;
125
+ case '-q':
126
+ case '--quiet':
127
+ options.quiet = true;
128
+ break;
129
+ case '-0':
130
+ options.level = 0; // Store only (no compression)
131
+ break;
132
+ case '-1':
133
+ options.level = 1; // Fastest compression
134
+ break;
135
+ case '-2':
136
+ options.level = 2;
137
+ break;
138
+ case '-3':
139
+ options.level = 3;
140
+ break;
141
+ case '-4':
142
+ options.level = 4;
143
+ break;
144
+ case '-5':
145
+ options.level = 5;
146
+ break;
147
+ case '-6':
148
+ options.level = 6; // Default compression
149
+ break;
150
+ case '-7':
151
+ options.level = 7;
152
+ break;
153
+ case '-8':
154
+ options.level = 8;
155
+ break;
156
+ case '-9':
157
+ options.level = 9; // Best compression
158
+ break;
159
+ case '-l':
160
+ case '--level':
161
+ const level = parseInt(args[++i]);
162
+ if (isNaN(level) || level < 0 || level > 9) {
163
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR, 'Error: Compression level must be between 0 and 9 (0=store, 1=fastest, 9=best)');
164
+ }
165
+ options.level = level;
166
+ break;
167
+ case '-ots':
168
+ case '--opentimestamp':
169
+ options.blockchainOts = true;
170
+ break;
171
+ case '-bt':
172
+ case '--blockchain-token':
173
+ options.blockchain = true;
174
+ break;
175
+ case '-bd':
176
+ case '--blockchain-default':
177
+ options.blockchain = true;
178
+ options.blockchainDefault = true;
179
+ break;
180
+ case '-bm':
181
+ case '--blockchain-mint':
182
+ options.blockchain = true;
183
+ options.blockchainMint = true;
184
+ break;
185
+ case '-n':
186
+ case '--network':
187
+ const network = args[++i];
188
+ if ((0, contracts_1.getChainIdByName)(network) === null) {
189
+ const supportedNetworks = (0, contracts_1.getSupportedNetworkNames)();
190
+ console.error(`Error: Unsupported network: "${network}"`);
191
+ console.error(`Supported networks: ${supportedNetworks.join(', ')}`);
192
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
193
+ }
194
+ options.network = network;
195
+ break;
196
+ case '--wallet-key':
197
+ options.walletPasskey = args[++i];
198
+ break;
199
+ case '-b':
200
+ case '--blockchain':
201
+ options.blockchain = true;
202
+ // Tokenization is automatically enabled when blockchain is enabled
203
+ break;
204
+ case '-w':
205
+ options.walletKey = args[++i];
206
+ break;
207
+ case '--compression':
208
+ const compression = args[++i];
209
+ if (compression === 'zstd' || compression === 'deflate') {
210
+ options.compression = compression;
211
+ }
212
+ else {
213
+ console.error('Error: Compression must be "zstd" or "deflate"');
214
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
215
+ }
216
+ break;
217
+ case '--deflate':
218
+ case '--pkzip-compress':
219
+ options.compression = 'deflate';
220
+ break;
221
+ case '-c':
222
+ // Add one-line comments for files
223
+ options.fileCommentsOnly = true;
224
+ break;
225
+ case '--block-size':
226
+ const blockSize = parseInt(args[++i], 10);
227
+ if (isNaN(blockSize) || blockSize < 1024) {
228
+ console.error('Error: Block size must be at least 1024 bytes');
229
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
230
+ }
231
+ options.blockSize = blockSize;
232
+ break;
233
+ case '--no-progress':
234
+ options.enableProgress = false;
235
+ break;
236
+ case '--progress':
237
+ options.progress = true;
238
+ options.enableProgress = true;
239
+ break;
240
+ case '-e':
241
+ case '--encrypt':
242
+ // InfoZip-compatible encryption option
243
+ options.encrypt = true;
244
+ // Only set encryption method if not already set
245
+ if (!options.encryptionMethod) {
246
+ options.encryptionMethod = 'pkzip'; // Default to PKZIP (InfoZip compatible)
247
+ }
248
+ // Only prompt for password if not already provided
249
+ if (!options.password) {
250
+ options.password = 'PROMPT'; // Will prompt for password
251
+ }
252
+ break;
253
+ case '-P':
254
+ case '--password':
255
+ // InfoZip-compatible password option (uppercase P)
256
+ options.encrypt = true;
257
+ // Only set encryption method if not already set (e.g., by --pkzip-encrypt)
258
+ if (!options.encryptionMethod) {
259
+ options.encryptionMethod = 'pkzip'; // Default to PKZIP
260
+ }
261
+ if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
262
+ // Password provided directly
263
+ options.password = args[++i];
264
+ }
265
+ else {
266
+ // No password provided, will prompt later
267
+ options.password = 'PROMPT';
268
+ }
269
+ break;
270
+ case '-p':
271
+ case '--show-progress':
272
+ // InfoZip-compatible show-progress option (lowercase p)
273
+ options.showFiles = true;
274
+ break;
275
+ case '--pkzip-encrypt':
276
+ options.encrypt = true;
277
+ options.encryptionMethod = 'pkzip';
278
+ // Only prompt for password if not already provided
279
+ if (!options.password) {
280
+ options.password = 'PROMPT'; // Will prompt for password
281
+ }
282
+ break;
283
+ case '-x':
284
+ case '--exclude':
285
+ if (!options.exclude)
286
+ options.exclude = [];
287
+ options.exclude.push(args[++i]);
288
+ break;
289
+ case '-i':
290
+ case '--include':
291
+ if (!options.include)
292
+ options.include = [];
293
+ options.include.push(args[++i]);
294
+ break;
295
+ case '--in-memory':
296
+ options.inMemory = true;
297
+ break;
298
+ case '-r':
299
+ case '--recurse':
300
+ options.recurse = true;
301
+ break;
302
+ case '-j':
303
+ case '--junk-paths':
304
+ options.junkPaths = true;
305
+ break;
306
+ case '-u':
307
+ case '--update':
308
+ options.update = true;
309
+ break;
310
+ case '-f':
311
+ case '--freshen':
312
+ options.freshen = true;
313
+ break;
314
+ case '-m':
315
+ case '--move':
316
+ options.move = true;
317
+ break;
318
+ case '-z':
319
+ case '--archive-comment':
320
+ options.archiveComment = args[++i];
321
+ if (!options.archiveComment) {
322
+ console.error('Error: --archive-comment requires a comment text');
323
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
324
+ }
325
+ break;
326
+ case '--comment-file':
327
+ options.commentFile = args[++i];
328
+ if (!options.commentFile) {
329
+ console.error('Error: --comment-file requires a file path');
330
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
331
+ }
332
+ break;
333
+ case '--interactive-comments':
334
+ options.interactiveComments = true;
335
+ break;
336
+ case '--suffixes':
337
+ if (!options.suffixes)
338
+ options.suffixes = [];
339
+ options.suffixes.push(args[++i]);
340
+ break;
341
+ case '-d':
342
+ options.delete = true;
343
+ break;
344
+ case '--debug':
345
+ options.debug = true;
346
+ break;
347
+ case '-sf':
348
+ case '--show-files':
349
+ options.showFiles = true;
350
+ break;
351
+ case '-l':
352
+ case '--to-crlf':
353
+ options.toCrlf = true;
354
+ break;
355
+ case '-ll':
356
+ case '--from-crlf':
357
+ options.fromCrlf = true;
358
+ break;
359
+ case '-X':
360
+ case '--preserve-perms':
361
+ options.preservePerms = true;
362
+ break;
363
+ case '-y':
364
+ case '--symlinks':
365
+ options.symlinks = true;
366
+ break;
367
+ case '-H':
368
+ case '--hard-links':
369
+ options.hardLinks = true;
370
+ break;
371
+ case '-o':
372
+ case '--old-timestamp':
373
+ options.oldTimestamp = true;
374
+ break;
375
+ case '--temp-path':
376
+ options.tempPath = args[++i];
377
+ if (!options.tempPath) {
378
+ console.error('Error: --temp-path requires a directory path');
379
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
380
+ }
381
+ break;
382
+ case '-T':
383
+ case '--test-integrity':
384
+ options.testIntegrity = true;
385
+ break;
386
+ case '--non-interactive':
387
+ options.nonInteractive = true;
388
+ break;
389
+ case '--upgrade':
390
+ options.upgrade = true;
391
+ options.blockchain = true; // Upgrade implies blockchain tokenization
392
+ break;
393
+ case '--overwrite':
394
+ options.overwrite = true;
395
+ break;
396
+ case '-@':
397
+ options.stdinFilenames = true;
398
+ break;
399
+ default:
400
+ if (arg.startsWith('-')) {
401
+ console.error(`Error: Unknown option ${arg}`);
402
+ showHelp();
403
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
404
+ }
405
+ else if (!archive) {
406
+ archive = arg;
407
+ }
408
+ else {
409
+ files.push(arg);
410
+ }
411
+ break;
412
+ }
413
+ }
414
+ if (!archive) {
415
+ console.error('Error: Archive name is required');
416
+ showHelp();
417
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
418
+ }
419
+ // Apply PKZIP-style extension behavior: default to .nzip if no extension
420
+ // If archive name ends with a period, don't add extension (suppress default)
421
+ if (archive.endsWith('.')) {
422
+ // Remove trailing period to get the base name without extension
423
+ archive = archive.slice(0, -1);
424
+ }
425
+ else {
426
+ // Check if archive has an extension (has a dot followed by at least one character)
427
+ const ext = path.extname(archive);
428
+ if (!ext) {
429
+ // No extension found, add .nzip
430
+ archive = archive + '.nzip';
431
+ }
432
+ }
433
+ // Skip file validation for upgrade mode (only needs archive path)
434
+ if (files.length === 0 && !options.stdinFilenames && !options.upgrade) {
435
+ console.error('Error: At least one file or directory must be specified');
436
+ showHelp();
437
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
438
+ }
439
+ return { archive, files, options };
440
+ }
441
+ /**
442
+ * Show help information
443
+ */
444
+ function showHelp() {
445
+ console.log(`
446
+ NeoZip Version: ${version_1.APP_VERSION} (${version_1.APP_RELEASE_DATE})
447
+
448
+ Usage: neozip [options] <archive> <files...>
449
+
450
+ Configuration Commands:
451
+ neozip init Interactive wallet setup wizard
452
+ neozip config Show current configuration and manage settings (interactive menu)
453
+
454
+ Options:
455
+ -h, --help Show this help message
456
+ -V, --version Show version information
457
+ -v, --verbose Enable verbose output
458
+ -q, --quiet Suppress output
459
+ -d Delete specified files from archive
460
+ --debug Enable debug output
461
+ -sf, --show-files Show files as they are processed
462
+ -l, --to-crlf Convert line endings to CRLF (Windows style)
463
+ -ll, --from-crlf Convert line endings from CRLF to LF (Unix style)
464
+ -X, --preserve-perms Preserve file permissions and ownership (UID/GID)
465
+ -y, --symlinks Store symbolic links as links (don't follow them)
466
+ -H, --hard-links Handle hard links efficiently (detect and deduplicate)
467
+ -o, --old-timestamp Make zipfile as old as latest entry
468
+ --temp-path <dir> Specify temporary file directory
469
+ -T, --test-integrity Test archive integrity after creation
470
+ --non-interactive Skip interactive prompts (exit on minting errors)
471
+ --upgrade Upgrade existing ZIP file for tokenization (add SHA-256 hashes)
472
+ --overwrite Overwrite input file when upgrading (default: create new file)
473
+ -@ Read file names from stdin (one per line)
474
+ -0 Store only (no compression)
475
+ -1 to -9 Compression level (1=fastest, 9=best, default: 6)
476
+ --level <level> Compression level (0-9, 0=store, default: 6)
477
+ -b, --blockchain Enable blockchain operations with tokenization
478
+ -bd, --blockchain-default Auto-select default token option (use existing or mint new)
479
+ -bm, --blockchain-mint Force mint new token (skip existing token selection)
480
+ -ots, --opentimestamp Enable OpenTimestamp proof on Bitcoin blockchain
481
+ -n, --network <network> Blockchain network (base-sepolia, base-mainnet, default: base-sepolia)
482
+ -w, --wallet-key <key> Wallet private key (overrides NEOZIP_WALLET_PASSKEY)
483
+ -c Add one-line comments for files
484
+ --compression <alg> Compression algorithm (zstd, deflate, default: zstd)
485
+ --deflate Use deflate compression (same as --compression deflate)
486
+ --pkzip-compress Use deflate compression (same as --compression deflate)
487
+ --block-size <bytes> Block size for streaming (default: 131072)
488
+ --no-progress Disable progress reporting
489
+ --progress Enable enhanced progress reporting
490
+ -e, --encrypt Encrypt files (InfoZip-compatible). Will prompt for password
491
+ -P, --password [pwd] Encrypt files with password (InfoZip-compatible). Provide password or will prompt
492
+ -p, --show-progress Show progress during compression (InfoZip-compatible)
493
+ --pkzip-encrypt Use PKZIP encryption (legacy compatibility only, same as -e)
494
+ -x, --exclude <pattern> Exclude files matching pattern (can be used multiple times)
495
+ -i, --include <pattern> Include only files matching pattern (can be used multiple times)
496
+ --suffixes <list> Don't compress files with these suffixes (can be used multiple times)
497
+ -r, --recurse Include subdirectories recursively
498
+ -j, --junk-paths Store only filenames, not directory paths
499
+ -u, --update Update existing archive (only newer files)
500
+ -f, --freshen Freshen existing archive (only existing files, no new files)
501
+ -m, --move Move files into archive (delete originals after compression)
502
+ -z, --archive-comment <text> Set archive comment
503
+ --comment-file <file> Read comments from file (archive and file comments)
504
+ --interactive-comments Prompt for comments interactively
505
+ --in-memory Use in-memory compression (browser compatible)
506
+
507
+ Arguments:
508
+ <archive> Output ZIP file name
509
+ <files...> Files and directories to compress
510
+
511
+ Examples:
512
+ neozip output/test.nzip file1.txt file2.txt
513
+ neozip output/simple.nzip ./data/
514
+ neozip -r output/recursive.nzip ./project/
515
+ `);
516
+ }
517
+ /**
518
+ * Show extended help information (equivalent to InfoZip's -h2)
519
+ */
520
+ function showExtendedHelp() {
521
+ console.log('Extended Help for NeoZip');
522
+ console.log('');
523
+ console.log('NeoZip is a next-generation ZIP utility that builds upon the strengths of the ZIP format');
524
+ console.log('while incorporating blockchain technology, advanced compression, and modern features.');
525
+ console.log('');
526
+ console.log('Basic command line:');
527
+ console.log(' neozip [options] archive_name file file ...');
528
+ console.log('');
529
+ console.log('Some examples:');
530
+ console.log(' Add file.txt to z.nzip (create z if needed): neozip z file.txt');
531
+ console.log(' Zip all files in current dir: neozip z *');
532
+ console.log(' Zip files in current dir and subdirs also: neozip -r z .');
533
+ console.log('');
534
+ console.log('Basic modes:');
535
+ console.log(' External modes (selects files from file system):');
536
+ console.log(' add - add new files/update existing files in archive (default)');
537
+ console.log(' -u update - add new files/update existing files only if later date');
538
+ console.log(' -f freshen - update existing files only (no files added)');
539
+ console.log(' Internal modes (selects entries in archive):');
540
+ console.log(' -d delete - delete files from archive');
541
+ console.log('');
542
+ console.log('Basic options:');
543
+ console.log(' -r recurse into directories');
544
+ console.log(' -m after archive created, delete original files (move into archive)');
545
+ console.log(' -j junk directory names (store just file names)');
546
+ console.log(' -q quiet operation');
547
+ console.log(' -v verbose operation');
548
+ console.log(' -c prompt for one-line comment for each entry');
549
+ console.log(' -z prompt for comment for archive');
550
+ console.log(' -@ read names to zip from stdin (one path per line)');
551
+ console.log(' -o make zipfile as old as latest entry');
552
+ console.log('');
553
+ console.log('Syntax:');
554
+ console.log(' The full command line syntax is:');
555
+ console.log('');
556
+ console.log(' neozip [-shortopts ...] [--longopt ...] [zipfile [path path ...]] [-xi list]');
557
+ console.log('');
558
+ console.log(' Any number of short option and long option arguments are allowed');
559
+ console.log(' as well as any number of path arguments for files to zip up.');
560
+ console.log('');
561
+ console.log('Options and Values:');
562
+ console.log(' For short options that take values, use -ovalue or -o value or -o=value');
563
+ console.log(' For long option values, use either --longoption=value or --longoption value');
564
+ console.log(' For example:');
565
+ console.log(' neozip --temp-path=/tmp --exclude pattern pattern zipfile path1 path2');
566
+ console.log('');
567
+ console.log('Wildcards:');
568
+ console.log(' NeoZip supports the following wildcards:');
569
+ console.log(' ? matches any single character');
570
+ console.log(' * matches any number of characters, including zero');
571
+ console.log(' [list] matches char in list (regex), can do range [a-f], all but [!bf]');
572
+ console.log('');
573
+ console.log('Include and Exclude:');
574
+ console.log(' -i pattern pattern ... include files that match a pattern');
575
+ console.log(' -x pattern pattern ... exclude files that match a pattern');
576
+ console.log(' Patterns are paths with optional wildcards and match paths as stored in');
577
+ console.log(' archive. Exclude and include lists end at next option, @, or end of line.');
578
+ console.log('');
579
+ console.log('End Of Line Translation (text files only):');
580
+ console.log(' -l change LF to CR LF (Unix->Windows)');
581
+ console.log(' -ll change CR LF to LF (Windows->Unix)');
582
+ console.log(' If first buffer read from file contains binary the translation is skipped');
583
+ console.log('');
584
+ console.log('Recursion:');
585
+ console.log(' -r recurse paths, include files in subdirs: neozip -r a path path ...');
586
+ console.log(' Use -i and -x with either to include or exclude paths');
587
+ console.log('');
588
+ console.log('Date filtering:');
589
+ console.log(' -t date exclude before (include files modified on this date and later)');
590
+ console.log(' -tt date include before (include files modified before date)');
591
+ console.log(' Can use both at same time to set a date range');
592
+ console.log(' Dates are mmddyyyy or yyyy-mm-dd');
593
+ console.log('');
594
+ console.log('Deletion:');
595
+ console.log(' -d delete files');
596
+ console.log(' Delete archive entries matching internal archive paths in list');
597
+ console.log(' neozip archive -d pattern pattern ...');
598
+ console.log('');
599
+ console.log('Compression:');
600
+ console.log(' -0 store files (no compression)');
601
+ console.log(' -1 to -9 compress fastest to compress best (default is 6)');
602
+ console.log(' --compression <method> set compression method:');
603
+ console.log(' store - store without compression, same as option -0');
604
+ console.log(' deflate - original zip deflate, same as -1 to -9');
605
+ console.log(' zstd - Zstandard compression (default)');
606
+ console.log(' lz4 - LZ4 compression');
607
+ console.log(' --deflate use deflate compression (same as --compression deflate)');
608
+ console.log(' --pkzip-compress use deflate compression (same as --compression deflate)');
609
+ console.log(' brotli - Brotli compression');
610
+ console.log('');
611
+ console.log('Encryption:');
612
+ console.log(' -e, --encrypt encrypt files (InfoZip-compatible), prompt for password');
613
+ console.log(' -P, --password pswd encrypt files with password (InfoZip-compatible)');
614
+ console.log(' --pkzip-encrypt use legacy PKZip 2.0 encryption (same as -e)');
615
+ console.log('');
616
+ console.log('Progress:');
617
+ console.log(' -p, --show-progress show progress during compression (InfoZip-compatible)');
618
+ console.log('');
619
+ console.log('Blockchain Features:');
620
+ console.log(' -b, --blockchain enable blockchain tokenization');
621
+ console.log(' --skip-blockchain disable blockchain features');
622
+ console.log(' --network <network> specify blockchain network (base-sepolia, ethereum, etc.)');
623
+ console.log(' --wallet <address> specify wallet address');
624
+ console.log(' --private-key <key> specify private key (not recommended)');
625
+ console.log(' --gas-limit <limit> set gas limit for transactions');
626
+ console.log(' --gas-price <price> set gas price for transactions');
627
+ console.log('');
628
+ console.log('Testing archives:');
629
+ console.log(' -T test completed archive with neounzip before finalizing');
630
+ console.log(' --test-integrity same as -T');
631
+ console.log('');
632
+ console.log('Archive Management:');
633
+ console.log(' -o make zipfile as old as latest entry');
634
+ console.log(' --temp-path <dir> specify temporary file directory');
635
+ console.log(' --comment-file <file> add comments from file');
636
+ console.log('');
637
+ console.log('Symbolic Links and Hard Links:');
638
+ console.log(' -y store symbolic links as links (don\'t follow them)');
639
+ console.log(' -H handle hard links efficiently (detect and deduplicate)');
640
+ console.log('');
641
+ console.log('File Permissions:');
642
+ console.log(' -X preserve file permissions and ownership (UID/GID)');
643
+ console.log('');
644
+ console.log('Progress and Verbosity:');
645
+ console.log(' -v verbose operation');
646
+ console.log(' -q quiet operation');
647
+ console.log(' --progress show progress bar');
648
+ console.log(' --debug show debug information');
649
+ console.log('');
650
+ console.log('More option highlights:');
651
+ console.log(' --temp-path <dir> when creating or updating archive, create the temp archive in');
652
+ console.log(' dir, which allows using seekable temp file when writing to a');
653
+ console.log(' write once CD, such archives compatible with more unzips');
654
+ console.log(' --show-files show files to operate on and exit');
655
+ console.log(' --suffixes <list> specify file suffixes to compress');
656
+ console.log(' --block-size <size> set compression block size');
657
+ console.log('');
658
+ console.log('For more information, visit: https://github.com/NeoWareInc/neozip-cli');
659
+ console.log('For detailed API documentation, see: https://docs.neoware.io/neozip');
660
+ }
661
+ /**
662
+ * Main function
663
+ */
664
+ async function main() {
665
+ try {
666
+ // Parse command line arguments
667
+ const args = process.argv.slice(2);
668
+ // Handle configuration commands first
669
+ if (args.length > 0) {
670
+ const command = args[0];
671
+ // Handle `neozip init` - interactive setup wizard
672
+ if (command === 'init') {
673
+ // Lazy-load ConfigSetup only when needed
674
+ const { ConfigSetup } = await import('./config/ConfigSetup.js');
675
+ const wizard = new ConfigSetup();
676
+ const success = await wizard.run();
677
+ process.exit(success ? exit_codes_1.ZIP_EXIT_CODES.SUCCESS : exit_codes_1.ZIP_EXIT_CODES.BAD_ARCHIVE_FORMAT);
678
+ }
679
+ // Handle `neozip config` - show interactive menu
680
+ if (command === 'config') {
681
+ // Lazy-load ConfigSetup only when needed
682
+ const { ConfigSetup } = await import('./config/ConfigSetup.js');
683
+ await ConfigSetup.showAndManage();
684
+ // showAndManage handles its own exit
685
+ }
686
+ }
687
+ let { archive, files, options } = parseArgs(args);
688
+ // If network not explicitly provided via CLI, use from ConfigStore (which reads from ENV or wallet.json)
689
+ const networkProvidedViaCLI = args.includes('--network') || args.includes('-n');
690
+ if (!networkProvidedViaCLI) {
691
+ const config = ConfigStore_1.ConfigStore.getConfig();
692
+ if (config.network) {
693
+ options.network = config.network;
694
+ }
695
+ }
696
+ // Handle stdin filenames
697
+ if (options.stdinFilenames) {
698
+ if (files.length > 0) {
699
+ console.error('Error: Cannot specify both files and -@ (stdin filenames)');
700
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
701
+ }
702
+ if (options.debug) {
703
+ (0, utils_1.logDebug)('Reading filenames from stdin...', options);
704
+ }
705
+ try {
706
+ files = await (0, user_interaction_1.readFilenamesFromStdin)();
707
+ if (options.debug) {
708
+ (0, utils_1.logDebug)(`Read ${files.length} filenames from stdin: ${files.join(', ')}`, options);
709
+ }
710
+ if (files.length === 0) {
711
+ console.error('Error: No filenames provided via stdin');
712
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
713
+ }
714
+ }
715
+ catch (error) {
716
+ console.error(`Error reading from stdin: ${error instanceof Error ? error.message : String(error)}`);
717
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
718
+ }
719
+ }
720
+ // Handle upgrade operation
721
+ if (options.upgrade) {
722
+ // Validate: upgrade requires exactly one argument (the ZIP file path)
723
+ if (files.length > 0) {
724
+ console.error('Error: --upgrade requires exactly one argument (the ZIP file path)');
725
+ console.error(' Usage: neozip --upgrade <existing-zip-file>');
726
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
727
+ }
728
+ if (!archive) {
729
+ console.error('Error: --upgrade requires a ZIP file path');
730
+ console.error(' Usage: neozip --upgrade <existing-zip-file>');
731
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
732
+ }
733
+ // Validate input file exists
734
+ if (!fs.existsSync(archive)) {
735
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_FIND_ARCHIVE, `Error: ZIP file not found: ${archive}`);
736
+ }
737
+ // Call upgrade function
738
+ await (0, createZip_1.upgradeZipForTokenization)(archive, options);
739
+ (0, utils_1.log)('✓ Upgrade operation completed successfully', options);
740
+ process.exit(exit_codes_1.ZIP_EXIT_CODES.SUCCESS);
741
+ }
742
+ // Handle delete operation
743
+ if (options.delete) {
744
+ await (0, file_operations_1.deleteFromArchive)(archive, files, options);
745
+ (0, utils_1.log)('✓ Delete operation completed successfully', options);
746
+ return;
747
+ }
748
+ // Create ZIP archive
749
+ await (0, createZip_1.createZip)(archive, files, options);
750
+ // Move files if requested (delete originals after successful compression)
751
+ if (options.move) {
752
+ await (0, file_operations_1.moveFiles)(files, options);
753
+ }
754
+ (0, utils_1.log)('✓ NeoZip completed successfully', options);
755
+ // Explicitly exit to ensure process terminates (provider cleanup should allow this)
756
+ process.exit(exit_codes_1.ZIP_EXIT_CODES.SUCCESS);
757
+ }
758
+ catch (error) {
759
+ const errorMessage = error instanceof Error ? error.message : String(error);
760
+ (0, utils_1.logError)(`Error: ${errorMessage}`);
761
+ // Determine appropriate exit code based on error type
762
+ if (errorMessage.includes('ENOENT') || errorMessage.includes('not found')) {
763
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_FIND_ARCHIVE, `Error: ${errorMessage}`);
764
+ }
765
+ else if (errorMessage.includes('EACCES') || errorMessage.includes('permission')) {
766
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_WRITE_ARCHIVE, `Error: ${errorMessage}`);
767
+ }
768
+ else if (errorMessage.includes('ENOSPC') || errorMessage.includes('disk full')) {
769
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.WRITE_ERROR, `Error: ${errorMessage}`);
770
+ }
771
+ else if (errorMessage.includes('memory') || errorMessage.includes('allocation')) {
772
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.MEMORY_ERROR, `Error: ${errorMessage}`);
773
+ }
774
+ else {
775
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_WRITE_ARCHIVE, `Error: ${errorMessage}`);
776
+ }
777
+ }
778
+ }
779
+ // Always run main when this module is loaded
780
+ // This allows it to work both when called directly and when imported by index.js
781
+ main().catch(err => {
782
+ console.error('Fatal error:', err);
783
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_WRITE_ARCHIVE);
784
+ });
785
+ //# sourceMappingURL=neozip.js.map