@loaders.gl/zip 4.1.0-alpha.1 → 4.1.0-alpha.11

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 (68) hide show
  1. package/dist/dist.dev.js +875 -64
  2. package/dist/filesystems/zip-filesystem.d.ts.map +1 -1
  3. package/dist/filesystems/zip-filesystem.js.map +1 -1
  4. package/dist/hash-file-utility.d.ts +19 -0
  5. package/dist/hash-file-utility.d.ts.map +1 -1
  6. package/dist/hash-file-utility.js +30 -0
  7. package/dist/hash-file-utility.js.map +1 -1
  8. package/dist/index.cjs +542 -56
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/lib/tar/header.d.ts.map +1 -1
  14. package/dist/lib/tar/header.js.map +1 -1
  15. package/dist/lib/tar/tar.d.ts.map +1 -1
  16. package/dist/lib/tar/tar.js.map +1 -1
  17. package/dist/lib/tar/types.d.ts.map +1 -1
  18. package/dist/lib/tar/types.js.map +1 -1
  19. package/dist/lib/tar/utils.d.ts.map +1 -1
  20. package/dist/lib/tar/utils.js.map +1 -1
  21. package/dist/parse-zip/cd-file-header.d.ts +1 -1
  22. package/dist/parse-zip/cd-file-header.d.ts.map +1 -1
  23. package/dist/parse-zip/cd-file-header.js +4 -4
  24. package/dist/parse-zip/cd-file-header.js.map +1 -1
  25. package/dist/parse-zip/end-of-central-directory.d.ts +35 -0
  26. package/dist/parse-zip/end-of-central-directory.d.ts.map +1 -1
  27. package/dist/parse-zip/end-of-central-directory.js +161 -9
  28. package/dist/parse-zip/end-of-central-directory.js.map +1 -1
  29. package/dist/parse-zip/local-file-header.d.ts +16 -0
  30. package/dist/parse-zip/local-file-header.d.ts.map +1 -1
  31. package/dist/parse-zip/local-file-header.js +73 -1
  32. package/dist/parse-zip/local-file-header.js.map +1 -1
  33. package/dist/parse-zip/search-from-the-end.d.ts.map +1 -1
  34. package/dist/parse-zip/search-from-the-end.js.map +1 -1
  35. package/dist/parse-zip/zip-composition.d.ts +38 -0
  36. package/dist/parse-zip/zip-composition.d.ts.map +1 -0
  37. package/dist/parse-zip/zip-composition.js +115 -0
  38. package/dist/parse-zip/zip-composition.js.map +1 -0
  39. package/dist/parse-zip/zip64-info-generation.d.ts +5 -8
  40. package/dist/parse-zip/zip64-info-generation.d.ts.map +1 -1
  41. package/dist/parse-zip/zip64-info-generation.js +6 -3
  42. package/dist/parse-zip/zip64-info-generation.js.map +1 -1
  43. package/dist/tar-builder.d.ts.map +1 -1
  44. package/dist/tar-builder.js.map +1 -1
  45. package/dist/zip-loader.d.ts.map +1 -1
  46. package/dist/zip-loader.js +1 -1
  47. package/dist/zip-loader.js.map +1 -1
  48. package/dist/zip-writer.d.ts +2 -2
  49. package/dist/zip-writer.d.ts.map +1 -1
  50. package/dist/zip-writer.js +22 -7
  51. package/dist/zip-writer.js.map +1 -1
  52. package/package.json +7 -7
  53. package/src/filesystems/zip-filesystem.ts +2 -1
  54. package/src/hash-file-utility.ts +84 -3
  55. package/src/index.ts +6 -3
  56. package/src/lib/tar/header.ts +2 -1
  57. package/src/lib/tar/tar.ts +2 -1
  58. package/src/lib/tar/types.ts +2 -1
  59. package/src/lib/tar/utils.ts +2 -1
  60. package/src/parse-zip/cd-file-header.ts +8 -6
  61. package/src/parse-zip/end-of-central-directory.ts +338 -10
  62. package/src/parse-zip/local-file-header.ts +128 -2
  63. package/src/parse-zip/search-from-the-end.ts +2 -1
  64. package/src/parse-zip/zip-composition.ts +235 -0
  65. package/src/parse-zip/zip64-info-generation.ts +21 -5
  66. package/src/tar-builder.ts +2 -1
  67. package/src/zip-loader.ts +2 -1
  68. package/src/zip-writer.ts +24 -10
