@zip.js/zip.js 2.8.50 → 2.8.51

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.
@@ -26,7 +26,7 @@
26
26
  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
27
  */
28
28
 
29
- /* global WritableStream, AbortController */
29
+ /* global WritableStream, AbortController, DOMException */
30
30
  // deno-lint-ignore-file no-this-alias
31
31
 
32
32
  import {
@@ -72,6 +72,8 @@ import { toCompatibleReadable, toCompatibleWritable } from "./util/compatible-st
72
72
  const ERR_ENTRY_EXISTS = "Entry filename already exists";
73
73
  const ERR_READABLE_CONSUMED = "Readable stream already consumed";
74
74
  const ERR_ABORT_EXPORT = "zipjs-abort-export";
75
+ const ERR_ABORTED = "The operation was aborted";
76
+ const ABORT_ERROR_NAME = "AbortError";
75
77
  const INFOZIP_EXTRA_FIELD_TYPE = "infozip";
76
78
  const INTERPRETED_EXTRA_FIELD_TYPES = new Set([
77
79
  EXTRAFIELD_TYPE_ZIP64,
@@ -524,6 +526,10 @@ class ZipDirectoryEntry extends ZipEntry {
524
526
  }
525
527
  }
526
528
 
529
+ getChildren(options = {}) {
530
+ return collectChildren(this, options.recursive);
531
+ }
532
+
527
533
  isPasswordProtected() {
528
534
  const children = this.children;
529
535
  for (let childIndex = 0; childIndex < children.length; childIndex++) {
@@ -615,6 +621,10 @@ class FS {
615
621
  return this.root.getChildByName(name);
616
622
  }
617
623
 
624
+ getChildren(options) {
625
+ return this.root.getChildren(options);
626
+ }
627
+
618
628
  addDirectory(name, options) {
619
629
  return this.root.addDirectory(name, options);
620
630
  }
@@ -723,7 +733,7 @@ class FS {
723
733
  }
724
734
 
725
735
  const fs = { FS, ZipDirectoryEntry, ZipFileEntry };
726
- export { fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED };
736
+ export { fs, ERR_ENTRY_EXISTS, ERR_READABLE_CONSUMED, ERR_ABORTED };
727
737
 
728
738
  function getTotalSize(entries, propertyName) {
729
739
  let size = 0;
@@ -875,103 +885,101 @@ function getUserExtraField(extraField) {
875
885
  async function exportZip(zipWriter, entry, totalSize, options, readers) {
876
886
  const selectedEntry = entry;
877
887
  const entryOffsets = new Map();
878
- await process(zipWriter, entry);
888
+ if (options.bufferedWrite) {
889
+ await processChildren(entry);
890
+ } else {
891
+ for (const child of entry.getChildren({ recursive: true })) {
892
+ await addChild(child);
893
+ }
894
+ }
879
895
 
880
- async function process(zipWriter, entry) {
881
- await exportChild();
896
+ async function processChildren(entry) {
897
+ const results = await Promise.allSettled(entry.children.map(async child => {
898
+ await addChild(child);
899
+ await processChildren(child);
900
+ }));
901
+ const errorResult = results.find(result => result.status == "rejected");
902
+ if (errorResult) {
903
+ throw errorResult.reason;
904
+ }
905
+ }
882
906
 
883
- async function exportChild() {
884
- if (options.bufferedWrite) {
885
- const results = await Promise.allSettled(entry.children.map(processChild));
886
- const errorResult = results.find(result => result.status == "rejected");
887
- if (errorResult) {
888
- throw errorResult.reason;
907
+ async function addChild(child) {
908
+ const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
909
+ const childOptions = child.options || {};
910
+ let zipEntryOptions = {};
911
+ if (child.data instanceof Entry) {
912
+ const {
913
+ externalFileAttributes,
914
+ versionMadeBy,
915
+ comment,
916
+ lastModDate,
917
+ creationDate,
918
+ lastAccessDate,
919
+ uncompressedSize,
920
+ encrypted,
921
+ zipCrypto,
922
+ crc32,
923
+ compressionMethod,
924
+ extraFieldAES,
925
+ internalFileAttributes,
926
+ extraField,
927
+ uid,
928
+ gid
929
+ } = child.data;
930
+ zipEntryOptions = {
931
+ externalFileAttributes,
932
+ versionMadeBy,
933
+ comment,
934
+ lastModDate,
935
+ creationDate,
936
+ lastAccessDate,
937
+ internalFileAttributes
938
+ };
939
+ const userExtraField = getUserExtraField(extraField);
940
+ if (userExtraField) {
941
+ zipEntryOptions.extraField = userExtraField;
942
+ }
943
+ if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
944
+ Object.assign(zipEntryOptions, {
945
+ uid,
946
+ gid,
947
+ unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
948
+ });
949
+ }
950
+ if (child.passThrough) {
951
+ let level, encryptionStrength;
952
+ if (compressionMethod === 0) {
953
+ level = 0;
889
954
  }
890
- } else {
891
- for (const child of entry.children) {
892
- await processChild(child);
955
+ if (extraFieldAES) {
956
+ encryptionStrength = extraFieldAES.strength;
893
957
  }
894
- }
895
- }
896
-
897
- async function processChild(child) {
898
- const name = options.relativePath ? child.getRelativeName(selectedEntry) : child.getFullname();
899
- const childOptions = child.options || {};
900
- let zipEntryOptions = {};
901
- if (child.data instanceof Entry) {
902
- const {
903
- externalFileAttributes,
904
- versionMadeBy,
905
- comment,
906
- lastModDate,
907
- creationDate,
908
- lastAccessDate,
909
- uncompressedSize,
958
+ zipEntryOptions = Object.assign(zipEntryOptions, {
959
+ passThrough: true,
910
960
  encrypted,
911
961
  zipCrypto,
912
962
  crc32,
913
- compressionMethod,
914
- extraFieldAES,
915
- internalFileAttributes,
916
- extraField,
917
- uid,
918
- gid
919
- } = child.data;
920
- zipEntryOptions = {
921
- externalFileAttributes,
922
- versionMadeBy,
923
- comment,
924
- lastModDate,
925
- creationDate,
926
- lastAccessDate,
927
- internalFileAttributes
928
- };
929
- const userExtraField = getUserExtraField(extraField);
930
- if (userExtraField) {
931
- zipEntryOptions.extraField = userExtraField;
932
- }
933
- if (uid !== UNDEFINED_VALUE || gid !== UNDEFINED_VALUE) {
934
- Object.assign(zipEntryOptions, {
935
- uid,
936
- gid,
937
- unixExtraFieldType: options.unixExtraFieldType || INFOZIP_EXTRA_FIELD_TYPE
938
- });
939
- }
940
- if (child.passThrough) {
941
- let level, encryptionStrength;
942
- if (compressionMethod === 0) {
943
- level = 0;
944
- }
945
- if (extraFieldAES) {
946
- encryptionStrength = extraFieldAES.strength;
947
- }
948
- zipEntryOptions = Object.assign(zipEntryOptions, {
949
- passThrough: true,
950
- encrypted,
951
- zipCrypto,
952
- crc32,
953
- uncompressedSize,
954
- level,
955
- encryptionStrength,
956
- compressionMethod
957
- });
958
- }
963
+ uncompressedSize,
964
+ level,
965
+ encryptionStrength,
966
+ compressionMethod
967
+ });
959
968
  }
960
- await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
961
- directory: child.directory,
962
- onprogress: async indexProgress => {
963
- if (options.onprogress) {
964
- entryOffsets.set(name, indexProgress);
965
- try {
966
- await options.onprogress(Array.from(entryOffsets.values()).reduce((previousValue, currentValue) => previousValue + currentValue), totalSize);
967
- } catch {
968
- // ignored
969
- }
969
+ }
970
+ await zipWriter.add(name, readers.get(child), Object.assign({}, options, zipEntryOptions, childOptions, {
971
+ directory: child.directory,
972
+ onprogress: async indexProgress => {
973
+ if (options.onprogress) {
974
+ entryOffsets.set(name, indexProgress);
975
+ try {
976
+ await options.onprogress(Array.from(entryOffsets.values()).reduce((previousValue, currentValue) => previousValue + currentValue), totalSize);
977
+ } catch {
978
+ // ignored
970
979
  }
971
980
  }
972
- }));
973
- await process(zipWriter, child);
974
- }
981
+ }
982
+ }));
975
983
  }
976
984
  }
977
985
 
@@ -1027,6 +1035,7 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
1027
1035
  const { signal } = abortController;
1028
1036
  const releaseSignal = forwardAbort(options.signal, abortController);
1029
1037
  const exportedEntryNames = [];
1038
+ let exportAborted = false;
1030
1039
  try {
1031
1040
  await exportChildren(zipEntry, directoryHandle);
1032
1041
  } catch (error) {
@@ -1059,10 +1068,10 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
1059
1068
 
1060
1069
  async function exportChild(child, parentHandle) {
1061
1070
  if (signal.aborted) {
1062
- if (isExportAborted(signal.reason)) {
1071
+ if (exportAborted || isExportAborted(signal.reason)) {
1063
1072
  return;
1064
1073
  }
1065
- throw signal.reason;
1074
+ throw signal.reason === UNDEFINED_VALUE ? new DOMException(ERR_ABORTED, ABORT_ERROR_NAME) : signal.reason;
1066
1075
  }
1067
1076
  try {
1068
1077
  if (child.directory) {
@@ -1071,22 +1080,27 @@ async function exportFileSystemHandle(zipEntry, directoryHandle, options) {
1071
1080
  } else {
1072
1081
  const fileHandle = await parentHandle.getFileHandle(child.name, { create: true });
1073
1082
  const writable = await fileHandle.createWritable();
1074
- await child.getData({ writable }, Object.assign({}, options, {
1075
- signal,
1076
- onprogress: async progress => {
1077
- if (options.onprogress) {
1078
- writtenSizes.set(child.id, progress);
1079
- try {
1080
- await options.onprogress(Array.from(writtenSizes.values()).reduce((previousValue, currentValue) => previousValue + currentValue, 0), totalSize);
1081
- } catch {
1082
- // ignored
1083
+ try {
1084
+ await child.getData({ writable }, Object.assign({}, options, {
1085
+ signal,
1086
+ onprogress: async progress => {
1087
+ if (options.onprogress) {
1088
+ writtenSizes.set(child.id, progress);
1089
+ try {
1090
+ await options.onprogress(Array.from(writtenSizes.values()).reduce((previousValue, currentValue) => previousValue + currentValue, 0), totalSize);
1091
+ } catch {
1092
+ // ignored
1093
+ }
1083
1094
  }
1084
1095
  }
1085
- }
1086
- }));
1096
+ }));
1097
+ } catch (error) {
1098
+ throw exportAborted ? new Error(ERR_ABORT_EXPORT) : error;
1099
+ }
1087
1100
  exportedEntryNames.push(child.getRelativeName(zipEntry));
1088
1101
  }
1089
1102
  } catch (error) {
1103
+ exportAborted = true;
1090
1104
  abortController.abort(new Error(ERR_ABORT_EXPORT));
1091
1105
  try {
1092
1106
  if (error.entryName === UNDEFINED_VALUE) {
@@ -1158,6 +1172,21 @@ function resetFS(fs) {
1158
1172
  fs.root = new ZipDirectoryEntry(fs);
1159
1173
  }
1160
1174
 
1175
+ function collectChildren(directory, recursive) {
1176
+ const children = [];
1177
+ const pendingDirectories = [directory];
1178
+ let directoryIndex = 0;
1179
+ while (directoryIndex < pendingDirectories.length) {
1180
+ for (const child of pendingDirectories[directoryIndex++].children) {
1181
+ children.push(child);
1182
+ if (recursive) {
1183
+ pendingDirectories.push(child);
1184
+ }
1185
+ }
1186
+ }
1187
+ return children;
1188
+ }
1189
+
1161
1190
  function registerEntries(fs, entry) {
1162
1191
  const pendingEntries = [entry];
1163
1192
  while (pendingEntries.length) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
4
4
  "author": "Gildas Lormeau",
5
5
  "license": "BSD-3-Clause",
6
- "version": "2.8.50",
6
+ "version": "2.8.51",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",