@zip.js/zip.js 2.8.51 → 2.8.53

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 (41) hide show
  1. package/README.md +8 -3
  2. package/deno.json +1 -1
  3. package/dist/zip-core-external.js +241 -95
  4. package/dist/zip-core-external.min.js +1 -1
  5. package/dist/zip-core.js +243 -94
  6. package/dist/zip-core.min.js +1 -1
  7. package/dist/zip-fs-core-external.js +564 -199
  8. package/dist/zip-fs-core-external.min.js +1 -1
  9. package/dist/zip-fs-core.js +551 -194
  10. package/dist/zip-fs-core.min.js +1 -1
  11. package/dist/zip-fs-external.js +564 -199
  12. package/dist/zip-fs-external.min.js +1 -1
  13. package/dist/zip-fs-native.js +567 -198
  14. package/dist/zip-fs-native.min.js +1 -1
  15. package/dist/zip-fs.js +567 -198
  16. package/dist/zip-fs.min.js +1 -1
  17. package/dist/zip-legacy.js +243 -94
  18. package/dist/zip-legacy.min.js +1 -1
  19. package/dist/zip-native.js +243 -94
  20. package/dist/zip-native.min.js +1 -1
  21. package/dist/zip.js +243 -94
  22. package/dist/zip.min.js +1 -1
  23. package/eslint.config.mjs +1 -1
  24. package/index-native.cjs +567 -198
  25. package/index-native.min.js +1 -1
  26. package/index.cjs +567 -198
  27. package/index.d.cts +551 -45
  28. package/index.d.ts +551 -45
  29. package/index.min.js +1 -1
  30. package/lib/core/codec-worker-web.js +13 -4
  31. package/lib/core/codec-worker.js +2 -0
  32. package/lib/core/constants.js +9 -0
  33. package/lib/core/io.js +43 -4
  34. package/lib/core/options.js +2 -0
  35. package/lib/core/util/compatible-streams.js +3 -8
  36. package/lib/core/zip-entry.js +16 -0
  37. package/lib/core/zip-fs.js +236 -107
  38. package/lib/core/zip-reader.js +106 -40
  39. package/lib/core/zip-writer.js +171 -41
  40. package/lib/zip-core-writer.js +3 -0
  41. package/package.json +9 -7