package/dist/index.cjs CHANGED
@@ -35,7 +35,11 @@ __export(src_exports, {
35
35
  ZipFileSystem: () => ZipFileSystem,
36
36
  ZipLoader: () => ZipLoader,
37
37
  ZipWriter: () => ZipWriter,
38
+ addOneFile: () => addOneFile,
39
+ composeHashFile: () => composeHashFile,
40
+ createZip: () => createZip,
38
41
  generateCDHeader: () => generateCDHeader,
42
+ generateLocalHeader: () => generateLocalHeader,
39
43
  localHeaderSignature: () => signature3,
40
44
  makeHashTableFromZipHeaders: () => makeHashTableFromZipHeaders,
41
45
  makeZipCDHeaderIterator: () => makeZipCDHeaderIterator,
@@ -94,27 +98,41 @@ async function loadZipEntry(jsZip, subFilename, options = {}) {
94
98
 
95
99
  // src/zip-writer.ts
96
100
  var import_jszip2 = __toESM(require("jszip"), 1);
101
+ var VERSION2 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
97
102
  var ZipWriter = {
98
103
  name: "Zip Archive",
104
+ id: "zip",
105
+ module: "zip",
106
+ version: VERSION2,
99
107
  extensions: ["zip"],
100
108
  category: "archive",
101
109
  mimeTypes: ["application/zip"],
102
- // @ts-ignore
110
+ options: {
111
+ zip: {
112
+ onUpdate: () => {
113
+ }
114
+ },
115
+ jszip: {}
116
+ },
103
117
  encode: encodeZipAsync
104
118
  };
105
119
  async function encodeZipAsync(fileMap, options = {}) {
120
+ var _a;
106
121
  const jsZip = new import_jszip2.default();
107
122
  for (const subFileName in fileMap) {
108
123
  const subFileData = fileMap[subFileName];
109
124
  jsZip.file(subFileName, subFileData, (options == null ? void 0 : options.jszip) || {});
110
125
  }
111
- const jszipOptions = { ...options == null ? void 0 : options.jszip, type: "arraybuffer" };
112
- const { onUpdate = () => {
113
- } } = options;
126
+ const zipOptions = { ...ZipWriter.options.zip, ...options == null ? void 0 : options.zip };
127
+ const jszipOptions = { ...(_a = ZipWriter.options) == null ? void 0 : _a.jszip, ...options.jszip };
114
128
  try {
115
- return await jsZip.generateAsync(jszipOptions, onUpdate);
129
+ return await jsZip.generateAsync(
130
+ { ...jszipOptions, type: "arraybuffer" },
131
+ // generate an arraybuffer
132
+ zipOptions.onUpdate
133
+ );
116
134
  } catch (error) {
117
- options.log.error(`Unable to write zip archive: ${error}`);
135
+ options.log.error(`Unable to encode zip archive: ${error}`);
118
136
  throw error;
119
137
  }
120
138
  }
@@ -338,7 +356,7 @@ var TarBuilder = class {
338
356
  var import_loader_utils3 = require("@loaders.gl/loader-utils");
339
357
 
340
358
  // src/parse-zip/end-of-central-directory.ts
341
- var import_loader_utils = require("@loaders.gl/loader-utils");
359
+ var import_loader_utils2 = require("@loaders.gl/loader-utils");
342
360
 
343
361
  // src/parse-zip/search-from-the-end.ts
344
362
  var searchFromTheEnd = async (file, target) => {
@@ -362,43 +380,8 @@ var searchFromTheEnd = async (file, target) => {
362
380
  return targetOffset;
363
381
  };
364
382
 
365
- // src/parse-zip/end-of-central-directory.ts
366
- var eoCDSignature = new Uint8Array([80, 75, 5, 6]);
367
- var zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
368
- var zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
369
- var CD_RECORDS_NUMBER_OFFSET = 8n;
370
- var CD_START_OFFSET_OFFSET = 16n;
371
- var ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
372
- var ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
373
- var ZIP64_CD_START_OFFSET_OFFSET = 48n;
374
- var parseEoCDRecord = async (file) => {
375
- const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
376
- let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));
377
- let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));
378
- if (cdStartOffset === BigInt(4294967295) || cdRecordsNumber === BigInt(4294967295)) {
379
- const zip64EoCDLocatorOffset = zipEoCDOffset - 20n;
380
- const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);
381
- if (!(0, import_loader_utils.compareArrayBuffers)(magicBytes, zip64EoCDLocatorSignature)) {
382
- throw new Error("zip64 EoCD locator not found");
383
- }
384
- const zip64EoCDOffset = await file.getBigUint64(
385
- zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET
386
- );
387
- const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n);
388
- if (!(0, import_loader_utils.compareArrayBuffers)(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {
389
- throw new Error("zip64 EoCD not found");
390
- }
391
- cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);
392
- cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);
393
- }
394
- return {
395
- cdRecordsNumber,
396
- cdStartOffset
397
- };
398
- };
399
-
400
383
  // src/parse-zip/zip64-info-generation.ts
