7zip-native 0.0.8 → 0.0.10
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/README.md +44 -12
- package/bench/compare.mts +25 -11
- package/bench/folder-concurrency.mts +5 -12
- package/bench/multiprocess-extract.cjs +334 -0
- package/dist/index.cjs +192 -99
- package/dist/index.d.cts +10 -9
- package/dist/index.d.mts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.mjs +194 -101
- package/native/addon.cpp +1399 -71
- package/package.json +4 -2
- package/patches/deflate-input-buffer-size.patch +47 -0
- package/prebuilds/darwin-arm64/7zip_native.node +0 -0
- package/prebuilds/darwin-arm64/lib7z.dylib +0 -0
- package/prebuilds/darwin-x64/7zip_native.node +0 -0
- package/prebuilds/darwin-x64/lib7z.dylib +0 -0
- package/prebuilds/linux-arm/7z.so +0 -0
- package/prebuilds/linux-arm/7zip_native.node +0 -0
- package/prebuilds/linux-arm64/7z.so +0 -0
- package/prebuilds/linux-arm64/7zip_native.node +0 -0
- package/prebuilds/linux-ia32/7z.so +0 -0
- package/prebuilds/linux-ia32/7zip_native.node +0 -0
- package/prebuilds/linux-x64/7z.so +0 -0
- package/prebuilds/linux-x64/7zip_native.node +0 -0
- package/prebuilds/win32-arm64/7z.dll +0 -0
- package/prebuilds/win32-arm64/7zip_native.node +0 -0
- package/prebuilds/win32-x64/7z.dll +0 -0
- package/prebuilds/win32-x64/7zip_native.node +0 -0
- package/scripts/build-native.mjs +22 -1
- package/vendor/7zip/CPP/7zip/Archive/Archive2.def +1 -0
- package/vendor/7zip/CPP/7zip/Bundles/Format7zF/_o/7z.so +0 -0
- package/vendor/7zip/CPP/7zip/Bundles/Format7zF/_o/Alloc.o +0 -0
- package/vendor/7zip/CPP/7zip/Bundles/Format7zF/_o/DeflateDecoder.o +0 -0
- package/vendor/7zip/CPP/7zip/Compress/DeflateDecoder.cpp +15 -1
package/dist/index.cjs
CHANGED
|
@@ -20,6 +20,9 @@ class ArchiveError extends Error {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const defaultMaxOutputBytes = 4n * 1024n * 1024n * 1024n;
|
|
23
|
+
const defaultDeflateBufferSize = 32 * 1024;
|
|
24
|
+
const minDeflateBufferSize = 4 * 1024;
|
|
25
|
+
const maxDeflateBufferSize = 2 * 1024 * 1024;
|
|
23
26
|
function normalizeMaxBytes(value, label) {
|
|
24
27
|
if (value === undefined) {
|
|
25
28
|
return defaultMaxOutputBytes;
|
|
@@ -159,6 +162,19 @@ async function assertReplaceableOutput(filePath) {
|
|
|
159
162
|
}
|
|
160
163
|
}
|
|
161
164
|
}
|
|
165
|
+
async function assertFolderOutputDoesNotExist(filePath) {
|
|
166
|
+
try {
|
|
167
|
+
await promises.lstat(filePath);
|
|
168
|
+
const error = new Error(`Output file already exists: ${filePath}`);
|
|
169
|
+
Object.assign(error, { code: 'EEXIST' });
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
if (error.code !== 'ENOENT') {
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
162
178
|
async function assertOutputDoesNotExist(filePath) {
|
|
163
179
|
try {
|
|
164
180
|
await promises.lstat(filePath);
|
|
@@ -188,7 +204,7 @@ async function normalizeCreateEntry(entry) {
|
|
|
188
204
|
if (details.isSymbolicLink() || !details.isFile()) {
|
|
189
205
|
throw new ArchiveError('ERR_ARCHIVE_CREATE', `Archive creation source is not a regular file: ${sourcePath}`);
|
|
190
206
|
}
|
|
191
|
-
return { sourcePath, path: internalPath };
|
|
207
|
+
return { sourcePath, path: internalPath, mtimeMs: details.mtimeMs };
|
|
192
208
|
}
|
|
193
209
|
async function ensureExtractionRoot(root) {
|
|
194
210
|
try {
|
|
@@ -318,6 +334,7 @@ class Archive {
|
|
|
318
334
|
handle;
|
|
319
335
|
closed = false;
|
|
320
336
|
entriesPromise;
|
|
337
|
+
entryIndexes;
|
|
321
338
|
constructor(handle) {
|
|
322
339
|
this.handle = handle;
|
|
323
340
|
}
|
|
@@ -342,8 +359,14 @@ class Archive {
|
|
|
342
359
|
throw new RangeError('Password exceeds the 1 MiB native password limit');
|
|
343
360
|
}
|
|
344
361
|
}
|
|
362
|
+
const deflateBufferSize = options.deflateBufferSize ?? defaultDeflateBufferSize;
|
|
363
|
+
if (!Number.isSafeInteger(deflateBufferSize)
|
|
364
|
+
|| deflateBufferSize < minDeflateBufferSize
|
|
365
|
+
|| deflateBufferSize > maxDeflateBufferSize) {
|
|
366
|
+
throw new RangeError(`Deflate buffer size must be an integer between ${minDeflateBufferSize} and ${maxDeflateBufferSize} bytes`);
|
|
367
|
+
}
|
|
345
368
|
try {
|
|
346
|
-
const handle = await native.open(node_path.resolve(path), options.password, enginePath);
|
|
369
|
+
const handle = await native.open(node_path.resolve(path), options.password, enginePath, deflateBufferSize);
|
|
347
370
|
return new Archive(handle);
|
|
348
371
|
}
|
|
349
372
|
catch (cause) {
|
|
@@ -455,7 +478,23 @@ class Archive {
|
|
|
455
478
|
if (typeof idOrPath === 'number' && (!Number.isSafeInteger(idOrPath) || idOrPath < 0)) {
|
|
456
479
|
throw new RangeError('Entry ID must be a non-negative safe integer');
|
|
457
480
|
}
|
|
458
|
-
|
|
481
|
+
const entries = await this.entries();
|
|
482
|
+
if (!this.entryIndexes) {
|
|
483
|
+
const pathEntries = Object.create(null);
|
|
484
|
+
const idEntries = Object.create(null);
|
|
485
|
+
for (const entry of entries) {
|
|
486
|
+
pathEntries[entry.path] ??= entry;
|
|
487
|
+
idEntries[entry.id] ??= entry;
|
|
488
|
+
}
|
|
489
|
+
this.entryIndexes = { pathEntries, idEntries };
|
|
490
|
+
}
|
|
491
|
+
if (typeof idOrPath === 'number') {
|
|
492
|
+
return this.entryIndexes.idEntries[idOrPath];
|
|
493
|
+
}
|
|
494
|
+
if (typeof idOrPath === 'string') {
|
|
495
|
+
return this.entryIndexes.pathEntries[idOrPath];
|
|
496
|
+
}
|
|
497
|
+
return undefined;
|
|
459
498
|
}
|
|
460
499
|
async extract(idOrPathOrPaths) {
|
|
461
500
|
this.assertOpen();
|
|
@@ -533,9 +572,6 @@ class Archive {
|
|
|
533
572
|
|| options.concurrency > 128)) {
|
|
534
573
|
throw new RangeError('Folder extraction concurrency must be an integer between 1 and 128');
|
|
535
574
|
}
|
|
536
|
-
if (options.onProgress !== undefined && typeof options.onProgress !== 'function') {
|
|
537
|
-
throw new TypeError('Folder extraction onProgress option must be a function');
|
|
538
|
-
}
|
|
539
575
|
if (options.onExtract !== undefined && typeof options.onExtract !== 'function') {
|
|
540
576
|
throw new TypeError('Folder extraction onExtract option must be a function');
|
|
541
577
|
}
|
|
@@ -578,33 +614,13 @@ class Archive {
|
|
|
578
614
|
}
|
|
579
615
|
const root = node_path.resolve(destination);
|
|
580
616
|
const plans = makeOutputPlans(root, selectedEntries);
|
|
581
|
-
const
|
|
582
|
-
if (maxBytes !== null &&
|
|
617
|
+
const totalBytes = selectedEntries.reduce((total, entry) => total + (entry.isDirectory ? 0n : entry.size), 0n);
|
|
618
|
+
if (maxBytes !== null && totalBytes > maxBytes) {
|
|
583
619
|
throw new ArchiveError('ERR_RESOURCE_LIMIT', `Folder output exceeds the ${maxBytes}-byte limit`);
|
|
584
620
|
}
|
|
585
621
|
options.signal?.throwIfAborted();
|
|
586
622
|
await ensureExtractionRoot(root);
|
|
587
|
-
let extractedBytes = 0n;
|
|
588
623
|
let filesExtracted = 0;
|
|
589
|
-
const totalFiles = plans.filter(plan => !plan.isDirectory).length;
|
|
590
|
-
const reportProgress = () => {
|
|
591
|
-
let percent = 0;
|
|
592
|
-
if (expectedBytes > 0n) {
|
|
593
|
-
const scaledPercent = extractedBytes * 10000n / expectedBytes;
|
|
594
|
-
percent = Number(scaledPercent > 9900n ? 9900n : scaledPercent) / 100;
|
|
595
|
-
}
|
|
596
|
-
if (filesExtracted === totalFiles) {
|
|
597
|
-
percent = 100;
|
|
598
|
-
}
|
|
599
|
-
options.onProgress?.({
|
|
600
|
-
filesExtracted,
|
|
601
|
-
totalFiles,
|
|
602
|
-
bytesProcessed: extractedBytes,
|
|
603
|
-
totalBytes: expectedBytes,
|
|
604
|
-
percent,
|
|
605
|
-
});
|
|
606
|
-
};
|
|
607
|
-
reportProgress();
|
|
608
624
|
for (const plan of plans) {
|
|
609
625
|
options.signal?.throwIfAborted();
|
|
610
626
|
if (plan.isDirectory) {
|
|
@@ -616,7 +632,6 @@ class Archive {
|
|
|
616
632
|
const extractionSignal = controller.signal;
|
|
617
633
|
let hasFailure = false;
|
|
618
634
|
let failure;
|
|
619
|
-
let nextFileIndex = 0;
|
|
620
635
|
const stop = (error) => {
|
|
621
636
|
if (!hasFailure) {
|
|
622
637
|
hasFailure = true;
|
|
@@ -630,78 +645,77 @@ class Archive {
|
|
|
630
645
|
stop(options.signal?.reason);
|
|
631
646
|
};
|
|
632
647
|
options.signal?.addEventListener('abort', abortFromCaller, { once: true });
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
648
|
+
const groupCount = Math.min(concurrency, filePlans.length);
|
|
649
|
+
const fileGroups = Array.from({ length: groupCount }, () => []);
|
|
650
|
+
filePlans.forEach((plan, index) => {
|
|
651
|
+
fileGroups[index % groupCount].push(plan);
|
|
652
|
+
});
|
|
653
|
+
const extractGroup = async (group) => {
|
|
654
|
+
const outputs = [];
|
|
655
|
+
let completionFailed = false;
|
|
656
|
+
let completionFailure;
|
|
657
|
+
try {
|
|
658
|
+
for (const plan of group) {
|
|
659
|
+
await ensureOutputParents(root, plan.targetPath);
|
|
660
|
+
extractionSignal.throwIfAborted();
|
|
661
|
+
if (options.overwrite) {
|
|
662
|
+
await assertReplaceableOutput(plan.targetPath);
|
|
645
663
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
return;
|
|
664
|
+
else {
|
|
665
|
+
await assertFolderOutputDoesNotExist(plan.targetPath);
|
|
649
666
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
const temporaryPath = node_path.join(node_path.dirname(plan.targetPath), `.7zip-native-${node_crypto.randomUUID()}.tmp`);
|
|
656
|
-
try {
|
|
657
|
-
await promises$1.pipeline(this.createReadStream(plan.entry.id, {
|
|
658
|
-
signal: extractionSignal,
|
|
659
|
-
maxBytes: null,
|
|
660
|
-
}), limit, node_fs.createWriteStream(temporaryPath, { flags: 'wx', mode: 0o600 }), { signal: extractionSignal });
|
|
661
|
-
extractionSignal.throwIfAborted();
|
|
662
|
-
await assertReplaceableOutput(plan.targetPath);
|
|
663
|
-
extractionSignal.throwIfAborted();
|
|
664
|
-
await promises.rename(temporaryPath, plan.targetPath);
|
|
667
|
+
outputs.push({
|
|
668
|
+
id: plan.entry.id,
|
|
669
|
+
path: plan.targetPath,
|
|
670
|
+
overwrite: options.overwrite === true,
|
|
671
|
+
});
|
|
665
672
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
673
|
+
let onFileCompleted;
|
|
674
|
+
const onExtract = options.onExtract;
|
|
675
|
+
if (onExtract) {
|
|
676
|
+
const plansById = new Map(group.map(plan => [plan.entry.id, plan]));
|
|
677
|
+
onFileCompleted = (id) => {
|
|
678
|
+
if (completionFailed || hasFailure) {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
try {
|
|
682
|
+
const plan = plansById.get(id);
|
|
683
|
+
if (plan === undefined) {
|
|
684
|
+
throw new ArchiveError('ERR_ARCHIVE_EXTRACT', 'Native folder extraction returned an unknown file completion');
|
|
685
|
+
}
|
|
686
|
+
extractionSignal.throwIfAborted();
|
|
687
|
+
filesExtracted++;
|
|
688
|
+
onExtract({
|
|
689
|
+
entry: plan.entry,
|
|
690
|
+
outputPath: plan.targetPath,
|
|
691
|
+
percent: filesExtracted * 100 / filePlans.length,
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
catch (error) {
|
|
695
|
+
completionFailed = true;
|
|
696
|
+
completionFailure = error;
|
|
697
|
+
stop(error);
|
|
698
|
+
}
|
|
699
|
+
};
|
|
669
700
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
signal: extractionSignal,
|
|
674
|
-
maxBytes: null,
|
|
675
|
-
}), limit, node_fs.createWriteStream(plan.targetPath, { flags: 'wx', mode: 0o600 }), { signal: extractionSignal });
|
|
676
|
-
}
|
|
677
|
-
filesExtracted++;
|
|
678
|
-
reportProgress();
|
|
679
|
-
options.onExtract?.({ entry: plan.entry, outputPath: plan.targetPath });
|
|
680
|
-
};
|
|
681
|
-
const runWorker = async () => {
|
|
682
|
-
while (!hasFailure) {
|
|
683
|
-
if (options.signal?.aborted) {
|
|
684
|
-
stop(options.signal.reason);
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
const plan = filePlans[nextFileIndex++];
|
|
688
|
-
if (!plan) {
|
|
689
|
-
return;
|
|
690
|
-
}
|
|
691
|
-
try {
|
|
692
|
-
await extractFile(plan);
|
|
693
|
-
}
|
|
694
|
-
catch (error) {
|
|
695
|
-
stop(error);
|
|
696
|
-
return;
|
|
701
|
+
await this.extractEntriesToFiles(outputs, extractionSignal, onFileCompleted);
|
|
702
|
+
if (completionFailed) {
|
|
703
|
+
throw completionFailure;
|
|
697
704
|
}
|
|
698
705
|
}
|
|
706
|
+
catch (caughtError) {
|
|
707
|
+
throw completionFailed ? completionFailure : caughtError;
|
|
708
|
+
}
|
|
699
709
|
};
|
|
700
710
|
try {
|
|
701
711
|
options.signal?.throwIfAborted();
|
|
702
|
-
const workers =
|
|
703
|
-
|
|
704
|
-
|
|
712
|
+
const workers = fileGroups.map(group => extractGroup(group));
|
|
713
|
+
try {
|
|
714
|
+
await Promise.all(workers);
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
stop(error);
|
|
718
|
+
await Promise.allSettled(workers);
|
|
705
719
|
throw failure;
|
|
706
720
|
}
|
|
707
721
|
}
|
|
@@ -709,8 +723,67 @@ class Archive {
|
|
|
709
723
|
options.signal?.removeEventListener('abort', abortFromCaller);
|
|
710
724
|
}
|
|
711
725
|
}
|
|
712
|
-
async read(
|
|
726
|
+
async read(idOrPathOrPaths, options) {
|
|
713
727
|
this.assertOpen();
|
|
728
|
+
const maxUInt64 = (1n << 64n) - 1n;
|
|
729
|
+
const normalizeRange = (range) => {
|
|
730
|
+
const offset = this.toUnsignedBigInt(range.offset ?? 0, 'offset');
|
|
731
|
+
const length = this.toUnsignedBigInt(range.length, 'length');
|
|
732
|
+
if (offset > maxUInt64 || length > maxUInt64 - offset) {
|
|
733
|
+
throw new ArchiveError('ERR_INVALID_RANGE', 'Read range exceeds the native 64-bit offset limit');
|
|
734
|
+
}
|
|
735
|
+
return { offset, length };
|
|
736
|
+
};
|
|
737
|
+
if (options === undefined) {
|
|
738
|
+
if (!Array.isArray(idOrPathOrPaths)) {
|
|
739
|
+
throw new TypeError('Read options are required for an entry selector');
|
|
740
|
+
}
|
|
741
|
+
const requests = idOrPathOrPaths;
|
|
742
|
+
const normalized = await Promise.all(requests.map(async (request) => {
|
|
743
|
+
if (!request || typeof request !== 'object' || !('entry' in request)) {
|
|
744
|
+
throw new TypeError('Batch read requests must include an entry selector');
|
|
745
|
+
}
|
|
746
|
+
const range = normalizeRange(request);
|
|
747
|
+
return {
|
|
748
|
+
id: await this.resolveEntryId(request.entry),
|
|
749
|
+
...range,
|
|
750
|
+
};
|
|
751
|
+
}));
|
|
752
|
+
if (!normalized.length) {
|
|
753
|
+
return [];
|
|
754
|
+
}
|
|
755
|
+
try {
|
|
756
|
+
return await native.readMany(this.handle, normalized);
|
|
757
|
+
}
|
|
758
|
+
catch (cause) {
|
|
759
|
+
throw extractionError(cause);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
const isBatch = Array.isArray(idOrPathOrPaths);
|
|
763
|
+
let selectors;
|
|
764
|
+
if (isBatch) {
|
|
765
|
+
selectors = idOrPathOrPaths;
|
|
766
|
+
}
|
|
767
|
+
else {
|
|
768
|
+
selectors = [idOrPathOrPaths];
|
|
769
|
+
}
|
|
770
|
+
const { offset, length } = normalizeRange(options);
|
|
771
|
+
if (isBatch) {
|
|
772
|
+
const ids = await Promise.all(selectors.map(selector => this.resolveEntryId(selector)));
|
|
773
|
+
const uniqueIds = [...new Set(ids)];
|
|
774
|
+
if (!uniqueIds.length) {
|
|
775
|
+
return [];
|
|
776
|
+
}
|
|
777
|
+
try {
|
|
778
|
+
const buffers = await native.readMany(this.handle, uniqueIds.map(id => ({ id, offset, length })));
|
|
779
|
+
const buffersById = new Map(uniqueIds.map((id, index) => [id, buffers[index]]));
|
|
780
|
+
return ids.map(id => buffersById.get(id));
|
|
781
|
+
}
|
|
782
|
+
catch (cause) {
|
|
783
|
+
throw extractionError(cause);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
const idOrPath = selectors[0];
|
|
714
787
|
let id;
|
|
715
788
|
if (typeof idOrPath === 'number') {
|
|
716
789
|
this.validateIds([idOrPath]);
|
|
@@ -719,12 +792,6 @@ class Archive {
|
|
|
719
792
|
else {
|
|
720
793
|
id = await this.resolveEntryId(idOrPath);
|
|
721
794
|
}
|
|
722
|
-
const offset = this.toUnsignedBigInt(options.offset ?? 0, 'offset');
|
|
723
|
-
const length = this.toUnsignedBigInt(options.length, 'length');
|
|
724
|
-
const maxUInt64 = (1n << 64n) - 1n;
|
|
725
|
-
if (offset > maxUInt64 || length > maxUInt64 - offset) {
|
|
726
|
-
throw new ArchiveError('ERR_INVALID_RANGE', 'Read range exceeds the native 64-bit offset limit');
|
|
727
|
-
}
|
|
728
795
|
try {
|
|
729
796
|
return await native.read(this.handle, id, offset, length);
|
|
730
797
|
}
|
|
@@ -732,6 +799,32 @@ class Archive {
|
|
|
732
799
|
throw extractionError(cause);
|
|
733
800
|
}
|
|
734
801
|
}
|
|
802
|
+
async extractEntriesToFiles(outputs, signal, onFileCompleted) {
|
|
803
|
+
let task;
|
|
804
|
+
const cancelTask = () => {
|
|
805
|
+
if (task) {
|
|
806
|
+
native.cancelExtractToFiles(task.taskId);
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
try {
|
|
810
|
+
signal.throwIfAborted();
|
|
811
|
+
task = native.startExtractToFiles(this.handle, outputs, onFileCompleted);
|
|
812
|
+
signal.addEventListener('abort', cancelTask, { once: true });
|
|
813
|
+
if (signal.aborted) {
|
|
814
|
+
cancelTask();
|
|
815
|
+
}
|
|
816
|
+
return await task.promise;
|
|
817
|
+
}
|
|
818
|
+
catch (cause) {
|
|
819
|
+
if (signal.aborted) {
|
|
820
|
+
throw signal.reason ?? cause;
|
|
821
|
+
}
|
|
822
|
+
throw extractionError(cause);
|
|
823
|
+
}
|
|
824
|
+
finally {
|
|
825
|
+
signal.removeEventListener('abort', cancelTask);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
735
828
|
async close() {
|
|
736
829
|
if (this.closed) {
|
|
737
830
|
return;
|
package/dist/index.d.cts
CHANGED
|
@@ -16,8 +16,12 @@ interface ReadOptions {
|
|
|
16
16
|
readonly offset?: number | bigint;
|
|
17
17
|
readonly length: number | bigint;
|
|
18
18
|
}
|
|
19
|
+
interface ReadRequest extends ReadOptions {
|
|
20
|
+
readonly entry: EntrySelector;
|
|
21
|
+
}
|
|
19
22
|
interface OpenOptions {
|
|
20
23
|
readonly password?: string;
|
|
24
|
+
readonly deflateBufferSize?: number;
|
|
21
25
|
}
|
|
22
26
|
type ArchiveFormat = '7z' | 'zip' | 'tar' | 'wim';
|
|
23
27
|
interface ArchiveCreateEntry {
|
|
@@ -29,16 +33,10 @@ interface CreateArchiveOptions {
|
|
|
29
33
|
readonly compressionLevel?: number;
|
|
30
34
|
readonly overwrite?: boolean;
|
|
31
35
|
}
|
|
32
|
-
interface ExtractToFolderProgress {
|
|
33
|
-
readonly filesExtracted: number;
|
|
34
|
-
readonly totalFiles: number;
|
|
35
|
-
readonly bytesProcessed: bigint;
|
|
36
|
-
readonly totalBytes: bigint;
|
|
37
|
-
readonly percent: number;
|
|
38
|
-
}
|
|
39
36
|
interface ExtractedArchiveFile {
|
|
40
37
|
readonly entry: ArchiveEntry;
|
|
41
38
|
readonly outputPath: string;
|
|
39
|
+
readonly percent: number;
|
|
42
40
|
}
|
|
43
41
|
interface ReadStreamOptions {
|
|
44
42
|
readonly highWaterMark?: number;
|
|
@@ -50,7 +48,6 @@ interface ExtractToFolderOptions {
|
|
|
50
48
|
readonly paths?: readonly string[];
|
|
51
49
|
readonly concurrency?: number;
|
|
52
50
|
readonly overwrite?: boolean;
|
|
53
|
-
readonly onProgress?: (progress: ExtractToFolderProgress) => void;
|
|
54
51
|
readonly onExtract?: (result: ExtractedArchiveFile) => void;
|
|
55
52
|
readonly maxBytes?: number | bigint | null;
|
|
56
53
|
readonly signal?: AbortSignal;
|
|
@@ -65,6 +62,7 @@ declare class Archive {
|
|
|
65
62
|
private readonly handle;
|
|
66
63
|
private closed;
|
|
67
64
|
private entriesPromise?;
|
|
65
|
+
private entryIndexes?;
|
|
68
66
|
private constructor();
|
|
69
67
|
static concurrency(value?: number): number;
|
|
70
68
|
static open(path: string, options?: OpenOptions): Promise<Archive>;
|
|
@@ -77,6 +75,9 @@ declare class Archive {
|
|
|
77
75
|
extractToStream(idOrPath: EntrySelector, destination: Writable, options?: ReadStreamOptions): Promise<void>;
|
|
78
76
|
extractToFolder(destination: string, options?: ExtractToFolderOptions): Promise<void>;
|
|
79
77
|
read(idOrPath: EntrySelector, options: ReadOptions): Promise<Buffer>;
|
|
78
|
+
read(idsOrPaths: readonly EntrySelector[], options: ReadOptions): Promise<Buffer[]>;
|
|
79
|
+
read(requests: readonly ReadRequest[]): Promise<Buffer[]>;
|
|
80
|
+
private extractEntriesToFiles;
|
|
80
81
|
close(): Promise<void>;
|
|
81
82
|
private assertOpen;
|
|
82
83
|
private validateIds;
|
|
@@ -86,4 +87,4 @@ declare class Archive {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
export { Archive, ArchiveError };
|
|
89
|
-
export type { ArchiveCreateEntry, ArchiveEntry, ArchiveErrorCode, ArchiveFormat, CreateArchiveOptions, EntryId, EntrySelector, ExtractToFolderOptions,
|
|
90
|
+
export type { ArchiveCreateEntry, ArchiveEntry, ArchiveErrorCode, ArchiveFormat, CreateArchiveOptions, EntryId, EntrySelector, ExtractToFolderOptions, ExtractedArchiveFile, OpenOptions, ReadOptions, ReadRequest, ReadStreamOptions };
|
package/dist/index.d.mts
CHANGED
|
@@ -16,8 +16,12 @@ interface ReadOptions {
|
|
|
16
16
|
readonly offset?: number | bigint;
|
|
17
17
|
readonly length: number | bigint;
|
|
18
18
|
}
|
|
19
|
+
interface ReadRequest extends ReadOptions {
|
|
20
|
+
readonly entry: EntrySelector;
|
|
21
|
+
}
|
|
19
22
|
interface OpenOptions {
|
|
20
23
|
readonly password?: string;
|
|
24
|
+
readonly deflateBufferSize?: number;
|
|
21
25
|
}
|
|
22
26
|
type ArchiveFormat = '7z' | 'zip' | 'tar' | 'wim';
|
|
23
27
|
interface ArchiveCreateEntry {
|
|
@@ -29,16 +33,10 @@ interface CreateArchiveOptions {
|
|
|
29
33
|
readonly compressionLevel?: number;
|
|
30
34
|
readonly overwrite?: boolean;
|
|
31
35
|
}
|
|
32
|
-
interface ExtractToFolderProgress {
|
|
33
|
-
readonly filesExtracted: number;
|
|
34
|
-
readonly totalFiles: number;
|
|
35
|
-
readonly bytesProcessed: bigint;
|
|
36
|
-
readonly totalBytes: bigint;
|
|
37
|
-
readonly percent: number;
|
|
38
|
-
}
|
|
39
36
|
interface ExtractedArchiveFile {
|
|
40
37
|
readonly entry: ArchiveEntry;
|
|
41
38
|
readonly outputPath: string;
|
|
39
|
+
readonly percent: number;
|
|
42
40
|
}
|
|
43
41
|
interface ReadStreamOptions {
|
|
44
42
|
readonly highWaterMark?: number;
|
|
@@ -50,7 +48,6 @@ interface ExtractToFolderOptions {
|
|
|
50
48
|
readonly paths?: readonly string[];
|
|
51
49
|
readonly concurrency?: number;
|
|
52
50
|
readonly overwrite?: boolean;
|
|
53
|
-
readonly onProgress?: (progress: ExtractToFolderProgress) => void;
|
|
54
51
|
readonly onExtract?: (result: ExtractedArchiveFile) => void;
|
|
55
52
|
readonly maxBytes?: number | bigint | null;
|
|
56
53
|
readonly signal?: AbortSignal;
|
|
@@ -65,6 +62,7 @@ declare class Archive {
|
|
|
65
62
|
private readonly handle;
|
|
66
63
|
private closed;
|
|
67
64
|
private entriesPromise?;
|
|
65
|
+
private entryIndexes?;
|
|
68
66
|
private constructor();
|
|
69
67
|
static concurrency(value?: number): number;
|
|
70
68
|
static open(path: string, options?: OpenOptions): Promise<Archive>;
|
|
@@ -77,6 +75,9 @@ declare class Archive {
|
|
|
77
75
|
extractToStream(idOrPath: EntrySelector, destination: Writable, options?: ReadStreamOptions): Promise<void>;
|
|
78
76
|
extractToFolder(destination: string, options?: ExtractToFolderOptions): Promise<void>;
|
|
79
77
|
read(idOrPath: EntrySelector, options: ReadOptions): Promise<Buffer>;
|
|
78
|
+
read(idsOrPaths: readonly EntrySelector[], options: ReadOptions): Promise<Buffer[]>;
|
|
79
|
+
read(requests: readonly ReadRequest[]): Promise<Buffer[]>;
|
|
80
|
+
private extractEntriesToFiles;
|
|
80
81
|
close(): Promise<void>;
|
|
81
82
|
private assertOpen;
|
|
82
83
|
private validateIds;
|
|
@@ -86,4 +87,4 @@ declare class Archive {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
export { Archive, ArchiveError };
|
|
89
|
-
export type { ArchiveCreateEntry, ArchiveEntry, ArchiveErrorCode, ArchiveFormat, CreateArchiveOptions, EntryId, EntrySelector, ExtractToFolderOptions,
|
|
90
|
+
export type { ArchiveCreateEntry, ArchiveEntry, ArchiveErrorCode, ArchiveFormat, CreateArchiveOptions, EntryId, EntrySelector, ExtractToFolderOptions, ExtractedArchiveFile, OpenOptions, ReadOptions, ReadRequest, ReadStreamOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -16,8 +16,12 @@ interface ReadOptions {
|
|
|
16
16
|
readonly offset?: number | bigint;
|
|
17
17
|
readonly length: number | bigint;
|
|
18
18
|
}
|
|
19
|
+
interface ReadRequest extends ReadOptions {
|
|
20
|
+
readonly entry: EntrySelector;
|
|
21
|
+
}
|
|
19
22
|
interface OpenOptions {
|
|
20
23
|
readonly password?: string;
|
|
24
|
+
readonly deflateBufferSize?: number;
|
|
21
25
|
}
|
|
22
26
|
type ArchiveFormat = '7z' | 'zip' | 'tar' | 'wim';
|
|
23
27
|
interface ArchiveCreateEntry {
|
|
@@ -29,16 +33,10 @@ interface CreateArchiveOptions {
|
|
|
29
33
|
readonly compressionLevel?: number;
|
|
30
34
|
readonly overwrite?: boolean;
|
|
31
35
|
}
|
|
32
|
-
interface ExtractToFolderProgress {
|
|
33
|
-
readonly filesExtracted: number;
|
|
34
|
-
readonly totalFiles: number;
|
|
35
|
-
readonly bytesProcessed: bigint;
|
|
36
|
-
readonly totalBytes: bigint;
|
|
37
|
-
readonly percent: number;
|
|
38
|
-
}
|
|
39
36
|
interface ExtractedArchiveFile {
|
|
40
37
|
readonly entry: ArchiveEntry;
|
|
41
38
|
readonly outputPath: string;
|
|
39
|
+
readonly percent: number;
|
|
42
40
|
}
|
|
43
41
|
interface ReadStreamOptions {
|
|
44
42
|
readonly highWaterMark?: number;
|
|
@@ -50,7 +48,6 @@ interface ExtractToFolderOptions {
|
|
|
50
48
|
readonly paths?: readonly string[];
|
|
51
49
|
readonly concurrency?: number;
|
|
52
50
|
readonly overwrite?: boolean;
|
|
53
|
-
readonly onProgress?: (progress: ExtractToFolderProgress) => void;
|
|
54
51
|
readonly onExtract?: (result: ExtractedArchiveFile) => void;
|
|
55
52
|
readonly maxBytes?: number | bigint | null;
|
|
56
53
|
readonly signal?: AbortSignal;
|
|
@@ -65,6 +62,7 @@ declare class Archive {
|
|
|
65
62
|
private readonly handle;
|
|
66
63
|
private closed;
|
|
67
64
|
private entriesPromise?;
|
|
65
|
+
private entryIndexes?;
|
|
68
66
|
private constructor();
|
|
69
67
|
static concurrency(value?: number): number;
|
|
70
68
|
static open(path: string, options?: OpenOptions): Promise<Archive>;
|
|
@@ -77,6 +75,9 @@ declare class Archive {
|
|
|
77
75
|
extractToStream(idOrPath: EntrySelector, destination: Writable, options?: ReadStreamOptions): Promise<void>;
|
|
78
76
|
extractToFolder(destination: string, options?: ExtractToFolderOptions): Promise<void>;
|
|
79
77
|
read(idOrPath: EntrySelector, options: ReadOptions): Promise<Buffer>;
|
|
78
|
+
read(idsOrPaths: readonly EntrySelector[], options: ReadOptions): Promise<Buffer[]>;
|
|
79
|
+
read(requests: readonly ReadRequest[]): Promise<Buffer[]>;
|
|
80
|
+
private extractEntriesToFiles;
|
|
80
81
|
close(): Promise<void>;
|
|
81
82
|
private assertOpen;
|
|
82
83
|
private validateIds;
|
|
@@ -86,4 +87,4 @@ declare class Archive {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
export { Archive, ArchiveError };
|
|
89
|
-
export type { ArchiveCreateEntry, ArchiveEntry, ArchiveErrorCode, ArchiveFormat, CreateArchiveOptions, EntryId, EntrySelector, ExtractToFolderOptions,
|
|
90
|
+
export type { ArchiveCreateEntry, ArchiveEntry, ArchiveErrorCode, ArchiveFormat, CreateArchiveOptions, EntryId, EntrySelector, ExtractToFolderOptions, ExtractedArchiveFile, OpenOptions, ReadOptions, ReadRequest, ReadStreamOptions };
|