@@ -120,12 +120,17 @@ import {
120
120
  FILE_ATTR_MSDOS_SYSTEM_MASK,
121
121
  FILE_ATTR_MSDOS_ARCHIVE_MASK,
122
122
  FILE_ATTR_UNIX_TYPE_DIR,
123
+ FILE_ATTR_UNIX_TYPE_FILE,
124
+ FILE_ATTR_UNIX_TYPE_MASK,
125
+ FILE_ATTR_UNIX_TYPE_SYMLINK,
123
126
  FILE_ATTR_UNIX_EXECUTABLE_MASK,
124
127
  FILE_ATTR_UNIX_DEFAULT_MASK,
125
128
  FILE_ATTR_UNIX_SETUID_MASK,
126
129
  FILE_ATTR_UNIX_SETGID_MASK,
127
130
  FILE_ATTR_UNIX_STICKY_MASK,
128
131
  VERSION_DEFLATE,
132
+ VERSION_MADE_BY_MSDOS,
133
+ VERSION_MADE_BY_UNIX,
129
134
  VERSION_ZIP64,
130
135
  VERSION_AES,
131
136
  DIRECTORY_SIGNATURE,
@@ -154,17 +159,21 @@ import {
154
159
  import {
155
160
  initStream,
156
161
  GenericWriter,
157
- GenericReader
162
+ GenericReader,
163
+ BlobReader,
164
+ ownsWritable
158
165
  } from "./io.js";
159
166
  import { encodeText } from "./util/encode-text.js";
160
167
  import { getDataView } from "./util/array.js";
161
- import { toCompatibleReadable } from "./util/compatible-streams.js";
168
+ import { toCompatibleReadable, streamToBlob } from "./util/compatible-streams.js";
162
169
  import {
163
170
  PROPERTY_NAME_LAST_MODIFICATION_DATE,
164
171
  PROPERTY_NAME_LAST_ACCESS_DATE,
165
172
  PROPERTY_NAME_CREATION_DATE,
166
173
  PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES,
167
174
  PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES,
175
+ PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES,
176
+ PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES,
168
177
  PROPERTY_NAME_MS_DOS_COMPATIBLE,
169
178
  PROPERTY_NAME_ZIP64,
170
179
  PROPERTY_NAME_ENCRYPTED,
@@ -220,11 +229,13 @@ import {
220
229
 
221
230
  const ERR_DUPLICATED_NAME = "File already exists";
222
231
  const ERR_INVALID_COMMENT = "Zip file comment exceeds 64KB";
232
+ const ERR_INVALID_COMMENT_TYPE = "Invalid zip file comment (must be a Uint8Array)";
223
233
  const ERR_INVALID_ENTRY_COMMENT = "File entry comment exceeds 64KB";
224
234
  const ERR_INVALID_ENTRY_NAME = "File entry name exceeds 64KB";
225
235
  const ERR_INVALID_VERSION = "Version exceeds 65535";
226
236
  const ERR_INVALID_ENCRYPTION_STRENGTH = "The strength must equal 1, 2, or 3";
227
237
  const ERR_UNSUPPORTED_ENCRYPTION_USDZ = "Encryption is not supported in USDZ files";
238
+ const ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH = "Encryption is not supported when the 'passThrough' option is set";
228
239
  const ERR_INVALID_EXTRAFIELD_TYPE = "Extra field type exceeds 65535";
229
240
  const ERR_INVALID_EXTRAFIELD_DATA = "Extra field data exceeds 64KB";
230
241
  const ERR_UNSUPPORTED_COMPRESSION = "Compression method not supported";
@@ -234,6 +245,7 @@ const MIN_NTFS_TIME = BigInt(0);
234
245
  const MAX_NTFS_TIME = BigInt("0x7fffffffffffffff");
235
246
  const ERR_UNSUPPORTED_FORMAT = "Zip64 is not supported (set the 'zip64' option to 'true')";
236
247
  const ERR_UNDEFINED_UNCOMPRESSED_SIZE = "Undefined uncompressed size";
248
+ const ERR_UNDETERMINED_SIZE = "Undetermined size";
237
249
  const ERR_UNDEFINED_READER = "Undefined reader";
238
250
  const ERR_ZIP_NOT_EMPTY = "Zip file not empty";
239
251
  const ERR_INVALID_UID = "Invalid uid (must be integer 0..2^32-1)";
@@ -286,6 +298,10 @@ class ZipWriter {
286
298
  }
287
299
  reader = new GenericReader(reader);
288
300
  await initStream(reader);
301
+ if (reader.size === UNDEFINED_VALUE || !reader.readUint8Array) {
302
+ reader = new BlobReader(await streamToBlob(reader.readable));
303
+ await initStream(reader);
304
+ }
289
305
  const { ZipReader } = await import("./zip-reader.js");
290
306
  const zipReader = new ZipReader(reader.readable);
291
307
  const entries = await zipReader.getEntries();
@@ -434,6 +450,9 @@ class ZipWriter {
434
450
  const zipWriter = this;
435
451
  const { pendingAddFileCalls, writer } = this;
436
452
  const { writable } = writer;
453
+ if (!(comment instanceof Uint8Array)) {
454
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
455
+ }
437
456
  if (getLength(comment) > MAX_16_BITS) {
438
457
  throw new Error(ERR_INVALID_COMMENT);
439
458
  }
@@ -441,7 +460,7 @@ class ZipWriter {
441
460
  await Promise.allSettled(Array.from(pendingAddFileCalls));
442
461
  }
443
462
  await closeFile(zipWriter, comment, options);
444
- const preventClose = getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
463
+ const preventClose = !ownsWritable(writer) && getOptionValue(zipWriter, options, OPTION_PREVENT_CLOSE);
445
464
  if (!preventClose) {
446
465
  await writable.getWriter().close();
447
466
  }
@@ -514,8 +533,10 @@ function watchAddFileCall(zipWriterStream, promiseAddFile, onerror) {
514
533
  export {
515
534
  ZipWriter,
516
535
  ZipWriterStream,
536
+ getEntriesSize,
517
537
  ERR_DUPLICATED_NAME,
518
538
  ERR_INVALID_COMMENT,
539
+ ERR_INVALID_COMMENT_TYPE,
519
540
  ERR_INVALID_ENTRY_NAME,
520
541
  ERR_INVALID_ENTRY_COMMENT,
521
542
  ERR_INVALID_VERSION,
@@ -523,8 +544,10 @@ export {
523
544
  ERR_INVALID_EXTRAFIELD_DATA,
524
545
  ERR_INVALID_ENCRYPTION_STRENGTH,
525
546
  ERR_UNSUPPORTED_ENCRYPTION_USDZ,
547
+ ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH,
526
548
  ERR_UNSUPPORTED_FORMAT,
527
549
  ERR_UNDEFINED_UNCOMPRESSED_SIZE,
550
+ ERR_UNDETERMINED_SIZE,
528
551
  ERR_UNDEFINED_READER,
529
552
  ERR_ZIP_NOT_EMPTY,
530
553
  ERR_INVALID_SIGNATURE_DATA,
@@ -559,8 +582,6 @@ async function addFile(zipWriter, name, reader, options) {
559
582
  const diskOffset = getDiskOffset(zipWriter.writer);
560
583
  const diskNumber = getDiskNumber(zipWriter.writer);
561
584
  options = Object.assign({}, options, attributesInfo.resolvedOptions, metadataInfo.resolvedOptions, sizesInfo.resolvedOptions, {
562
- internalFileAttribute: metadataInfo.resolvedOptions.internalFileAttributes,
563
- externalFileAttribute: attributesInfo.resolvedOptions.externalFileAttributes,
564
585
  signature: options[PROPERTY_NAME_SIGNATURE],
565
586
  crc32: options.crc32 === UNDEFINED_VALUE ? options[PROPERTY_NAME_SIGNATURE] : options.crc32,
566
587
  offset: zipWriter.offset - diskOffset,
@@ -574,14 +595,20 @@ async function addFile(zipWriter, name, reader, options) {
574
595
  zipWriter.files.delete(name);
575
596
  throw error;
576
597
  }
577
- Object.assign(fileEntry, { name, comment, extraField });
598
+ Object.assign(fileEntry, {
599
+ name,
600
+ comment,
601
+ extraField,
602
+ [PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES]: fileEntry.internalFileAttributes,
603
+ [PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES]: fileEntry.externalFileAttributes
604
+ });
578
605
  return new Entry(fileEntry);
579
606
  }
580
607
 
581
608
  function resolveAttributes(zipWriter, name, options) {
582
609
  name = name.trim();
583
610
  let msDosCompatible = getOptionValue(zipWriter, options, PROPERTY_NAME_MS_DOS_COMPATIBLE);
584
- let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? 20 : 768);
611
+ let versionMadeBy = getOptionValue(zipWriter, options, PROPERTY_NAME_VERSION_MADE_BY, msDosCompatible ? VERSION_MADE_BY_MSDOS : VERSION_MADE_BY_UNIX);
585
612
  const executable = getOptionValue(zipWriter, options, PROPERTY_NAME_EXECUTABLE);
586
613
  const uid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_UID);
587
614
  const gid = getNumberOptionValue(zipWriter, options, PROPERTY_NAME_GID);
@@ -615,7 +642,7 @@ function resolveAttributes(zipWriter, name, options) {
615
642
  const hasMsDosProvided = msdosAttributesRaw !== UNDEFINED_VALUE || msdosAttributes !== UNDEFINED_VALUE;
616
643
  if (hasUnixMetadata) {
617
644
  msDosCompatible = false;
618
- versionMadeBy = (versionMadeBy & MAX_16_BITS) | (3 << 8);
645
+ versionMadeBy = (versionMadeBy & MAX_8_BITS) | VERSION_MADE_BY_UNIX;
619
646
  } else if (hasMsDosProvided) {
620
647
  msDosCompatible = true;
621
648
  versionMadeBy = (versionMadeBy & MAX_8_BITS);
@@ -629,7 +656,7 @@ function resolveAttributes(zipWriter, name, options) {
629
656
  if (versionMadeBy > MAX_16_BITS) {
630
657
  throw new Error(ERR_INVALID_VERSION);
631
658
  }
632
- let externalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES);
659
+ let externalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_EXTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_EXTERNAL_FILE_ATTRIBUTES);
633
660
  const externalFileAttributesProvided = externalFileAttributes !== UNDEFINED_VALUE;
634
661
  if (!externalFileAttributesProvided) {
635
662
  externalFileAttributes = 0;
@@ -655,11 +682,10 @@ function resolveAttributes(zipWriter, name, options) {
655
682
  externalFileAttributes = FILE_ATTR_UNIX_DEFAULT_MASK << 16;
656
683
  }
657
684
  }
658
- let unixExternalUpper;
659
685
  if (!msDosCompatible) {
660
686
  const unixModeProvided = unixMode !== UNDEFINED_VALUE || Boolean(setuid || setgid || sticky);
661
- unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
662
- unixMode = unixMode === UNDEFINED_VALUE ? unixExternalUpper : (unixMode & MAX_16_BITS);
687
+ const defaultUnixMode = (externalFileAttributes >> 16) & MAX_16_BITS;
688
+ unixMode = unixMode === UNDEFINED_VALUE ? defaultUnixMode : (unixMode & MAX_16_BITS);
663
689
  if (setuid) {
664
690
  unixMode |= FILE_ATTR_UNIX_SETUID_MASK;
665
691
  } else {
@@ -677,7 +703,9 @@ function resolveAttributes(zipWriter, name, options) {
677
703
  }
678
704
  if (!externalFileAttributesProvided || unixModeProvided) {
679
705
  if (directory) {
680
- unixMode |= FILE_ATTR_UNIX_TYPE_DIR;
706
+ unixMode = (unixMode & ~FILE_ATTR_UNIX_TYPE_MASK) | FILE_ATTR_UNIX_TYPE_DIR;
707
+ } else if (!(unixMode & FILE_ATTR_UNIX_TYPE_MASK)) {
708
+ unixMode |= FILE_ATTR_UNIX_TYPE_FILE;
681
709
  }
682
710
  externalFileAttributes = ((unixMode & MAX_16_BITS) << 16) | (externalFileAttributes & MAX_16_BITS);
683
711
  }
@@ -686,17 +714,20 @@ function resolveAttributes(zipWriter, name, options) {
686
714
  if (hasMsDosProvided) {
687
715
  externalFileAttributes = (externalFileAttributes & MAX_32_BITS) | (msdosAttributesRaw & MAX_8_BITS);
688
716
  }
717
+ const unixExternalUpper = (externalFileAttributes >> 16) & MAX_16_BITS;
718
+ const symlink = unixMode !== UNDEFINED_VALUE && ((unixMode & FILE_ATTR_UNIX_TYPE_MASK) == FILE_ATTR_UNIX_TYPE_SYMLINK);
689
719
  return {
690
720
  name,
691
721
  resolvedOptions: {
692
722
  versionMadeBy,
693
- msDosCompatible,
723
+ msDosCompatible: Boolean(msDosCompatible),
694
724
  externalFileAttributes,
695
725
  unixExternalUpper,
696
726
  uid,
697
727
  gid,
698
728
  unixMode,
699
729
  unixExtraFieldType,
730
+ symlink,
700
731
  setuid,
701
732
  setgid,
702
733
  sticky,
@@ -730,15 +761,12 @@ function resolveMetadata(zipWriter, name, options) {
730
761
  const lastModDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_MODIFICATION_DATE, new Date());
731
762
  const lastAccessDate = getOptionValue(zipWriter, options, PROPERTY_NAME_LAST_ACCESS_DATE);
732
763
  const creationDate = getOptionValue(zipWriter, options, PROPERTY_NAME_CREATION_DATE);
733
- const internalFileAttributes = getOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, 0);
764
+ const internalFileAttributes = getAliasedOptionValue(zipWriter, options, PROPERTY_NAME_INTERNAL_FILE_ATTRIBUTES, PROPERTY_NAME_DEPRECATED_INTERNAL_FILE_ATTRIBUTES, 0);
734
765
  const passThrough = getOptionValue(zipWriter, options, OPTION_PASS_THROUGH);
735
- let password, rawPassword;
736
- if (!passThrough) {
737
- password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
738
- rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
739
- if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
740
- throw new Error(ERR_INVALID_PASSWORD_TYPE);
741
- }
766
+ const password = getOptionValue(zipWriter, options, OPTION_PASSWORD);
767
+ const rawPassword = getOptionValue(zipWriter, options, OPTION_RAW_PASSWORD);
768
+ if ((password && typeof password != STRING_TYPE) || (rawPassword && !(rawPassword instanceof Uint8Array))) {
769
+ throw new Error(ERR_INVALID_PASSWORD_TYPE);
742
770
  }
743
771
  const encryptionStrength = getNumberOptionValue(zipWriter, options, OPTION_ENCRYPTION_STRENGTH, 3);
744
772
  const zipCrypto = getOptionValue(zipWriter, options, PROPERTY_NAME_ZIPCRYPTO);
@@ -851,14 +879,24 @@ function serializeExtraField(extraField) {
851
879
  }
852
880
 
853
881
  async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, options) {
882
+ if (metadata.passThrough && !reader && !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY)) {
883
+ throw new Error(ERR_UNDEFINED_READER);
884
+ }
885
+ let contentSize;
886
+ if (reader) {
887
+ reader = new GenericReader(reader);
888
+ await initStream(reader);
889
+ ({ size: contentSize } = reader);
890
+ }
891
+ return Object.assign({ reader }, resolveEntrySizes(zipWriter, Boolean(reader), contentSize, metadata, options));
892
+ }
893
+
894
+ function resolveEntrySizes(zipWriter, hasContent, contentSize, metadata, options) {
854
895
  const { passThrough, zipCrypto, password, rawPassword, encryptionStrength } = metadata;
855
896
  let { dataDescriptor, zip64, level, compressionMethod } = metadata;
856
897
  let maximumCompressedSize = 0;
857
898
  let uncompressedSize = 0;
858
- if (passThrough) {
859
- if (!reader) {
860
- throw new Error(ERR_UNDEFINED_READER);
861
- }
899
+ if (passThrough && hasContent) {
862
900
  uncompressedSize = options[PROPERTY_NAME_UNCOMPRESSED_SIZE];
863
901
  if (uncompressedSize === UNDEFINED_VALUE) {
864
902
  throw new Error(ERR_UNDEFINED_UNCOMPRESSED_SIZE);
@@ -866,29 +904,30 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
866
904
  }
867
905
  const zip64Enabled = zip64 === true;
868
906
  const encrypted = getOptionValue(zipWriter, options, PROPERTY_NAME_ENCRYPTED);
869
- const encryptedEntry = Boolean(reader) && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
870
- if (!reader) {
907
+ if (hasContent && passThrough && !encrypted && getLength(password, rawPassword)) {
908
+ throw new Error(ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH);
909
+ }
910
+ const encryptedEntry = hasContent && (Boolean((password && getLength(password)) || (rawPassword && getLength(rawPassword))) || (passThrough && encrypted));
911
+ if (!hasContent) {
871
912
  level = 0;
872
913
  compressionMethod = COMPRESSION_METHOD_STORE;
873
914
  }
874
915
  const encryptionOverhead = encryptedEntry ? (zipCrypto ? 12 : 16 + encryptionStrength * 4) : 0;
875
- if (reader) {
876
- reader = new GenericReader(reader);
877
- await initStream(reader);
916
+ if (hasContent) {
878
917
  if (!passThrough) {
879
- if (reader.size === UNDEFINED_VALUE) {
918
+ if (contentSize === UNDEFINED_VALUE) {
880
919
  dataDescriptor = true;
881
920
  if (zip64 || zip64 === UNDEFINED_VALUE) {
882
921
  zip64 = true;
883
922
  uncompressedSize = maximumCompressedSize = MAX_32_BITS + 1;
884
923
  }
885
924
  } else {
886
- options.uncompressedSize = uncompressedSize = reader.size;
887
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
925
+ options.uncompressedSize = uncompressedSize = contentSize;
926
+ maximumCompressedSize = (isCompressed(compressionMethod, level) ? getMaximumCompressedSize(uncompressedSize) : uncompressedSize) + encryptionOverhead;
888
927
  }
889
928
  } else {
890
929
  options.uncompressedSize = uncompressedSize;
891
- maximumCompressedSize = getMaximumCompressedSize(uncompressedSize) + encryptionOverhead;
930
+ maximumCompressedSize = contentSize === UNDEFINED_VALUE ? getMaximumCompressedSize(uncompressedSize) + encryptionOverhead : contentSize;
892
931
  }
893
932
  }
894
933
  const zip64UncompressedSize = zip64Enabled || uncompressedSize >= MAX_32_BITS;
@@ -902,7 +941,7 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
902
941
  }
903
942
  zip64 = zip64 || false;
904
943
  return {
905
- reader,
944
+ maximumCompressedSize,
906
945
  resolvedOptions: {
907
946
  dataDescriptor,
908
947
  zip64,
@@ -916,6 +955,81 @@ async function resolveSizes(zipWriter, reader, { resolvedOptions: metadata }, op
916
955
  };
917
956
  }
918
957
 
958
+ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comment) {
959
+ const zipWriter = { options: writerOptions, config: getConfiguration() };
960
+ if (writerOptions[OPTION_SIGN_CENTRAL_DIRECTORY]) {
961
+ throw new Error(ERR_UNDETERMINED_SIZE);
962
+ }
963
+ if (comment !== UNDEFINED_VALUE && !(comment instanceof Uint8Array)) {
964
+ throw new Error(ERR_INVALID_COMMENT_TYPE);
965
+ }
966
+ const commentLength = getLength(comment);
967
+ if (commentLength > MAX_16_BITS) {
968
+ throw new Error(ERR_INVALID_COMMENT);
969
+ }
970
+ const usdz = writerOptions[OPTION_USDZ];
971
+ const files = new Map();
972
+ let layoutDependsOnWriteOrder = Boolean(usdz);
973
+ let offset = 0;
974
+ for (const entry of entries) {
975
+ let { name } = entry;
976
+ const { size } = entry;
977
+ const options = Object.assign({}, entry.options);
978
+ name = name.trim();
979
+ if (getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY) && !name.endsWith(DIRECTORY_SIGNATURE)) {
980
+ name += DIRECTORY_SIGNATURE;
981
+ }
982
+ const attributesInfo = resolveAttributes(zipWriter, name, options);
983
+ ({ name } = attributesInfo);
984
+ const { resolvedOptions: metadata } = resolveMetadata(zipWriter, name, options);
985
+ if (metadata.level != 0 && metadata.compressionMethod === UNDEFINED_VALUE &&
986
+ !metadata.passThrough && !(await supportsDeflate(zipWriter.config))) {
987
+ metadata.level = 0;
988
+ }
989
+ const hasContent = !getOptionValue(zipWriter, options, PROPERTY_NAME_DIRECTORY);
990
+ if (hasContent && size === UNDEFINED_VALUE) {
991
+ throw new Error(ERR_UNDETERMINED_SIZE);
992
+ }
993
+ const { maximumCompressedSize, resolvedOptions: sizes } = resolveEntrySizes(zipWriter, hasContent, size, metadata, options);
994
+ if (hasContent && !metadata.passThrough && isCompressed(sizes.compressionMethod, sizes.level)) {
995
+ throw new Error(ERR_UNDETERMINED_SIZE);
996
+ }
997
+ const entryOptions = Object.assign({}, options, attributesInfo.resolvedOptions, metadata, sizes);
998
+ const headerInfo = getHeaderInfo(entryOptions);
999
+ const dataDescriptorInfo = getDataDescriptorInfo(entryOptions);
1000
+ const entryInfo = {
1001
+ headerInfo,
1002
+ metadataSize: getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray)
1003
+ };
1004
+ if (usdz) {
1005
+ appendExtraFieldUSDZ(entryInfo, offset);
1006
+ }
1007
+ const compressedSize = hasContent ? maximumCompressedSize : 0;
1008
+ if (offset >= MAX_32_BITS) {
1009
+ layoutDependsOnWriteOrder = true;
1010
+ }
1011
+ files.set(name, Object.assign({}, entryOptions, headerInfo, {
1012
+ offset,
1013
+ diskNumberStart: 0,
1014
+ compressedSize
1015
+ }));
1016
+ offset += entryInfo.metadataSize + compressedSize;
1017
+ }
1018
+ if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
1019
+ throw new Error(ERR_UNDETERMINED_SIZE);
1020
+ }
1021
+ const directoryDataLength = createDirectoryRecords(files);
1022
+ let zip64 = getOptionValue(zipWriter, writerOptions, PROPERTY_NAME_ZIP64);
1023
+ if (offset >= MAX_32_BITS || directoryDataLength >= MAX_32_BITS || files.size >= MAX_16_BITS) {
1024
+ if (zip64 === false) {
1025
+ throw new Error(ERR_UNSUPPORTED_FORMAT);
1026
+ } else {
1027
+ zip64 = true;
1028
+ }
1029
+ }
1030
+ return offset + directoryDataLength + commentLength + (zip64 ? ZIP64_END_OF_CENTRAL_DIR_TOTAL_LENGTH : END_OF_CENTRAL_DIR_LENGTH);
1031
+ }
1032
+
919
1033
  async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
920
1034
  const {
921
1035
  files,
@@ -1130,6 +1244,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1130
1244
  uid,
1131
1245
  gid,
1132
1246
  unixMode,
1247
+ symlink,
1133
1248
  setuid,
1134
1249
  setgid,
1135
1250
  sticky,
@@ -1166,6 +1281,7 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1166
1281
  uid,
1167
1282
  gid,
1168
1283
  unixMode,
1284
+ symlink: Boolean(symlink),
1169
1285
  setuid,
1170
1286
  setgid,
1171
1287
  sticky,
@@ -1246,8 +1362,8 @@ async function createFileEntry(reader, writer, { diskNumberStart, lock }, entryI
1246
1362
  rawLastModDate,
1247
1363
  creationDate,
1248
1364
  lastAccessDate,
1249
- encrypted,
1250
- zipCrypto,
1365
+ encrypted: Boolean(encrypted),
1366
+ zipCrypto: Boolean(zipCrypto),
1251
1367
  size: metadataSize + compressedSize,
1252
1368
  compressionMethod,
1253
1369
  version,
@@ -1287,9 +1403,7 @@ function getHeaderInfo(options) {
1287
1403
  crc32
1288
1404
  } = options;
1289
1405
  let { version, compressionMethod } = options;
1290
- const compressed = !directory && (compressionMethod === UNDEFINED_VALUE
1291
- ? (level === UNDEFINED_VALUE || level > 0)
1292
- : compressionMethod !== COMPRESSION_METHOD_STORE);
1406
+ const compressed = !directory && isCompressed(compressionMethod, level);
1293
1407
  let rawLocalExtraFieldZip64;
1294
1408
  const uncompressedFile = passThrough || !compressed;
1295
1409
  const zip64ExtraFieldComplete = zip64 && (options.bufferedWrite || !dataDescriptor || ((!zip64UncompressedSize && !zip64CompressedSize) || uncompressedFile));
@@ -1976,6 +2090,16 @@ function getOptionValue(zipWriter, options, name, defaultValue) {
1976
2090
  return result === UNDEFINED_VALUE ? defaultValue : result;
1977
2091
  }
1978
2092
 
2093
+ function getAliasedOptionValue(zipWriter, options, name, deprecatedName, defaultValue) {
2094
+ const value = getAliasedValue(options, name, deprecatedName);
2095
+ const result = value === UNDEFINED_VALUE ? getAliasedValue(zipWriter.options, name, deprecatedName) : value;
2096
+ return result === UNDEFINED_VALUE ? defaultValue : result;
2097
+ }
2098
+
2099
+ function getAliasedValue(options, name, deprecatedName) {
2100
+ return options[name] === UNDEFINED_VALUE ? options[deprecatedName] : options[name];
2101
+ }
2102
+
1979
2103
  function getNumberOptionValue(zipWriter, options, name, defaultValue) {
1980
2104
  return toNumber(getOptionValue(zipWriter, options, name, defaultValue));
1981
2105
  }
@@ -1988,6 +2112,12 @@ function getMaximumCompressedSize(uncompressedSize) {
1988
2112
  return uncompressedSize + (5 * (Math.floor(uncompressedSize / 16383) + 1));
1989
2113
  }
1990
2114
 
2115
+ function isCompressed(compressionMethod, level) {
2116
+ return compressionMethod === UNDEFINED_VALUE
2117
+ ? (level === UNDEFINED_VALUE || level > 0)
2118
+ : compressionMethod !== COMPRESSION_METHOD_STORE;
2119
+ }
2120
+
1991
2121
  function setUint8(view, offset, value) {
1992
2122
  view.setUint8(offset, value);
1993
2123
  }
@@ -33,6 +33,7 @@ export {
33
33
  ZipWriterStream,
34
34
  ERR_DUPLICATED_NAME,
35
35
  ERR_INVALID_COMMENT,
36
+ ERR_INVALID_COMMENT_TYPE,
36
37
  ERR_INVALID_ENTRY_NAME,
37
38
  ERR_INVALID_ENTRY_COMMENT,
38
39
  ERR_INVALID_VERSION,
@@ -40,8 +41,10 @@ export {
40
41
  ERR_INVALID_EXTRAFIELD_DATA,
41
42
  ERR_INVALID_ENCRYPTION_STRENGTH,
42
43
  ERR_UNSUPPORTED_ENCRYPTION_USDZ,
44
+ ERR_UNSUPPORTED_ENCRYPTION_PASS_THROUGH,
43
45
  ERR_UNSUPPORTED_FORMAT,
44
46
  ERR_UNDEFINED_UNCOMPRESSED_SIZE,
47
+ ERR_UNDETERMINED_SIZE,
45
48
  ERR_UNDEFINED_READER,
46
49
  ERR_ZIP_NOT_EMPTY,
47
50
  ERR_INVALID_SIGNATURE_DATA,
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.51",
6
+ "version": "2.8.53",
7
7
  "type": "module",
8
8
  "keywords": [
9
9
  "zip",
@@ -35,25 +35,27 @@
35
35
  },
36
36
  "scripts": {
37
37
  "lint": "npx eslint . && deno lint",
38
- "test": "npm run test-node && npm run test-deno && npm run test-bun && npm run test-node-dist && npm run test-deno-dist && npm run test-bun-dist && npm run test-web-streams-polyfill && npm run test-types",
39
- "test-browsers": "npm run test-chrome && npm run test-firefox && npm run test-webkit",
38
+ "test": "npm run test-node && npm run test-deno && npm run test-bun && npm run test-node-dist && npm run test-deno-dist && npm run test-bun-dist && npm run test-web-streams-polyfill && npm run test-types && npm run test-api-symmetry && npm run test-api-shape",
39
+ "test-browsers": "npm run test-chrome && npm run test-firefox && npm run test-safari",
40
40
  "serve-tests": "http-server -p 8888 -c-1 .",
41
41
  "test-all": "npm run lint && npm run test && npm run test-browsers",
42
42
  "build": "npx rollup -c",
43
43
  "build-dev": "npx rollup -c --environment DEV",
44
44
  "build-doc-api": "npx typedoc",
45
- "build-doc-markdown": "npx typedoc --plugin typedoc-plugin-markdown --out ./docs",
45
+ "build-doc-markdown": "npx typedoc --plugin typedoc-plugin-markdown --disableSources --out ./docs",
46
46
  "test-deno": "cd ./tests && deno test --allow-read ./deno-runner.js",
47
47
  "test-web-streams-polyfill": "cd ./tests && deno run --allow-read ./web-streams-polyfill-runner.js",
48
48
  "test-node": "cd ./tests && node ./node-runner.js",
49
- "test-bun": "cd ./tests && bun test ./bun-runner.js --timeout 30000",
49
+ "test-bun": "cd ./tests && bun test ./bun-runner.js",
50
50
  "test-deno-dist": "./tests/dist-runner.sh deno",
51
51
  "test-node-dist": "./tests/dist-runner.sh node",
52
52
  "test-bun-dist": "./tests/dist-runner.sh bun",
53
53
  "test-types": "tsc -p ./tests/types/tsconfig.json",
54
+ "test-api-symmetry": "node ./tests/api-symmetry/audit.js",
55
+ "test-api-shape": "node ./tests/api-symmetry/shape.js",
54
56
  "test-firefox": "node ./tests/browser-runner.js firefox",
55
57
  "test-chrome": "node ./tests/browser-runner.js chrome",
56
- "test-webkit": "node ./tests/browser-runner.js webkit"
58
+ "test-safari": "node ./tests/browser-runner.js safari"
57
59
  },
58
60
  "main": "./index.cjs",
59
61
  "module": "./index.js",
@@ -260,8 +262,8 @@
260
262
  "@rollup/plugin-terser": "^1.0.0",
261
263
  "eslint": "^10.8.1",
262
264
  "http-server": "^14.1.1",
263
- "playwright": "^1.62.1",
264
265
  "rollup": "^4.62.4",
266
+ "selenium-webdriver": "^4.47.0",
265
267
  "typedoc": "^0.28.20",
266
268
  "typedoc-plugin-markdown": "^4.12.0",
267
269
  "web-streams-polyfill": "^4.3.0",