401
- var import_loader_utils2 = require("@loaders.gl/loader-utils");
384
+ var import_loader_utils = require("@loaders.gl/loader-utils");
402
385
  var signature = new Uint8Array([1, 0]);
403
386
  function createZip64Info(options) {
404
387
  const optionsToUse = {
@@ -414,14 +397,17 @@ function createZip64Info(options) {
414
397
  NUMBER_SETTERS[field.size](newValue, 0, optionsToUse[field.name ?? ""] ?? field.default);
415
398
  arraysToConcat.push(newValue.buffer);
416
399
  }
417
- return (0, import_loader_utils2.concatenateArrayBuffers)(...arraysToConcat);
400
+ return (0, import_loader_utils.concatenateArrayBuffers)(...arraysToConcat);
401
+ }
402
+ function setFieldToNumber(header, fieldSize, fieldOffset, value) {
403
+ NUMBER_SETTERS[fieldSize](header, Number(fieldOffset), value);
418
404
  }
419
405
  var NUMBER_SETTERS = {
420
406
  2: (header, offset, value) => {
421
- header.setUint16(offset, value, true);
407
+ header.setUint16(offset, Number(value > 65535 ? 65535 : value), true);
422
408
  },
423
409
  4: (header, offset, value) => {
424
- header.setUint32(offset, value, true);
410
+ header.setUint32(offset, Number(value > 4294967295 ? 4294967295 : value), true);
425
411
  },
426
412
  8: (header, offset, value) => {
427
413
  header.setBigUint64(offset, BigInt(value), true);
@@ -455,6 +441,261 @@ var ZIP64_FIELDS = [
455
441
  }
456
442
  ];
457
443
 
444
+ // src/parse-zip/end-of-central-directory.ts
445
+ var eoCDSignature = new Uint8Array([80, 75, 5, 6]);
446
+ var zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
447
+ var zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
448
+ var CD_RECORDS_NUMBER_OFFSET = 8n;
449
+ var CD_RECORDS_NUMBER_ON_DISC_OFFSET = 10n;
450
+ var CD_CD_BYTE_SIZE_OFFSET = 12n;
451
+ var CD_START_OFFSET_OFFSET = 16n;
452
+ var CD_COMMENT_OFFSET = 22n;
453
+ var ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
454
+ var ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
455
+ var ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET = 32n;
456
+ var ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;
457
+ var ZIP64_CD_START_OFFSET_OFFSET = 48n;
458
+ var ZIP64_COMMENT_OFFSET = 56n;
459
+ var parseEoCDRecord = async (file) => {
460
+ const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
461
+ let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));
462
+ let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));
463
+ let zip64EoCDLocatorOffset = zipEoCDOffset - 20n;
464
+ let zip64EoCDOffset = 0n;
465
+ const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);
466
+ if ((0, import_loader_utils2.compareArrayBuffers)(magicBytes, zip64EoCDLocatorSignature)) {
467
+ zip64EoCDOffset = await file.getBigUint64(
468
+ zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET
469
+ );
470
+ const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n);
471
+ if (!(0, import_loader_utils2.compareArrayBuffers)(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {
472
+ throw new Error("zip64 EoCD not found");
473
+ }
474
+ cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);
475
+ cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);
476
+ } else {
477
+ zip64EoCDLocatorOffset = 0n;
478
+ }
479
+ return {
480
+ cdRecordsNumber,
481
+ cdStartOffset,
482
+ offsets: {
483
+ zip64EoCDOffset,
484
+ zip64EoCDLocatorOffset,
485
+ zipEoCDOffset
486
+ }
487
+ };
488
+ };
489
+ function updateEoCD(eocdBody, oldEoCDOffsets, newCDStartOffset, eocdStartOffset, newCDRecordsNumber) {
490
+ const eocd = new DataView(eocdBody);
491
+ const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset : 0n;
492
+ if (Number(newCDRecordsNumber) <= 65535) {
493
+ setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
494
+ setFieldToNumber(
495
+ eocd,
496
+ 2,
497
+ classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET,
498
+ newCDRecordsNumber
499
+ );
500
+ }
501
+ if (eocdStartOffset - newCDStartOffset <= 4294967295) {
502
+ setFieldToNumber(
503
+ eocd,
504
+ 4,
505
+ classicEoCDOffset + CD_CD_BYTE_SIZE_OFFSET,
506
+ eocdStartOffset - newCDStartOffset
507
+ );
508
+ }
509
+ if (newCDStartOffset < 4294967295) {
510
+ setFieldToNumber(eocd, 4, classicEoCDOffset + CD_START_OFFSET_OFFSET, newCDStartOffset);
511
+ }
512
+ if (oldEoCDOffsets.zip64EoCDLocatorOffset && oldEoCDOffsets.zip64EoCDOffset) {
513
+ const locatorOffset = oldEoCDOffsets.zip64EoCDLocatorOffset - oldEoCDOffsets.zip64EoCDOffset;
514
+ setFieldToNumber(eocd, 8, locatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET, eocdStartOffset);
515
+ setFieldToNumber(eocd, 8, ZIP64_CD_START_OFFSET_OFFSET, newCDStartOffset);
516
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
517
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
518
+ setFieldToNumber(eocd, 8, ZIP64_CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);
519
+ }
520
+ return new Uint8Array(eocd.buffer);
521
+ }
522
+ function generateEoCD(options) {
523
+ const header = new DataView(new ArrayBuffer(Number(CD_COMMENT_OFFSET)));
524
+ for (const field of EOCD_FIELDS) {
525
+ setFieldToNumber(
526
+ header,
527
+ field.size,
528
+ field.offset,
529
+ options[field.name ?? ""] ?? field.default ?? 0
530
+ );
531
+ }
532
+ const locator = generateZip64InfoLocator(options);
533
+ const zip64Record = generateZip64Info(options);
534
+ return (0, import_loader_utils2.concatenateArrayBuffers)(zip64Record, locator, header.buffer);
535
+ }
536
+ var EOCD_FIELDS = [
537
+ // End of central directory signature = 0x06054b50
538
+ {
539
+ offset: 0,
540
+ size: 4,
541
+ default: new DataView(eoCDSignature.buffer).getUint32(0, true)
542
+ },
543
+ // Number of this disk (or 0xffff for ZIP64)
544
+ {
545
+ offset: 4,
546
+ size: 2,
547
+ default: 0
548
+ },
549
+ // Disk where central directory starts (or 0xffff for ZIP64)
550
+ {
551
+ offset: 6,
552
+ size: 2,
553
+ default: 0
554
+ },
555
+ // Number of central directory records on this disk (or 0xffff for ZIP64)
556
+ {
557
+ offset: 8,
558
+ size: 2,
559
+ name: "recordsNumber"
560
+ },
561
+ // Total number of central directory records (or 0xffff for ZIP64)
562
+ {
563
+ offset: 10,
564
+ size: 2,
565
+ name: "recordsNumber"
566
+ },
567
+ // Size of central directory (bytes) (or 0xffffffff for ZIP64)
568
+ {
569
+ offset: 12,
570
+ size: 4,
571
+ name: "cdSize"
572
+ },
573
+ // Offset of start of central directory, relative to start of archive (or 0xffffffff for ZIP64)
574
+ {
575
+ offset: 16,
576
+ size: 4,
577
+ name: "cdOffset"
578
+ },
579
+ // Comment length (n)
580
+ {
581
+ offset: 20,
582
+ size: 2,
583
+ default: 0
584
+ }
585
+ ];
586
+ function generateZip64Info(options) {
587
+ const record = new DataView(new ArrayBuffer(Number(ZIP64_COMMENT_OFFSET)));
588
+ for (const field of ZIP64_EOCD_FIELDS) {
589
+ setFieldToNumber(
590
+ record,
591
+ field.size,
592
+ field.offset,
593
+ options[field.name ?? ""] ?? field.default ?? 0
594
+ );
595
+ }
596
+ return record.buffer;
597
+ }
598
+ function generateZip64InfoLocator(options) {
599
+ const locator = new DataView(new ArrayBuffer(Number(20)));
600
+ for (const field of ZIP64_EOCD_LOCATOR_FIELDS) {
601
+ setFieldToNumber(
602
+ locator,
603
+ field.size,
604
+ field.offset,
605
+ options[field.name ?? ""] ?? field.default ?? 0
606
+ );
607
+ }
608
+ return locator.buffer;
609
+ }
610
+ var ZIP64_EOCD_LOCATOR_FIELDS = [
611
+ // zip64 end of central dir locator signature
612
+ {
613
+ offset: 0,
614
+ size: 4,
615
+ default: new DataView(zip64EoCDLocatorSignature.buffer).getUint32(0, true)
616
+ },
617
+ // number of the disk with the start of the zip64 end of
618
+ {
619
+ offset: 4,
620
+ size: 4,
621
+ default: 0
622
+ },
623
+ // start of the zip64 end of central directory
624
+ {
625
+ offset: 8,
626
+ size: 8,
627
+ name: "eoCDStart"
628
+ },
629
+ // total number of disks
630
+ {
631
+ offset: 16,
632
+ size: 4,
633
+ default: 1
634
+ }
635
+ ];
636
+ var ZIP64_EOCD_FIELDS = [
637
+ // End of central directory signature = 0x06064b50
638
+ {
639
+ offset: 0,
640
+ size: 4,
641
+ default: new DataView(zip64EoCDSignature.buffer).getUint32(0, true)
642
+ },
643
+ // Size of the EOCD64 minus 12
644
+ {
645
+ offset: 4,
646
+ size: 8,
647
+ default: 44
648
+ },
649
+ // Version made by
650
+ {
651
+ offset: 12,
652
+ size: 2,
653
+ default: 45
654
+ },
655
+ // Version needed to extract (minimum)
656
+ {
657
+ offset: 14,
658
+ size: 2,
659
+ default: 45
660
+ },
661
+ // Number of this disk
662
+ {
663
+ offset: 16,
664
+ size: 4,
665
+ default: 0
666
+ },
667
+ // Disk where central directory starts
668
+ {
669
+ offset: 20,
670
+ size: 4,
671
+ default: 0
672
+ },
673
+ // Number of central directory records on this disk
674
+ {
675
+ offset: 24,
676
+ size: 8,
677
+ name: "recordsNumber"
678
+ },
679
+ // Total number of central directory records
680
+ {
681
+ offset: 32,
682
+ size: 8,
683
+ name: "recordsNumber"
684
+ },
685
+ // Size of central directory (bytes)
686
+ {
687
+ offset: 40,
688
+ size: 8,
689
+ name: "cdSize"
690
+ },
691
+ // Offset of start of central directory, relative to start of archive
692
+ {
693
+ offset: 48,
694
+ size: 8,
695
+ name: "cdOffset"
696
+ }
697
+ ];
698
+
458
699
  // src/parse-zip/cd-file-header.ts
