neozip-cli 0.75.1-beta → 0.80.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/CHANGELOG.md +30 -0
- package/DOCUMENTATION.md +9 -1
- package/README.md +22 -10
- package/dist/src/commands/mintTimestampProof.js +335 -0
- package/dist/src/commands/verifyEmail.js +146 -0
- package/dist/src/config/ConfigSetup.js +50 -20
- package/dist/src/config/ConfigStore.js +36 -3
- package/dist/src/index.js +1 -1
- package/dist/src/neolist.js +18 -10
- package/dist/src/neounzip.js +305 -60
- package/dist/src/neozip/blockchain.js +5 -5
- package/dist/src/neozip/createZip.js +207 -41
- package/dist/src/neozip/upgradeZip.js +182 -0
- package/dist/src/neozip.js +143 -8
- package/env.example +10 -0
- package/package.json +91 -85
- package/dist/neozipkit-bundles/blockchain.js +0 -13725
- package/dist/neozipkit-bundles/browser.js +0 -6186
- package/dist/neozipkit-bundles/core.js +0 -3839
- package/dist/neozipkit-bundles/node.js +0 -17730
- package/dist/neozipkit-wrappers/blockchain/core/contracts.js +0 -16
- package/dist/neozipkit-wrappers/blockchain/index.js +0 -2
- package/dist/neozipkit-wrappers/core/ZipDecompress.js +0 -2
- package/dist/neozipkit-wrappers/core/components/HashCalculator.js +0 -2
- package/dist/neozipkit-wrappers/core/components/Logger.js +0 -2
- package/dist/neozipkit-wrappers/core/constants/Errors.js +0 -2
- package/dist/neozipkit-wrappers/core/constants/Headers.js +0 -2
- package/dist/neozipkit-wrappers/core/encryption/ZipCrypto.js +0 -7
- package/dist/neozipkit-wrappers/core/index.js +0 -3
- package/dist/neozipkit-wrappers/index.js +0 -13
- package/dist/neozipkit-wrappers/node/index.js +0 -2
|
@@ -46,11 +46,14 @@ const fs = __importStar(require("fs"));
|
|
|
46
46
|
const path = __importStar(require("path"));
|
|
47
47
|
const neozipkit_1 = require("neozipkit");
|
|
48
48
|
const node_1 = __importDefault(require("neozipkit/node"));
|
|
49
|
-
const
|
|
49
|
+
const neozip_blockchain_1 = require("neozip-blockchain");
|
|
50
|
+
const ots_1 = require("neozip-blockchain/ots");
|
|
51
|
+
const zipstamp_server_1 = require("neozip-blockchain/zipstamp-server");
|
|
50
52
|
const CommentManager_1 = require("./CommentManager");
|
|
51
53
|
const utils_1 = require("./utils");
|
|
52
54
|
const file_operations_1 = require("./file-operations");
|
|
53
|
-
const
|
|
55
|
+
const blockchain_1 = require("./blockchain");
|
|
56
|
+
const ConfigStore_1 = require("../config/ConfigStore");
|
|
54
57
|
const user_interaction_1 = require("./user-interaction");
|
|
55
58
|
const exit_codes_1 = require("../exit-codes");
|
|
56
59
|
const version_1 = require("../version");
|
|
@@ -254,7 +257,7 @@ class ZipCreator {
|
|
|
254
257
|
this.centralDirOffset = 0;
|
|
255
258
|
this.zip = new node_1.default(); // Use ZipkitNode for ZIP operations
|
|
256
259
|
// Initialize HashAccumulator if blockchain features are enabled
|
|
257
|
-
if (this.options.blockchain || this.options.blockchainOts) {
|
|
260
|
+
if (this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp) {
|
|
258
261
|
this.hashAccumulator = new neozipkit_1.HashCalculator({ enableAccumulation: true });
|
|
259
262
|
}
|
|
260
263
|
}
|
|
@@ -284,7 +287,7 @@ class ZipCreator {
|
|
|
284
287
|
*/
|
|
285
288
|
async writeChunk(data) {
|
|
286
289
|
// For in-memory non-blockchain mode, write to buffer
|
|
287
|
-
if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts) {
|
|
290
|
+
if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts && !this.options.blockchainZipstamp) {
|
|
288
291
|
const bufferWriter = this.zip.bufferWriter;
|
|
289
292
|
if (bufferWriter) {
|
|
290
293
|
// Determine if this is a header or data by checking signature
|
|
@@ -333,7 +336,7 @@ class ZipCreator {
|
|
|
333
336
|
// Initialize output stream for file-based mode OR in-memory blockchain mode
|
|
334
337
|
// For in-memory blockchain mode, we need to write directly to file during compression
|
|
335
338
|
// For in-memory non-blockchain mode, output is written directly during compression
|
|
336
|
-
if (!this.options.inMemory || (this.options.blockchain || this.options.blockchainOts)) {
|
|
339
|
+
if (!this.options.inMemory || (this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp)) {
|
|
337
340
|
await this.initializeOutput();
|
|
338
341
|
}
|
|
339
342
|
await this.processFiles();
|
|
@@ -401,7 +404,9 @@ class ZipCreator {
|
|
|
401
404
|
const compressionDesc = this.options.level === 0 ? 'store (no compression)' : `${this.options.compression} (level ${this.options.level})`;
|
|
402
405
|
(0, utils_1.log)(`🔧 Compression: ${compressionDesc}`, this.options);
|
|
403
406
|
(0, utils_1.log)(`📊 Block size: ${(0, utils_1.formatBytes)(this.options.blockSize || 64 * 1024)}`, this.options);
|
|
404
|
-
|
|
407
|
+
if (!this.options.blockchainZipstamp && !this.options.blockchainOts) {
|
|
408
|
+
(0, utils_1.log)(`🔗 Tokenization: ${this.options.blockchain ? 'enabled' : 'disabled'}`, this.options);
|
|
409
|
+
}
|
|
405
410
|
const encryptionMethod = this.options.encryptionMethod || 'pkzip';
|
|
406
411
|
(0, utils_1.log)(`🔐 Encryption: ${this.options.encrypt ? `${encryptionMethod.toUpperCase()} enabled` : 'disabled'}`, this.options);
|
|
407
412
|
(0, utils_1.log)('', this.options);
|
|
@@ -433,6 +438,10 @@ class ZipCreator {
|
|
|
433
438
|
(0, utils_1.log)(`Blockchain: enabled (OpenTimestamp)`, this.options);
|
|
434
439
|
(0, utils_1.log)(`Bitcoin blockchain: enabled`, this.options);
|
|
435
440
|
}
|
|
441
|
+
else if (this.options.blockchainZipstamp) {
|
|
442
|
+
(0, utils_1.log)(`Blockchain: enabled (Zipstamp)`, this.options);
|
|
443
|
+
(0, utils_1.log)(`Zipstamp: enabled`, this.options);
|
|
444
|
+
}
|
|
436
445
|
else {
|
|
437
446
|
(0, utils_1.log)(`Blockchain: disabled`, this.options);
|
|
438
447
|
(0, utils_1.log)(`Tokenization: disabled`, this.options);
|
|
@@ -811,7 +820,7 @@ class ZipCreator {
|
|
|
811
820
|
const compressionOptions = {
|
|
812
821
|
level: level,
|
|
813
822
|
useZstd: level === 0 ? false : (this.options.compression || 'zstd') === 'zstd',
|
|
814
|
-
useSHA256: this.options.blockchain || this.options.blockchainOts || false,
|
|
823
|
+
useSHA256: this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp || false,
|
|
815
824
|
password: this.options.encrypt ? this.options.password : null,
|
|
816
825
|
encryptionMethod: this.options.encryptionMethod || 'pkzip'
|
|
817
826
|
};
|
|
@@ -829,7 +838,7 @@ class ZipCreator {
|
|
|
829
838
|
// Create ZipkitNode instance for buffer-based compression
|
|
830
839
|
const zipkit = new node_1.default();
|
|
831
840
|
// Determine if we need to write to file (for blockchain mode)
|
|
832
|
-
const writeToFile = this.options.blockchain || this.options.blockchainOts;
|
|
841
|
+
const writeToFile = this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp;
|
|
833
842
|
// Create appropriate output writer
|
|
834
843
|
let writer;
|
|
835
844
|
const positionRef = { current: this.currentPosition };
|
|
@@ -911,9 +920,11 @@ class ZipCreator {
|
|
|
911
920
|
if (this.hashAccumulator && entry.sha256) {
|
|
912
921
|
const filename = entry.filename || '';
|
|
913
922
|
// Skip blockchain metadata files
|
|
914
|
-
if (filename !==
|
|
915
|
-
filename !==
|
|
916
|
-
filename !==
|
|
923
|
+
if (filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
|
|
924
|
+
filename !== ots_1.TIMESTAMP_METADATA &&
|
|
925
|
+
filename !== ots_1.TIMESTAMP_SUBMITTED &&
|
|
926
|
+
filename !== zipstamp_server_1.SUBMIT_METADATA &&
|
|
927
|
+
filename !== zipstamp_server_1.TIMESTAMP_METADATA) {
|
|
917
928
|
const hashBuffer = Buffer.from(entry.sha256, 'hex');
|
|
918
929
|
this.hashAccumulator.addHash(hashBuffer);
|
|
919
930
|
if (this.options.verbose) {
|
|
@@ -978,9 +989,11 @@ class ZipCreator {
|
|
|
978
989
|
for (let index = 0; index < entryCnt; index++) {
|
|
979
990
|
const entry = zipEntries[index];
|
|
980
991
|
// Filter out metadata entries (handled separately in handleTokenization)
|
|
981
|
-
if (entry.filename ===
|
|
982
|
-
entry.filename ===
|
|
983
|
-
entry.filename ===
|
|
992
|
+
if (entry.filename === neozip_blockchain_1.TOKENIZED_METADATA ||
|
|
993
|
+
entry.filename === ots_1.TIMESTAMP_METADATA ||
|
|
994
|
+
entry.filename === ots_1.TIMESTAMP_SUBMITTED ||
|
|
995
|
+
entry.filename === zipstamp_server_1.SUBMIT_METADATA ||
|
|
996
|
+
entry.filename === zipstamp_server_1.TIMESTAMP_METADATA) {
|
|
984
997
|
zipEntries.splice(index, 1);
|
|
985
998
|
entryCnt--;
|
|
986
999
|
index--;
|
|
@@ -1059,9 +1072,11 @@ class ZipCreator {
|
|
|
1059
1072
|
if (this.hashAccumulator) {
|
|
1060
1073
|
const filename = entry.filename || '';
|
|
1061
1074
|
// Skip blockchain metadata files
|
|
1062
|
-
if (filename !==
|
|
1063
|
-
filename !==
|
|
1064
|
-
filename !==
|
|
1075
|
+
if (filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
|
|
1076
|
+
filename !== ots_1.TIMESTAMP_METADATA &&
|
|
1077
|
+
filename !== ots_1.TIMESTAMP_SUBMITTED &&
|
|
1078
|
+
filename !== zipstamp_server_1.SUBMIT_METADATA &&
|
|
1079
|
+
filename !== zipstamp_server_1.TIMESTAMP_METADATA) {
|
|
1065
1080
|
this.hashAccumulator.addHash(hash);
|
|
1066
1081
|
if (this.options.verbose) {
|
|
1067
1082
|
(0, utils_1.logDebug)(`Added SHA-256 hash to accumulator for ${filename}`, this.options);
|
|
@@ -1139,9 +1154,11 @@ class ZipCreator {
|
|
|
1139
1154
|
// Filter out blockchain metadata files to ensure consistent Merkle Root calculation
|
|
1140
1155
|
const contentEntries = entries.filter(entry => {
|
|
1141
1156
|
const filename = entry.filename || '';
|
|
1142
|
-
return filename !==
|
|
1143
|
-
filename !==
|
|
1144
|
-
filename !==
|
|
1157
|
+
return filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
|
|
1158
|
+
filename !== ots_1.TIMESTAMP_METADATA &&
|
|
1159
|
+
filename !== ots_1.TIMESTAMP_SUBMITTED &&
|
|
1160
|
+
filename !== zipstamp_server_1.SUBMIT_METADATA &&
|
|
1161
|
+
filename !== zipstamp_server_1.TIMESTAMP_METADATA;
|
|
1145
1162
|
});
|
|
1146
1163
|
// Add SHA-256 hashes to accumulator
|
|
1147
1164
|
for (const entry of contentEntries) {
|
|
@@ -1158,12 +1175,13 @@ class ZipCreator {
|
|
|
1158
1175
|
let tokenMeta = null;
|
|
1159
1176
|
let tokenInfoEntry = null;
|
|
1160
1177
|
let otsMetaEntry = null;
|
|
1178
|
+
let zipstampMetaEntry = null;
|
|
1161
1179
|
let merkleRoot = null;
|
|
1162
1180
|
if (this.options.blockchain) {
|
|
1163
1181
|
// Check for wallet passkey AFTER compression is complete
|
|
1164
1182
|
// Priority: -w option > wallet.json > environment variable
|
|
1165
1183
|
// Don't show error yet - we'll prompt user if key is missing
|
|
1166
|
-
const walletPasskey = (0,
|
|
1184
|
+
const walletPasskey = (0, blockchain_1.getWalletPasskey)(this.options.walletKey, false);
|
|
1167
1185
|
if (!walletPasskey) {
|
|
1168
1186
|
// Show error message and prompt user
|
|
1169
1187
|
console.error('\n❌ Error: Wallet private key is required for blockchain operations');
|
|
@@ -1186,6 +1204,7 @@ class ZipCreator {
|
|
|
1186
1204
|
(0, utils_1.log)('⚠️ Continuing without blockchain tokenization (ZIP file is already created)...', this.options);
|
|
1187
1205
|
this.options.blockchain = false;
|
|
1188
1206
|
this.options.blockchainOts = false;
|
|
1207
|
+
this.options.blockchainZipstamp = false;
|
|
1189
1208
|
return; // Skip tokenization, ZIP is already complete
|
|
1190
1209
|
}
|
|
1191
1210
|
else {
|
|
@@ -1276,7 +1295,7 @@ class ZipCreator {
|
|
|
1276
1295
|
// Always display network when tokenization is enabled
|
|
1277
1296
|
console.log(`🌐 Network: ${network}`);
|
|
1278
1297
|
// Get network config for contract address and version info
|
|
1279
|
-
const networkConfig = (0,
|
|
1298
|
+
const networkConfig = (0, neozip_blockchain_1.getNetworkByName)(network);
|
|
1280
1299
|
let contractAddress;
|
|
1281
1300
|
let networkChainId;
|
|
1282
1301
|
let contractVersion;
|
|
@@ -1290,7 +1309,7 @@ class ZipCreator {
|
|
|
1290
1309
|
}
|
|
1291
1310
|
else {
|
|
1292
1311
|
// Fallback to default (Base Sepolia)
|
|
1293
|
-
const defaultConfig = (0,
|
|
1312
|
+
const defaultConfig = (0, neozip_blockchain_1.getContractConfig)(84532);
|
|
1294
1313
|
contractAddress = defaultConfig.address;
|
|
1295
1314
|
networkChainId = defaultConfig.chainId;
|
|
1296
1315
|
const versionStr = defaultConfig.version || '0';
|
|
@@ -1300,8 +1319,8 @@ class ZipCreator {
|
|
|
1300
1319
|
// Display contract address and version right after network
|
|
1301
1320
|
console.log(`📄 Contract: ${contractAddress}`);
|
|
1302
1321
|
console.log(`🔢 Version: ${contractVersion}`);
|
|
1303
|
-
if (!(0,
|
|
1304
|
-
const supportedNetworks = (0,
|
|
1322
|
+
if (!(0, blockchain_1.isSupportedNetwork)(network)) {
|
|
1323
|
+
const supportedNetworks = (0, neozip_blockchain_1.getSupportedNetworkNames)();
|
|
1305
1324
|
console.error(`❌ Error: Unsupported network: ${network}`);
|
|
1306
1325
|
console.error(` Currently supported networks: ${supportedNetworks.join(', ')}`);
|
|
1307
1326
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR);
|
|
@@ -1309,7 +1328,7 @@ class ZipCreator {
|
|
|
1309
1328
|
let minter = null;
|
|
1310
1329
|
try {
|
|
1311
1330
|
// Initialize blockchain minter
|
|
1312
|
-
minter = new
|
|
1331
|
+
minter = new neozip_blockchain_1.ZipkitMinter(merkleRoot, {
|
|
1313
1332
|
network: network,
|
|
1314
1333
|
walletPrivateKey: this.options.walletPasskey,
|
|
1315
1334
|
verbose: this.options.verbose,
|
|
@@ -1380,7 +1399,7 @@ class ZipCreator {
|
|
|
1380
1399
|
}
|
|
1381
1400
|
else if (userChoice.action === 'mint-new') {
|
|
1382
1401
|
// Mint new token
|
|
1383
|
-
const mintResult = await (0,
|
|
1402
|
+
const mintResult = await (0, blockchain_1.handleTokenMinting)(minter, this.zip, this.options.nonInteractive || false, 0);
|
|
1384
1403
|
if (mintResult.success && mintResult.tokenInfo) {
|
|
1385
1404
|
tokenMeta = mintResult.tokenInfo;
|
|
1386
1405
|
// Add token metadata directly to ZIP (after compression, at the end)
|
|
@@ -1417,7 +1436,7 @@ class ZipCreator {
|
|
|
1417
1436
|
}
|
|
1418
1437
|
else {
|
|
1419
1438
|
// No existing tokens, mint new one
|
|
1420
|
-
const mintResult = await (0,
|
|
1439
|
+
const mintResult = await (0, blockchain_1.handleTokenMinting)(minter, this.zip, this.options.nonInteractive || false, 0);
|
|
1421
1440
|
if (mintResult.success && mintResult.tokenInfo) {
|
|
1422
1441
|
tokenMeta = mintResult.tokenInfo;
|
|
1423
1442
|
// Add token metadata directly to ZIP (after compression, at the end)
|
|
@@ -1537,16 +1556,16 @@ class ZipCreator {
|
|
|
1537
1556
|
console.log(`📋 Merkle Root: ${merkleRoot}`);
|
|
1538
1557
|
// Create actual OpenTimestamp proof
|
|
1539
1558
|
try {
|
|
1540
|
-
const otsProof = await (0,
|
|
1559
|
+
const otsProof = await (0, ots_1.createTimestamp)(merkleRoot, { debug: this.options.verbose });
|
|
1541
1560
|
if (!otsProof) {
|
|
1542
1561
|
throw new Error('Failed to create OpenTimestamp proof');
|
|
1543
1562
|
}
|
|
1544
1563
|
console.log('📄 OpenTimestamp metadata prepared');
|
|
1545
1564
|
// Use the createOtsMetadataEntry function like in the example
|
|
1546
|
-
const metaEntry = (0,
|
|
1565
|
+
const metaEntry = (0, ots_1.createOtsMetadataEntry)(this.zip, otsProof);
|
|
1547
1566
|
if (metaEntry) {
|
|
1548
1567
|
// Ensure the filename is set correctly
|
|
1549
|
-
metaEntry.filename =
|
|
1568
|
+
metaEntry.filename = ots_1.TIMESTAMP_SUBMITTED;
|
|
1550
1569
|
// Ensure OTS entry uses STORED compression (no compression for small metadata file)
|
|
1551
1570
|
metaEntry.cmpMethod = 0; // STORED
|
|
1552
1571
|
metaEntry.compressedSize = metaEntry.fileBuffer?.length || metaEntry.uncompressedSize || 0;
|
|
@@ -1586,10 +1605,143 @@ class ZipCreator {
|
|
|
1586
1605
|
}
|
|
1587
1606
|
}
|
|
1588
1607
|
}
|
|
1608
|
+
else if (this.options.blockchainZipstamp) {
|
|
1609
|
+
// Handle Zipstamp timestamp for blockchain
|
|
1610
|
+
if (this.options.debug) {
|
|
1611
|
+
(0, utils_1.logDebug)('Zipstamp process starting...', this.options);
|
|
1612
|
+
}
|
|
1613
|
+
console.log('🔗 Zipstamp: Creating timestamp proof on blockchain...');
|
|
1614
|
+
// Calculate merkle root (reuse same logic as OTS)
|
|
1615
|
+
let merkleRoot = null;
|
|
1616
|
+
if (this.hashAccumulator && this.hashAccumulator.leafCount() > 0) {
|
|
1617
|
+
merkleRoot = this.hashAccumulator.merkleRoot();
|
|
1618
|
+
if (this.options.verbose) {
|
|
1619
|
+
console.log(`✅ Calculated merkle root from ${this.hashAccumulator.leafCount()} accumulated SHA-256 hashes`);
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
else {
|
|
1623
|
+
let entriesForMerkle = [];
|
|
1624
|
+
const zipEntries = this.zip.getDirectory();
|
|
1625
|
+
if (zipEntries.length > 0) {
|
|
1626
|
+
entriesForMerkle = zipEntries;
|
|
1627
|
+
}
|
|
1628
|
+
else {
|
|
1629
|
+
try {
|
|
1630
|
+
if (fs.existsSync(this.archiveName)) {
|
|
1631
|
+
const zipkit = new node_1.default();
|
|
1632
|
+
if (this.options.inMemory) {
|
|
1633
|
+
const zipBuffer = fs.readFileSync(this.archiveName);
|
|
1634
|
+
zipkit.loadZip(zipBuffer);
|
|
1635
|
+
}
|
|
1636
|
+
else {
|
|
1637
|
+
await zipkit.loadZipFile(this.archiveName);
|
|
1638
|
+
}
|
|
1639
|
+
entriesForMerkle = zipkit.getDirectory() || [];
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
entriesForMerkle = await this.zip.getDirectory() || [];
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
catch (error) {
|
|
1646
|
+
console.error('❌ Error loading ZIP file for merkle root calculation:', error instanceof Error ? error.message : String(error));
|
|
1647
|
+
entriesForMerkle = await this.zip.getDirectory() || [];
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
merkleRoot = this.calculateMerkleRootFromEntries(entriesForMerkle);
|
|
1651
|
+
}
|
|
1652
|
+
if (!merkleRoot) {
|
|
1653
|
+
console.error('❌ Error calculating merkle root for Zipstamp');
|
|
1654
|
+
console.error(' Make sure files have been compressed with SHA-256 hashes.');
|
|
1655
|
+
if (this.options.verbose) {
|
|
1656
|
+
const hashCount = this.hashAccumulator ? this.hashAccumulator.leafCount() : 0;
|
|
1657
|
+
console.error(` Found ${hashCount} accumulated SHA-256 hashes`);
|
|
1658
|
+
}
|
|
1659
|
+
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BAD_ARCHIVE_FORMAT);
|
|
1660
|
+
}
|
|
1661
|
+
if (this.options.verbose && this.hashAccumulator) {
|
|
1662
|
+
console.log(`✅ Calculated merkle root from ${this.hashAccumulator.leafCount()} accumulated SHA-256 hashes`);
|
|
1663
|
+
}
|
|
1664
|
+
if (merkleRoot) {
|
|
1665
|
+
console.log(`📋 Merkle Root: ${merkleRoot}`);
|
|
1666
|
+
const recipientEmail = this.options.timestampEmail ||
|
|
1667
|
+
process.env.NEOZIP_TIMESTAMP_EMAIL ||
|
|
1668
|
+
ConfigStore_1.ConfigStore.getConfig().timestampEmail;
|
|
1669
|
+
console.log('🔗 Submitting hash digest to ZipStamp server...');
|
|
1670
|
+
console.log(` Zipstamp Server: ${(0, zipstamp_server_1.getZipStampServerUrl)()}`);
|
|
1671
|
+
console.log(`📧 Email: ${recipientEmail || '(none set)'}`);
|
|
1672
|
+
try {
|
|
1673
|
+
const zipstampMetadata = await (0, zipstamp_server_1.createTimestamp)(merkleRoot, {
|
|
1674
|
+
recipientEmail: recipientEmail || undefined,
|
|
1675
|
+
debug: this.options.verbose
|
|
1676
|
+
});
|
|
1677
|
+
if (!zipstampMetadata) {
|
|
1678
|
+
throw new Error('Failed to create Zipstamp timestamp');
|
|
1679
|
+
}
|
|
1680
|
+
console.log('📄 Zipstamp metadata prepared');
|
|
1681
|
+
const metaEntry = (0, zipstamp_server_1.createTimestampMetadataEntry)(this.zip, zipstampMetadata);
|
|
1682
|
+
if (metaEntry) {
|
|
1683
|
+
// createTimestampMetadataEntry sets filename based on status (TS-SUBMIT.NZIP or TIMESTAMP.NZIP)
|
|
1684
|
+
metaEntry.cmpMethod = 0; // STORED
|
|
1685
|
+
metaEntry.compressedSize = metaEntry.fileBuffer?.length || metaEntry.uncompressedSize || 0;
|
|
1686
|
+
if (this.options.verbose) {
|
|
1687
|
+
console.log(`📂 Final timestamp entry: ${metaEntry.filename}`);
|
|
1688
|
+
console.log(`📏 Final timestamp entry size: ${metaEntry.fileBuffer?.length || metaEntry.uncompressedSize || 0} bytes`);
|
|
1689
|
+
}
|
|
1690
|
+
console.log('✅ Zipstamp proof created and queued for inclusion');
|
|
1691
|
+
const isConfirmed = (metaEntry.filename || '').includes('TIMESTAMP') && !(metaEntry.filename || '').includes('TS-SUBMIT');
|
|
1692
|
+
console.log(isConfirmed
|
|
1693
|
+
? ' Timestamp proof is recorded on the blockchain.'
|
|
1694
|
+
: ' Timestamp proof will be recorded on the blockchain once confirmed.');
|
|
1695
|
+
metaEntry.localHdrOffset = this.currentPosition;
|
|
1696
|
+
if (this.zipWriter) {
|
|
1697
|
+
this.zipWriter.entryPositions.set(metaEntry.filename, this.currentPosition);
|
|
1698
|
+
}
|
|
1699
|
+
const localHdr = metaEntry.createLocalHdr();
|
|
1700
|
+
if (this.options.verbose) {
|
|
1701
|
+
(0, utils_1.log)(`📝 Writing Zipstamp entry: ${metaEntry.filename} at offset ${this.currentPosition}`, this.options);
|
|
1702
|
+
(0, utils_1.log)(`📊 Zipstamp entry size: ${metaEntry.fileBuffer?.length || 0} bytes`, this.options);
|
|
1703
|
+
}
|
|
1704
|
+
await this.writeChunk(localHdr);
|
|
1705
|
+
if (metaEntry.fileBuffer) {
|
|
1706
|
+
await this.writeChunk(metaEntry.fileBuffer);
|
|
1707
|
+
}
|
|
1708
|
+
zipstampMetaEntry = metaEntry;
|
|
1709
|
+
}
|
|
1710
|
+
else {
|
|
1711
|
+
console.warn('⚠️ Warning: Failed to create Zipstamp metadata entry');
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
catch (error) {
|
|
1715
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1716
|
+
console.error('❌ Failed to create Zipstamp proof:', errorMessage);
|
|
1717
|
+
const isValidationOrEmailError = errorMessage.toLowerCase().includes('validation') ||
|
|
1718
|
+
errorMessage.toLowerCase().includes('email') ||
|
|
1719
|
+
errorMessage.toLowerCase().includes('verify');
|
|
1720
|
+
if (isValidationOrEmailError) {
|
|
1721
|
+
console.error('');
|
|
1722
|
+
if (recipientEmail) {
|
|
1723
|
+
console.error(` Email used: ${recipientEmail}`);
|
|
1724
|
+
console.error('');
|
|
1725
|
+
}
|
|
1726
|
+
else {
|
|
1727
|
+
console.error(' No email was set (use --timestamp-email, NEOZIP_TIMESTAMP_EMAIL, or neozip verify-email).');
|
|
1728
|
+
console.error('');
|
|
1729
|
+
}
|
|
1730
|
+
console.error('💡 Zipstamp requires a verified email. Run:');
|
|
1731
|
+
console.error(' neozip verify-email');
|
|
1732
|
+
console.error('');
|
|
1733
|
+
console.error(' Or use: --timestamp-email <your-verified-email>');
|
|
1734
|
+
console.error(' Or set: NEOZIP_TIMESTAMP_EMAIL environment variable');
|
|
1735
|
+
console.error('');
|
|
1736
|
+
}
|
|
1737
|
+
throw error;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1589
1741
|
}
|
|
1590
1742
|
async finalize() {
|
|
1591
1743
|
// Check if this is in-memory non-blockchain mode (needs special handling)
|
|
1592
|
-
if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts) {
|
|
1744
|
+
if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts && !this.options.blockchainZipstamp) {
|
|
1593
1745
|
// For in-memory non-blockchain mode, write complete ZIP file from buffer
|
|
1594
1746
|
// Metadata should already be in the buffer (added via writeChunk() in handleTokenization())
|
|
1595
1747
|
const bufferWriter = this.zip.bufferWriter;
|
|
@@ -1752,6 +1904,9 @@ async function testArchiveIntegrity(archiveName, options) {
|
|
|
1752
1904
|
try {
|
|
1753
1905
|
// Always show when integrity testing starts
|
|
1754
1906
|
(0, utils_1.log)(`\n🧪 Testing archive integrity: ${archiveName}`, options);
|
|
1907
|
+
if (options.blockchainZipstamp) {
|
|
1908
|
+
(0, utils_1.log)(` (Validating file integrity only; timestamp not yet confirmed on blockchain)`, options);
|
|
1909
|
+
}
|
|
1755
1910
|
// Import child_process for shelling out
|
|
1756
1911
|
const { spawn } = require('child_process');
|
|
1757
1912
|
// Use the installed neounzip command directly (works in both dev and installed)
|
|
@@ -1760,6 +1915,11 @@ async function testArchiveIntegrity(archiveName, options) {
|
|
|
1760
1915
|
return new Promise((resolve) => {
|
|
1761
1916
|
// Build neounzip command arguments
|
|
1762
1917
|
const args = ['-t'];
|
|
1918
|
+
// For Zipstamp timestamped files: skip blockchain verification during integrity test.
|
|
1919
|
+
// We only validate file integrity (SHA-256); timestamp is pending and not yet minted.
|
|
1920
|
+
if (options.blockchainZipstamp) {
|
|
1921
|
+
args.push('--skip-blockchain');
|
|
1922
|
+
}
|
|
1763
1923
|
// Add password if encryption is enabled
|
|
1764
1924
|
if (options.encrypt && options.password) {
|
|
1765
1925
|
args.push('-P', options.password);
|
|
@@ -1806,6 +1966,10 @@ async function testArchiveIntegrity(archiveName, options) {
|
|
|
1806
1966
|
else {
|
|
1807
1967
|
(0, utils_1.log)(`✅ Archive integrity test passed`, options);
|
|
1808
1968
|
}
|
|
1969
|
+
// For Zipstamp: clarify that timestamp is not validated and not minted
|
|
1970
|
+
if (options.blockchainZipstamp) {
|
|
1971
|
+
(0, utils_1.log)(` Note: File integrity validated. Timestamp is pending (not yet confirmed on blockchain).`, options);
|
|
1972
|
+
}
|
|
1809
1973
|
resolve(true);
|
|
1810
1974
|
}
|
|
1811
1975
|
else {
|
|
@@ -1910,7 +2074,7 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
1910
2074
|
}
|
|
1911
2075
|
(0, utils_1.log)(` Found ${entries.length} entries in ZIP`, options);
|
|
1912
2076
|
// Check for existing token metadata (ignore per requirement 3a)
|
|
1913
|
-
const hasTokenMetadata = entries.some((e) => e.filename ===
|
|
2077
|
+
const hasTokenMetadata = entries.some((e) => e.filename === neozip_blockchain_1.TOKENIZED_METADATA);
|
|
1914
2078
|
if (hasTokenMetadata && options.verbose) {
|
|
1915
2079
|
(0, utils_1.log)(` Note: ZIP already contains token metadata (will create new token)`, options);
|
|
1916
2080
|
}
|
|
@@ -1922,9 +2086,11 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
1922
2086
|
for (const entry of entries) {
|
|
1923
2087
|
const filename = entry.filename || '';
|
|
1924
2088
|
// Skip metadata entries and directories
|
|
1925
|
-
if (filename ===
|
|
1926
|
-
filename ===
|
|
1927
|
-
filename ===
|
|
2089
|
+
if (filename === neozip_blockchain_1.TOKENIZED_METADATA ||
|
|
2090
|
+
filename === ots_1.TIMESTAMP_METADATA ||
|
|
2091
|
+
filename === ots_1.TIMESTAMP_SUBMITTED ||
|
|
2092
|
+
filename === zipstamp_server_1.SUBMIT_METADATA ||
|
|
2093
|
+
filename === zipstamp_server_1.TIMESTAMP_METADATA ||
|
|
1928
2094
|
entry.isDirectory) {
|
|
1929
2095
|
continue;
|
|
1930
2096
|
}
|
|
@@ -2080,7 +2246,7 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
2080
2246
|
}
|
|
2081
2247
|
// Mint new token before finalizing ZIP (so we can add metadata)
|
|
2082
2248
|
// Check for wallet passkey - don't show error yet
|
|
2083
|
-
const walletPasskey = (0,
|
|
2249
|
+
const walletPasskey = (0, blockchain_1.getWalletPasskey)(options.walletKey, false);
|
|
2084
2250
|
if (!walletPasskey) {
|
|
2085
2251
|
// Show error message and prompt user
|
|
2086
2252
|
console.error('❌ Error: Wallet private key is required for blockchain operations');
|
|
@@ -2118,10 +2284,10 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
2118
2284
|
if (walletPasskey) {
|
|
2119
2285
|
(0, utils_1.log)(` Minting new token on blockchain...`, options);
|
|
2120
2286
|
const network = options.network || 'base-sepolia';
|
|
2121
|
-
if (!(0,
|
|
2287
|
+
if (!(0, blockchain_1.isSupportedNetwork)(network)) {
|
|
2122
2288
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR, `Error: Unsupported network: ${network}`);
|
|
2123
2289
|
}
|
|
2124
|
-
const minter = new
|
|
2290
|
+
const minter = new neozip_blockchain_1.ZipkitMinter(merkleRoot, {
|
|
2125
2291
|
network,
|
|
2126
2292
|
walletPrivateKey: walletPasskey,
|
|
2127
2293
|
verbose: options.verbose,
|
|
@@ -2131,12 +2297,12 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
2131
2297
|
// Create a temporary ZipkitNode instance for handleTokenMinting
|
|
2132
2298
|
// (it needs a zip instance, but we'll add metadata manually)
|
|
2133
2299
|
const tempZip = new node_1.default();
|
|
2134
|
-
const mintResult = await (0,
|
|
2300
|
+
const mintResult = await (0, blockchain_1.handleTokenMinting)(minter, tempZip, options.nonInteractive || false, 0);
|
|
2135
2301
|
if (mintResult.success && mintResult.tokenInfo) {
|
|
2136
2302
|
// Add token metadata entry before central directory
|
|
2137
2303
|
const tokenContent = JSON.stringify(mintResult.tokenInfo, null, 2);
|
|
2138
2304
|
const tokenBuffer = Buffer.from(tokenContent, 'utf8');
|
|
2139
|
-
const tokenEntry = new neozipkit_1.ZipEntry(
|
|
2305
|
+
const tokenEntry = new neozipkit_1.ZipEntry(neozip_blockchain_1.TOKENIZED_METADATA, null, false);
|
|
2140
2306
|
tokenEntry.timeDateDOS = tokenEntry.setDateTime(new Date());
|
|
2141
2307
|
tokenEntry.compressedSize = tokenBuffer.length;
|
|
2142
2308
|
tokenEntry.uncompressedSize = tokenBuffer.length;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Upgrade Zipstamp timestamp from pending (TS-SUBMIT.NZIP) to confirmed (TIMESTAMP.NZIP)
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.upgradeZipForTimestamp = upgradeZipForTimestamp;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
const node_1 = __importDefault(require("neozipkit/node"));
|
|
47
|
+
const node_2 = require("neozipkit/node");
|
|
48
|
+
const zipstamp_server_1 = require("neozip-blockchain/zipstamp-server");
|
|
49
|
+
const exit_codes_1 = require("../exit-codes");
|
|
50
|
+
/**
|
|
51
|
+
* Extract timestamp metadata from a ZIP entry.
|
|
52
|
+
* Tries the library's extractTimestampData first; if it fails (e.g. file-based ZIP),
|
|
53
|
+
* fall back to extracting to a temp file and parsing JSON.
|
|
54
|
+
*/
|
|
55
|
+
async function extractTimestampMetadata(zip, entry) {
|
|
56
|
+
let metadata = await (0, zipstamp_server_1.extractTimestampData)(zip, entry);
|
|
57
|
+
if (metadata)
|
|
58
|
+
return metadata;
|
|
59
|
+
// Fallback for file-based ZIPs where zip.extract() may not work
|
|
60
|
+
try {
|
|
61
|
+
const tmpPath = path.join(os.tmpdir(), `neozip-upgrade-meta-${Date.now()}.json`);
|
|
62
|
+
await zip.extractToFile(entry, tmpPath, { skipHashCheck: true });
|
|
63
|
+
try {
|
|
64
|
+
const buf = fs.readFileSync(tmpPath);
|
|
65
|
+
return JSON.parse(buf.toString('utf-8'));
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
if (fs.existsSync(tmpPath))
|
|
69
|
+
fs.unlinkSync(tmpPath);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Upgrade a ZIP file with pending Zipstamp timestamp to confirmed status.
|
|
78
|
+
* Replaces TS-SUBMIT.NZIP with TIMESTAMP.NZIP when the batch is confirmed on the blockchain.
|
|
79
|
+
*/
|
|
80
|
+
async function upgradeZipForTimestamp(inputPath, outputPath, options = {}) {
|
|
81
|
+
const { wait = false, verbose = false, debug = false } = options;
|
|
82
|
+
if (!fs.existsSync(inputPath)) {
|
|
83
|
+
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_FIND_ARCHIVE, `Error: ZIP file not found: ${inputPath}`);
|
|
84
|
+
}
|
|
85
|
+
const zip = new node_1.default();
|
|
86
|
+
await zip.loadZipFile(inputPath);
|
|
87
|
+
const entries = zip.getDirectory() || [];
|
|
88
|
+
const metadataResult = (0, zipstamp_server_1.findMetadataEntry)(entries);
|
|
89
|
+
if (!metadataResult) {
|
|
90
|
+
console.log('No Zipstamp timestamp found in ZIP file');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (metadataResult.type === 'confirmed') {
|
|
94
|
+
console.log('✓ Timestamp already confirmed - no upgrade needed');
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const metadata = await extractTimestampMetadata(zip, metadataResult.entry);
|
|
98
|
+
if (!metadata || !metadata.digest) {
|
|
99
|
+
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BAD_ARCHIVE_FORMAT, 'Error: Failed to extract timestamp metadata');
|
|
100
|
+
}
|
|
101
|
+
if (!(0, zipstamp_server_1.shouldUpgrade)(metadata, metadataResult.type)) {
|
|
102
|
+
console.log('✓ Timestamp does not need upgrade');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const digest = metadata.digest;
|
|
106
|
+
const chainId = metadata.chainId && metadata.chainId > 0 ? metadata.chainId : undefined;
|
|
107
|
+
const batchId = metadata.batchId ?? undefined;
|
|
108
|
+
let verified = null;
|
|
109
|
+
if (wait) {
|
|
110
|
+
if (verbose || debug)
|
|
111
|
+
console.log('Polling for confirmation (--wait)...');
|
|
112
|
+
verified = await (0, zipstamp_server_1.pollForConfirmation)(digest, chainId, batchId, 300000, 5000, { debug });
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const verifyRes = await (0, zipstamp_server_1.verifyDigest)(digest, chainId, batchId, undefined, { debug });
|
|
116
|
+
if (verifyRes.verified) {
|
|
117
|
+
verified = verifyRes;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (!verified || !verified.verified) {
|
|
121
|
+
console.log('⏳ Timestamp not yet confirmed on blockchain');
|
|
122
|
+
console.log(' Run with --wait to poll until confirmed, or try again later');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
console.log('✓ Timestamp confirmed on blockchain');
|
|
126
|
+
if (verified.transactionHash && (verbose || debug)) {
|
|
127
|
+
console.log(` Transaction: ${verified.transactionHash}`);
|
|
128
|
+
}
|
|
129
|
+
const confirmedMetadata = {
|
|
130
|
+
...metadata,
|
|
131
|
+
status: 'confirmed',
|
|
132
|
+
merkleProof: verified.merkleProof ?? metadata.merkleProof,
|
|
133
|
+
merkleRoot: verified.merkleRoot ?? metadata.merkleRoot,
|
|
134
|
+
transactionHash: verified.transactionHash ?? metadata.transactionHash,
|
|
135
|
+
blockNumber: verified.blockNumber ?? metadata.blockNumber,
|
|
136
|
+
timestamp: verified.timestamp ?? metadata.timestamp
|
|
137
|
+
};
|
|
138
|
+
const metadataFiles = (0, zipstamp_server_1.getMetadataFileNames)();
|
|
139
|
+
const outPath = outputPath ?? inputPath.replace(/(\.nzip|\.zip)$/i, '-upgrade$1');
|
|
140
|
+
const tempDir = path.dirname(outPath) || '.';
|
|
141
|
+
const tempPath = path.join(tempDir, `.neozip-upgrade-${Date.now()}.tmp`);
|
|
142
|
+
try {
|
|
143
|
+
const zipCopy = new node_2.ZipCopyNode(new node_1.default());
|
|
144
|
+
const { destPath, dataEndOffset, copiedEntries } = await zipCopy.copyZipEntriesOnly(inputPath, tempPath, {
|
|
145
|
+
entryFilter: (entry) => !metadataFiles.includes(entry.filename || '')
|
|
146
|
+
});
|
|
147
|
+
const newEntry = (0, zipstamp_server_1.createTimestampMetadataEntry)(zip, confirmedMetadata);
|
|
148
|
+
if (!newEntry) {
|
|
149
|
+
throw new Error('Failed to create timestamp metadata entry');
|
|
150
|
+
}
|
|
151
|
+
newEntry.localHdrOffset = dataEndOffset;
|
|
152
|
+
newEntry.cmpMethod = 0;
|
|
153
|
+
newEntry.compressedSize = newEntry.fileBuffer?.length ?? newEntry.uncompressedSize ?? 0;
|
|
154
|
+
const localHdr = newEntry.createLocalHdr();
|
|
155
|
+
const data = newEntry.fileBuffer ?? Buffer.alloc(0);
|
|
156
|
+
const fd = fs.openSync(destPath, 'r+');
|
|
157
|
+
try {
|
|
158
|
+
fs.writeSync(fd, localHdr, 0, localHdr.length, dataEndOffset);
|
|
159
|
+
fs.writeSync(fd, data, 0, data.length, dataEndOffset + localHdr.length);
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
fs.closeSync(fd);
|
|
163
|
+
}
|
|
164
|
+
const allEntries = [...copiedEntries, newEntry];
|
|
165
|
+
zipCopy.writeCentralDirectoryAndEOCD(destPath, allEntries, { zipComment: '' });
|
|
166
|
+
fs.renameSync(destPath, outPath);
|
|
167
|
+
console.log(`✓ Upgraded ZIP written to: ${outPath}`);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
if (fs.existsSync(tempPath)) {
|
|
171
|
+
try {
|
|
172
|
+
fs.unlinkSync(tempPath);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Ignore cleanup errors
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
179
|
+
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.CANT_WRITE_ARCHIVE, `Error upgrading ZIP: ${msg}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=upgradeZip.js.map
|