459
700
  var CD_COMPRESSED_SIZE_OFFSET = 20n;
460
701
  var CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
@@ -558,7 +799,7 @@ function generateCDHeader(options) {
558
799
  const optionsToZip64 = {};
559
800
  if (optionsToUse.offset >= 4294967295) {
560
801
  optionsToZip64.offset = optionsToUse.offset;
561
- optionsToUse.offset = 4294967295;
802
+ optionsToUse.offset = BigInt(4294967295);
562
803
  }
563
804
  if (optionsToUse.length >= 4294967295) {
564
805
  optionsToZip64.size = optionsToUse.length;
@@ -568,10 +809,11 @@ function generateCDHeader(options) {
568
809
  zip64header = createZip64Info(optionsToZip64);
569
810
  optionsToUse.extraLength = zip64header.byteLength;
570
811
  }
571
- const header = new DataView(new ArrayBuffer(46));
812
+ const header = new DataView(new ArrayBuffer(Number(CD_FILE_NAME_OFFSET)));
572
813
  for (const field of ZIP_HEADER_FIELDS) {
573
- NUMBER_SETTERS[field.size](
814
+ setFieldToNumber(
574
815
  header,
816
+ field.size,
575
817
  field.offset,
576
818
  optionsToUse[field.name ?? ""] ?? field.default ?? 0
577
819
  );
@@ -734,9 +976,222 @@ var parseZipLocalFileHeader = async (headerOffset, buffer) => {
734
976
  compressionMethod
735
977
  };
736
978
  };
979
+ function generateLocalHeader(options) {
980
+ const optionsToUse = {
981
+ ...options,
982
+ extraLength: 0,
983
+ fnlength: options.fileName.length
984
+ };
985
+ let zip64header = new ArrayBuffer(0);
986
+ const optionsToZip64 = {};
987
+ if (optionsToUse.length >= 4294967295) {
988
+ optionsToZip64.size = optionsToUse.length;
989
+ optionsToUse.length = 4294967295;
990
+ }
991
+ if (Object.keys(optionsToZip64).length) {
992
+ zip64header = createZip64Info(optionsToZip64);
993
+ optionsToUse.extraLength = zip64header.byteLength;
994
+ }
995
+ const header = new DataView(new ArrayBuffer(Number(FILE_NAME_OFFSET)));
996
+ for (const field of ZIP_HEADER_FIELDS2) {
997
+ setFieldToNumber(
998
+ header,
999
+ field.size,
1000
+ field.offset,
1001
+ optionsToUse[field.name ?? ""] ?? field.default ?? 0
1002
+ );
1003
+ }
1004
+ const encodedName = new TextEncoder().encode(optionsToUse.fileName);
1005
+ const resHeader = (0, import_loader_utils4.concatenateArrayBuffers)(header.buffer, encodedName, zip64header);
1006
+ return resHeader;
1007
+ }
1008
+ var ZIP_HEADER_FIELDS2 = [
1009
+ // Local file header signature = 0x04034b50
1010
+ {
1011
+ offset: 0,
1012
+ size: 4,
1013
+ default: new DataView(signature3.buffer).getUint32(0, true)
1014
+ },
1015
+ // Version needed to extract (minimum)
1016
+ {
1017
+ offset: 4,
1018
+ size: 2,
1019
+ default: 45
1020
+ },
1021
+ // General purpose bit flag
1022
+ {
1023
+ offset: 6,
1024
+ size: 2,
1025
+ default: 0
1026
+ },
1027
+ // Compression method
1028
+ {
1029
+ offset: 8,
1030
+ size: 2,
1031
+ default: 0
1032
+ },
1033
+ // File last modification time
1034
+ {
1035
+ offset: 10,
1036
+ size: 2,
1037
+ default: 0
1038
+ },
1039
+ // File last modification date
1040
+ {
1041
+ offset: 12,
1042
+ size: 2,
1043
+ default: 0
1044
+ },
1045
+ // CRC-32 of uncompressed data
1046
+ {
1047
+ offset: 14,
1048
+ size: 4,
1049
+ name: "crc32"
1050
+ },
1051
+ // Compressed size (or 0xffffffff for ZIP64)
1052
+ {
1053
+ offset: 18,
1054
+ size: 4,
1055
+ name: "length"
1056
+ },
1057
+ // Uncompressed size (or 0xffffffff for ZIP64)
1058
+ {
1059
+ offset: 22,
1060
+ size: 4,
1061
+ name: "length"
1062
+ },
1063
+ // File name length (n)
1064
+ {
1065
+ offset: 26,
1066
+ size: 2,
1067
+ name: "fnlength"
1068
+ },
1069
+ // Extra field length (m)
1070
+ {
1071
+ offset: 28,
1072
+ size: 2,
1073
+ default: 0,
1074
+ name: "extraLength"
1075
+ }
1076
+ ];
737
1077
 
738
- // src/hash-file-utility.ts
1078
+ // src/parse-zip/zip-composition.ts
1079
+ var import_loader_utils5 = require("@loaders.gl/loader-utils");
739
1080
  var import_crypto = require("@loaders.gl/crypto");
1081
+ var import_core = require("@loaders.gl/core");
1082
+ async function cutTheTailOff(provider) {
1083
+ const oldEoCDinfo = await parseEoCDRecord(provider);
1084
+ const oldCDStartOffset = oldEoCDinfo.cdStartOffset;
1085
+ const oldCDLength = Number(
1086
+ oldEoCDinfo.offsets.zip64EoCDOffset ? oldEoCDinfo.offsets.zip64EoCDOffset - oldCDStartOffset : oldEoCDinfo.offsets.zipEoCDOffset - oldCDStartOffset
1087
+ );
1088
+ const zipEnding = await provider.slice(oldCDStartOffset, provider.length);
1089
+ await provider.truncate(Number(oldCDStartOffset));
1090
+ const oldCDBody = zipEnding.slice(0, oldCDLength);
1091
+ const eocdBody = zipEnding.slice(oldCDLength, zipEnding.byteLength);
1092
+ return [oldCDBody, eocdBody, oldEoCDinfo];
1093
+ }
1094
+ async function generateFileHeaders(fileName, fileToAdd, localFileHeaderOffset) {
1095
+ const newFileCRC322 = parseInt(await new import_crypto.CRC32Hash().hash(fileToAdd, "hex"), 16);
1096
+ const newFileLocalHeader = generateLocalHeader({
1097
+ crc32: newFileCRC322,
1098
+ fileName,
1099
+ length: fileToAdd.byteLength
1100
+ });
1101
+ const newFileCDHeader = generateCDHeader({
1102
+ crc32: newFileCRC322,
1103
+ fileName,
1104
+ offset: localFileHeaderOffset,
1105
+ length: fileToAdd.byteLength
1106
+ });
1107
+ return [
1108
+ new Uint8Array((0, import_loader_utils5.concatenateArrayBuffers)(newFileLocalHeader, fileToAdd)),
1109
+ new Uint8Array(newFileCDHeader)
1110
+ ];
1111
+ }
1112
+ async function addOneFile(zipUrl, fileToAdd, fileName) {
1113
+ const provider = new import_loader_utils5.FileHandleFile(zipUrl, true);
1114
+ const [oldCDBody, eocdBody, oldEoCDinfo] = await cutTheTailOff(provider);
1115
+ const newFileOffset = provider.length;
1116
+ const [localPart, cdHeaderPart] = await generateFileHeaders(fileName, fileToAdd, newFileOffset);
1117
+ await provider.append(localPart);
1118
+ const newCDBody = (0, import_loader_utils5.concatenateArrayBuffers)(oldCDBody, cdHeaderPart);
1119
+ const newCDStartOffset = provider.length;
1120
+ await provider.append(new Uint8Array(newCDBody));
1121
+ const eocdOffset = provider.length;
1122
+ await provider.append(
1123
+ updateEoCD(
1124
+ eocdBody,
1125
+ oldEoCDinfo.offsets,
1126
+ newCDStartOffset,
1127
+ eocdOffset,
1128
+ oldEoCDinfo.cdRecordsNumber + 1n
1129
+ )
1130
+ );
1131
+ }
1132
+ async function createZip(inputPath, outputPath, createAdditionalData) {
1133
+ const fileIterator = getFileIterator(inputPath);
1134
+ const resFile = new import_loader_utils5.NodeFile(outputPath, "w");
1135
+ const fileList = [];
1136
+ const cdArray = [];
1137
+ for await (const file of fileIterator) {
1138
+ await addFile(file, resFile, cdArray, fileList);
1139
+ }
1140
+ if (createAdditionalData) {
1141
+ const additionaldata = await createAdditionalData(fileList);
1142
+ console.log(additionaldata);
1143
+ await addFile(additionaldata, resFile, cdArray);
1144
+ }
1145
+ const cdOffset = (await resFile.stat()).bigsize;
1146
+ const cd = (0, import_loader_utils5.concatenateArrayBuffers)(...cdArray);
1147
+ await resFile.append(new Uint8Array(cd));
1148
+ const eoCDStart = (await resFile.stat()).bigsize;
1149
+ await resFile.append(
1150
+ new Uint8Array(
1151
+ generateEoCD({ recordsNumber: cdArray.length, cdSize: cd.byteLength, cdOffset, eoCDStart })
1152
+ )
1153
+ );
1154
+ }
1155
+ async function addFile(file, resFile, cdArray, fileList) {
1156
+ const size = (await resFile.stat()).bigsize;
1157
+ fileList == null ? void 0 : fileList.push({ fileName: file.path, localHeaderOffset: size });
1158
+ const [localPart, cdHeaderPart] = await generateFileHeaders(file.path, file.file, size);
1159
+ await resFile.append(localPart);
1160
+ cdArray.push(cdHeaderPart);
1161
+ }
1162
+ function getFileIterator(inputPath) {
1163
+ async function* iterable() {
1164
+ const fileList = await getAllFiles(inputPath);
1165
+ for (const filePath of fileList) {
1166
+ const file = await (await (0, import_core.fetchFile)(import_loader_utils5.path.join(inputPath, filePath))).arrayBuffer();
1167
+ yield { path: filePath, file };
1168
+ }
1169
+ }
1170
+ return iterable();
1171
+ }
1172
+ async function getAllFiles(basePath, subfolder = "", fsPassed) {
1173
+ const fs = fsPassed ? fsPassed : new import_loader_utils5.NodeFilesystem({});
1174
+ const files = await fs.readdir(pathJoin(basePath, subfolder));
1175
+ const arrayOfFiles = [];
1176
+ for (const file of files) {
1177
+ const fullPath = pathJoin(basePath, subfolder, file);
1178
+ if ((await fs.stat(fullPath)).isDirectory) {
1179
+ const files2 = await getAllFiles(basePath, pathJoin(subfolder, file));
1180
+ arrayOfFiles.push(...files2);
1181
+ } else {
1182
+ arrayOfFiles.push(pathJoin(subfolder, file));
1183
+ }
1184
+ }
1185
+ return arrayOfFiles;
1186
+ }
1187
+ function pathJoin(...paths) {
1188
+ const resPaths = paths.filter((val) => val.length);
1189
+ return import_loader_utils5.path.join(...resPaths);
1190
+ }
1191
+
1192
+ // src/hash-file-utility.ts
1193
+ var import_crypto2 = require("@loaders.gl/crypto");
1194
+ var import_loader_utils6 = require("@loaders.gl/loader-utils");
740
1195
  function parseHashTable(arrayBuffer) {
741
1196
  const dataView = new DataView(arrayBuffer);
742
1197
  const hashMap = {};
@@ -752,7 +1207,10 @@ function bufferToHex(buffer, start, length) {
752
1207
  }
753
1208
  async function makeHashTableFromZipHeaders(fileProvider) {
754
1209
  const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
755
- const md5Hash = new import_crypto.MD5Hash();
1210
+ return getHashTable(zipCDIterator);
1211
+ }
1212
+ async function getHashTable(zipCDIterator) {
1213
+ const md5Hash = new import_crypto2.MD5Hash();
756
1214
  const textEncoder = new TextEncoder();
757
1215
  const hashTable = {};
758
1216
  for await (const cdHeader of zipCDIterator) {
@@ -763,11 +1221,39 @@ async function makeHashTableFromZipHeaders(fileProvider) {
763
1221
  }
764
1222
  return hashTable;
765
1223
  }
1224
+ async function composeHashFile(zipCDIterator) {
1225
+ const md5Hash = new import_crypto2.MD5Hash();
1226
+ const textEncoder = new TextEncoder();
1227
+ const hashArray = [];
1228
+ for await (const cdHeader of zipCDIterator) {
1229
+ const filename = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
1230
+ const arrayBuffer = textEncoder.encode(filename).buffer;
1231
+ const md5 = await md5Hash.hash(arrayBuffer, "hex");
1232
+ hashArray.push(
1233
+ (0, import_loader_utils6.concatenateArrayBuffers)(hexStringToBuffer(md5), bigintToBuffer(cdHeader.localHeaderOffset))
1234
+ );
1235
+ }
1236
+ const bufferArray = hashArray.sort(compareHashes);
1237
+ return (0, import_loader_utils6.concatenateArrayBuffersFromArray)(bufferArray);
1238
+ }
1239
+ function compareHashes(arrA, arrB) {
1240
+ const a = new BigUint64Array(arrA);
1241
+ const b = new BigUint64Array(arrB);
1242
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
1243
+ }
1244
+ function hexStringToBuffer(str) {
1245
+ var _a;
1246
+ const byteArray = (_a = str.match(/../g)) == null ? void 0 : _a.map((h) => parseInt(h, 16));
1247
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
1248
+ }
1249
+ function bigintToBuffer(n) {
1250
+ return new BigUint64Array([n]).buffer;
1251
+ }
766
1252
 
767
1253
  // src/filesystems/zip-filesystem.ts
768
- var import_loader_utils5 = require("@loaders.gl/loader-utils");
769
- var import_loader_utils6 = require("@loaders.gl/loader-utils");
770
1254
  var import_loader_utils7 = require("@loaders.gl/loader-utils");
1255
+ var import_loader_utils8 = require("@loaders.gl/loader-utils");
1256
+ var import_loader_utils9 = require("@loaders.gl/loader-utils");
771
1257
  var import_compression = require("@loaders.gl/compression");
772
1258
  var COMPRESSION_METHODS = {
773
1259
  /** No compression */
@@ -789,12 +1275,12 @@ var ZipFileSystem = class {
789
1275
  this.fileProvider = null;
790
1276
  if (typeof file === "string") {
791
1277
  this.fileName = file;
792
- if (!import_loader_utils5.isBrowser) {
793
- this.fileProvider = new import_loader_utils7.FileHandleFile(file);
1278
+ if (!import_loader_utils7.isBrowser) {
1279
+ this.fileProvider = new import_loader_utils9.FileHandleFile(file);
794
1280
  } else {
795
1281
  throw new Error("Cannot open file for random access in a WEB browser");
796
1282
  }
797
- } else if ((0, import_loader_utils6.isFileProvider)(file)) {
1283
+ } else if ((0, import_loader_utils8.isFileProvider)(file)) {
798
1284
  this.fileProvider = file;
799
1285
  }
800
1286
  }