@loaders.gl/zip 4.1.0-alpha.1 → 4.1.0-alpha.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.
Files changed (68) hide show
  1. package/dist/dist.dev.js +313 -51
  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 +6 -0
  5. package/dist/hash-file-utility.d.ts.map +1 -1
  6. package/dist/hash-file-utility.js +22 -0
  7. package/dist/hash-file-utility.js.map +1 -1
  8. package/dist/index.cjs +290 -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 +19 -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 +41 -8
  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-compozition.d.ts +8 -0
  36. package/dist/parse-zip/zip-compozition.d.ts.map +1 -0
  37. package/dist/parse-zip/zip-compozition.js +43 -0
  38. package/dist/parse-zip/zip-compozition.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 +52 -2
  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 +99 -9
  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-compozition.ts +113 -0
  65. package/src/parse-zip/zip64-info-generation.ts +20 -4
  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/dist.dev.js CHANGED
@@ -6956,7 +6956,10 @@ var __exports__ = (() => {
6956
6956
  ZipFileSystem: () => ZipFileSystem,
6957
6957
  ZipLoader: () => ZipLoader,
6958
6958
  ZipWriter: () => ZipWriter,
6959
+ addOneFile: () => addOneFile,
6960
+ composeHashFile: () => composeHashFile,
6959
6961
  generateCDHeader: () => generateCDHeader,
6962
+ generateLocalHeader: () => generateLocalHeader,
6960
6963
  localHeaderSignature: () => signature3,
6961
6964
  makeHashTableFromZipHeaders: () => makeHashTableFromZipHeaders,
6962
6965
  makeZipCDHeaderIterator: () => makeZipCDHeaderIterator,
@@ -6969,7 +6972,7 @@ var __exports__ = (() => {
6969
6972
 
6970
6973
  // src/zip-loader.ts
6971
6974
  var import_jszip = __toESM(require_jszip_min(), 1);
6972
- var VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
6975
+ var VERSION = true ? "4.1.0-alpha.10" : "latest";
6973
6976
  var ZipLoader = {
6974
6977
  id: "zip",
6975
6978
  module: "zip",
@@ -7014,11 +7017,22 @@ var __exports__ = (() => {
7014
7017
 
7015
7018
  // src/zip-writer.ts
7016
7019
  var import_jszip2 = __toESM(require_jszip_min(), 1);
7020
+ var VERSION2 = true ? "4.1.0-alpha.10" : "latest";
7017
7021
  var ZipWriter = {
7018
7022
  name: "Zip Archive",
7023
+ id: "zip",
7024
+ module: "zip",
7025
+ version: VERSION2,
7019
7026
  extensions: ["zip"],
7020
7027
  category: "archive",
7021
7028
  mimeTypes: ["application/zip"],
7029
+ options: {
7030
+ zip: {
7031
+ onUpdate: () => {
7032
+ }
7033
+ },
7034
+ jszip: {}
7035
+ },
7022
7036
  encode: encodeZipAsync
7023
7037
  };
7024
7038
  async function encodeZipAsync(fileMap, options = {}) {
@@ -7027,18 +7041,21 @@ var __exports__ = (() => {
7027
7041
  const subFileData = fileMap[subFileName];
7028
7042
  jsZip.file(subFileName, subFileData, options?.jszip || {});
7029
7043
  }
7044
+ const zipOptions = {
7045
+ ...ZipWriter.options.zip,
7046
+ ...options?.zip
7047
+ };
7030
7048
  const jszipOptions = {
7031
- ...options?.jszip,
7032
- type: "arraybuffer"
7049
+ ...ZipWriter.options?.jszip,
7050
+ ...options.jszip
7033
7051
  };
7034
- const {
7035
- onUpdate = () => {
7036
- }
7037
- } = options;
7038
7052
  try {
7039
- return await jsZip.generateAsync(jszipOptions, onUpdate);
7053
+ return await jsZip.generateAsync({
7054
+ ...jszipOptions,
7055
+ type: "arraybuffer"
7056
+ }, zipOptions.onUpdate);
7040
7057
  } catch (error) {
7041
- options.log.error(`Unable to write zip archive: ${error}`);
7058
+ options.log.error(`Unable to encode zip archive: ${error}`);
7042
7059
  throw error;
7043
7060
  }
7044
7061
  }
@@ -7279,6 +7296,9 @@ var __exports__ = (() => {
7279
7296
  return true;
7280
7297
  }
7281
7298
  function concatenateArrayBuffers(...sources) {
7299
+ return concatenateArrayBuffersFromArray(sources);
7300
+ }
7301
+ function concatenateArrayBuffersFromArray(sources) {
7282
7302
  const sourceArrays = sources.map((source2) => source2 instanceof ArrayBuffer ? new Uint8Array(source2) : source2);
7283
7303
  const byteLength = sourceArrays.reduce((length, typedArray) => length + typedArray.byteLength, 0);
7284
7304
  const result = new Uint8Array(byteLength);
@@ -7361,6 +7381,12 @@ var __exports__ = (() => {
7361
7381
  async stat() {
7362
7382
  throw NOT_IMPLEMENTED;
7363
7383
  }
7384
+ async truncate(length) {
7385
+ throw NOT_IMPLEMENTED;
7386
+ }
7387
+ async append(data) {
7388
+ throw NOT_IMPLEMENTED;
7389
+ }
7364
7390
  async close() {
7365
7391
  }
7366
7392
  };
@@ -7372,9 +7398,14 @@ var __exports__ = (() => {
7372
7398
 
7373
7399
  // ../loader-utils/src/lib/file-provider/file-handle-file.ts
7374
7400
  var FileHandleFile = class {
7375
- constructor(path) {
7376
- this.file = new NodeFileFacade(path, "r");
7377
- this.size = this.file.bigsize;
7401
+ constructor(path, append = false) {
7402
+ this.file = new NodeFileFacade(path, append ? "a+" : "r");
7403
+ }
7404
+ async truncate(length) {
7405
+ await this.file.truncate(length);
7406
+ }
7407
+ async append(buffer) {
7408
+ await this.file.append(buffer);
7378
7409
  }
7379
7410
  async destroy() {
7380
7411
  await this.file.close();
@@ -7420,7 +7451,7 @@ var __exports__ = (() => {
7420
7451
  return await this.file.read(startOffset, length);
7421
7452
  }
7422
7453
  get length() {
7423
- return this.size;
7454
+ return this.file.bigsize;
7424
7455
  }
7425
7456
  };
7426
7457
 
@@ -7441,39 +7472,6 @@ var __exports__ = (() => {
7441
7472
  return targetOffset;
7442
7473
  };
7443
7474
 
7444
- // src/parse-zip/end-of-central-directory.ts
7445
- var eoCDSignature = new Uint8Array([80, 75, 5, 6]);
7446
- var zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
7447
- var zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
7448
- var CD_RECORDS_NUMBER_OFFSET = 8n;
7449
- var CD_START_OFFSET_OFFSET = 16n;
7450
- var ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
7451
- var ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
7452
- var ZIP64_CD_START_OFFSET_OFFSET = 48n;
7453
- var parseEoCDRecord = async (file) => {
7454
- const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
7455
- let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));
7456
- let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));
7457
- if (cdStartOffset === BigInt(4294967295) || cdRecordsNumber === BigInt(4294967295)) {
7458
- const zip64EoCDLocatorOffset = zipEoCDOffset - 20n;
7459
- const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);
7460
- if (!compareArrayBuffers(magicBytes, zip64EoCDLocatorSignature)) {
7461
- throw new Error("zip64 EoCD locator not found");
7462
- }
7463
- const zip64EoCDOffset = await file.getBigUint64(zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET);
7464
- const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n);
7465
- if (!compareArrayBuffers(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {
7466
- throw new Error("zip64 EoCD not found");
7467
- }
7468
- cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);
7469
- cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);
7470
- }
7471
- return {
7472
- cdRecordsNumber,
7473
- cdStartOffset
7474
- };
7475
- };
7476
-
7477
7475
  // src/parse-zip/zip64-info-generation.ts
7478
7476
  var signature = new Uint8Array([1, 0]);
7479
7477
  function createZip64Info(options) {
@@ -7492,12 +7490,15 @@ var __exports__ = (() => {
7492
7490
  }
7493
7491
  return concatenateArrayBuffers(...arraysToConcat);
7494
7492
  }
7493
+ function setFieldToNumber(header, fieldSize, fieldOffset, value) {
7494
+ NUMBER_SETTERS[fieldSize](header, Number(fieldOffset), value);
7495
+ }
7495
7496
  var NUMBER_SETTERS = {
7496
7497
  2: (header, offset, value) => {
7497
- header.setUint16(offset, value, true);
7498
+ header.setUint16(offset, Number(value), true);
7498
7499
  },
7499
7500
  4: (header, offset, value) => {
7500
- header.setUint32(offset, value, true);
7501
+ header.setUint32(offset, Number(value), true);
7501
7502
  },
7502
7503
  8: (header, offset, value) => {
7503
7504
  header.setBigUint64(offset, BigInt(value), true);
@@ -7520,6 +7521,71 @@ var __exports__ = (() => {
7520
7521
  name: "offset"
7521
7522
  }];
7522
7523
 
7524
+ // src/parse-zip/end-of-central-directory.ts
7525
+ var eoCDSignature = new Uint8Array([80, 75, 5, 6]);
7526
+ var zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
7527
+ var zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
7528
+ var CD_RECORDS_NUMBER_OFFSET = 8n;
7529
+ var CD_RECORDS_NUMBER_ON_DISC_OFFSET = 10n;
7530
+ var CD_CD_BYTE_SIZE_OFFSET = 12n;
7531
+ var CD_START_OFFSET_OFFSET = 16n;
7532
+ var ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
7533
+ var ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
7534
+ var ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET = 32n;
7535
+ var ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;
7536
+ var ZIP64_CD_START_OFFSET_OFFSET = 48n;
7537
+ var parseEoCDRecord = async (file) => {
7538
+ const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
7539
+ let cdRecordsNumber = BigInt(await file.getUint16(zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));
7540
+ let cdStartOffset = BigInt(await file.getUint32(zipEoCDOffset + CD_START_OFFSET_OFFSET));
7541
+ let zip64EoCDLocatorOffset = zipEoCDOffset - 20n;
7542
+ let zip64EoCDOffset = 0n;
7543
+ const magicBytes = await file.slice(zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);
7544
+ if (compareArrayBuffers(magicBytes, zip64EoCDLocatorSignature)) {
7545
+ zip64EoCDOffset = await file.getBigUint64(zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET);
7546
+ const endOfCDMagicBytes = await file.slice(zip64EoCDOffset, zip64EoCDOffset + 4n);
7547
+ if (!compareArrayBuffers(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {
7548
+ throw new Error("zip64 EoCD not found");
7549
+ }
7550
+ cdRecordsNumber = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);
7551
+ cdStartOffset = await file.getBigUint64(zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);
7552
+ } else {
7553
+ zip64EoCDLocatorOffset = 0n;
7554
+ }
7555
+ return {
7556
+ cdRecordsNumber,
7557
+ cdStartOffset,
7558
+ offsets: {
7559
+ zip64EoCDOffset,
7560
+ zip64EoCDLocatorOffset,
7561
+ zipEoCDOffset
7562
+ }
7563
+ };
7564
+ };
7565
+ async function updateEoCD(eocdBody, oldEoCDOffsets, newCDStartOffset, eocdStartOffset, newCDRecordsNumber) {
7566
+ const eocd = new DataView(eocdBody);
7567
+ const classicEoCDOffset = oldEoCDOffsets.zip64EoCDOffset ? oldEoCDOffsets.zipEoCDOffset - oldEoCDOffsets.zip64EoCDOffset : 0n;
7568
+ if (Number(newCDRecordsNumber) <= 65535) {
7569
+ setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
7570
+ setFieldToNumber(eocd, 2, classicEoCDOffset + CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
7571
+ }
7572
+ if (eocdStartOffset - newCDStartOffset <= 4294967295) {
7573
+ setFieldToNumber(eocd, 4, classicEoCDOffset + CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);
7574
+ }
7575
+ if (newCDStartOffset < 4294967295) {
7576
+ setFieldToNumber(eocd, 4, classicEoCDOffset + CD_START_OFFSET_OFFSET, newCDStartOffset);
7577
+ }
7578
+ if (oldEoCDOffsets.zip64EoCDLocatorOffset && oldEoCDOffsets.zip64EoCDOffset) {
7579
+ const locatorOffset = oldEoCDOffsets.zip64EoCDLocatorOffset - oldEoCDOffsets.zip64EoCDOffset;
7580
+ setFieldToNumber(eocd, 8, locatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET, eocdStartOffset);
7581
+ setFieldToNumber(eocd, 8, ZIP64_CD_START_OFFSET_OFFSET, newCDStartOffset);
7582
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_OFFSET, newCDRecordsNumber);
7583
+ setFieldToNumber(eocd, 8, ZIP64_CD_RECORDS_NUMBER_ON_DISC_OFFSET, newCDRecordsNumber);
7584
+ setFieldToNumber(eocd, 8, ZIP64_CD_CD_BYTE_SIZE_OFFSET, eocdStartOffset - newCDStartOffset);
7585
+ }
7586
+ return new Uint8Array(eocd.buffer);
7587
+ }
7588
+
7523
7589
  // src/parse-zip/cd-file-header.ts
7524
7590
  var CD_COMPRESSED_SIZE_OFFSET = 20n;
7525
7591
  var CD_UNCOMPRESSED_SIZE_OFFSET = 24n;
@@ -7627,7 +7693,7 @@ var __exports__ = (() => {
7627
7693
  const optionsToZip64 = {};
7628
7694
  if (optionsToUse.offset >= 4294967295) {
7629
7695
  optionsToZip64.offset = optionsToUse.offset;
7630
- optionsToUse.offset = 4294967295;
7696
+ optionsToUse.offset = BigInt(4294967295);
7631
7697
  }
7632
7698
  if (optionsToUse.length >= 4294967295) {
7633
7699
  optionsToZip64.size = optionsToUse.length;
@@ -7637,9 +7703,9 @@ var __exports__ = (() => {
7637
7703
  zip64header = createZip64Info(optionsToZip64);
7638
7704
  optionsToUse.extraLength = zip64header.byteLength;
7639
7705
  }
7640
- const header = new DataView(new ArrayBuffer(46));
7706
+ const header = new DataView(new ArrayBuffer(Number(CD_FILE_NAME_OFFSET)));
7641
7707
  for (const field of ZIP_HEADER_FIELDS) {
7642
- NUMBER_SETTERS[field.size](header, field.offset, optionsToUse[field.name ?? ""] ?? field.default ?? 0);
7708
+ setFieldToNumber(header, field.size, field.offset, optionsToUse[field.name ?? ""] ?? field.default ?? 0);
7643
7709
  }
7644
7710
  const encodedName = new TextEncoder().encode(optionsToUse.fileName);
7645
7711
  const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
@@ -7758,6 +7824,76 @@ var __exports__ = (() => {
7758
7824
  compressionMethod
7759
7825
  };
7760
7826
  };
7827
+ function generateLocalHeader(options) {
7828
+ const optionsToUse = {
7829
+ ...options,
7830
+ extraLength: 0,
7831
+ fnlength: options.fileName.length
7832
+ };
7833
+ let zip64header = new ArrayBuffer(0);
7834
+ const optionsToZip64 = {};
7835
+ if (optionsToUse.length >= 4294967295) {
7836
+ optionsToZip64.size = optionsToUse.length;
7837
+ optionsToUse.length = 4294967295;
7838
+ }
7839
+ if (Object.keys(optionsToZip64).length) {
7840
+ zip64header = createZip64Info(optionsToZip64);
7841
+ optionsToUse.extraLength = zip64header.byteLength;
7842
+ }
7843
+ const header = new DataView(new ArrayBuffer(Number(FILE_NAME_OFFSET)));
7844
+ for (const field of ZIP_HEADER_FIELDS2) {
7845
+ setFieldToNumber(header, field.size, field.offset, optionsToUse[field.name ?? ""] ?? field.default ?? 0);
7846
+ }
7847
+ const encodedName = new TextEncoder().encode(optionsToUse.fileName);
7848
+ const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
7849
+ return resHeader;
7850
+ }
7851
+ var ZIP_HEADER_FIELDS2 = [{
7852
+ offset: 0,
7853
+ size: 4,
7854
+ default: new DataView(signature3.buffer).getUint32(0, true)
7855
+ }, {
7856
+ offset: 4,
7857
+ size: 2,
7858
+ default: 45
7859
+ }, {
7860
+ offset: 6,
7861
+ size: 2,
7862
+ default: 0
7863
+ }, {
7864
+ offset: 8,
7865
+ size: 2,
7866
+ default: 0
7867
+ }, {
7868
+ offset: 10,
7869
+ size: 2,
7870
+ default: 0
7871
+ }, {
7872
+ offset: 12,
7873
+ size: 2,
7874
+ default: 0
7875
+ }, {
7876
+ offset: 14,
7877
+ size: 4,
7878
+ name: "crc32"
7879
+ }, {
7880
+ offset: 18,
7881
+ size: 4,
7882
+ name: "length"
7883
+ }, {
7884
+ offset: 22,
7885
+ size: 4,
7886
+ name: "length"
7887
+ }, {
7888
+ offset: 26,
7889
+ size: 2,
7890
+ name: "fnlength"
7891
+ }, {
7892
+ offset: 28,
7893
+ size: 2,
7894
+ default: 0,
7895
+ name: "extraLength"
7896
+ }];
7761
7897
 
7762
7898
  // ../crypto/src/lib/hash.ts
7763
7899
  var Hash = class {
@@ -7784,6 +7920,29 @@ var __exports__ = (() => {
7784
7920
  }
7785
7921
  };
7786
7922
 
7923
+ // ../crypto/src/lib/algorithms/crc32.ts
7924
+ var CRC32 = class {
7925
+ constructor() {
7926
+ this.crc = ~0;
7927
+ }
7928
+ update(arrayBuffer) {
7929
+ const CRC32_TABLE = getCRC32Table();
7930
+ const byteArray = new Uint8Array(arrayBuffer);
7931
+ for (let i = 0; i < byteArray.byteLength; i++) {
7932
+ this.crc = this.crc >>> 8 ^ CRC32_TABLE[(this.crc ^ byteArray[i]) & 255];
7933
+ }
7934
+ return this;
7935
+ }
7936
+ finalize() {
7937
+ this.crc = (this.crc ^ -1) >>> 0;
7938
+ return this.crc;
7939
+ }
7940
+ };
7941
+ var CRC32TAB = Uint32Array.of(0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918e3, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117);
7942
+ function getCRC32Table() {
7943
+ return CRC32TAB;
7944
+ }
7945
+
7787
7946
  // ../crypto/src/lib/utils/base64-utils.ts
7788
7947
  function asciiToBase64(string) {
7789
7948
  string = `${string}`;
@@ -7835,6 +7994,16 @@ var __exports__ = (() => {
7835
7994
  }
7836
7995
 
7837
7996
  // ../crypto/src/lib/utils/digest-utils.ts
7997
+ function encodeNumber(number, encoding) {
7998
+ switch (encoding) {
7999
+ case "hex":
8000
+ return convertNumberToHex(number);
8001
+ case "base64":
8002
+ return convertHexToBase64(convertNumberToHex(number));
8003
+ default:
8004
+ throw new Error(encoding);
8005
+ }
8006
+ }
7838
8007
  function encodeHex(hex, encoding) {
7839
8008
  switch (encoding) {
7840
8009
  case "hex":
@@ -7853,6 +8022,43 @@ var __exports__ = (() => {
7853
8022
  const string = matches2.map((a) => String.fromCharCode(parseInt(a, 16))).join("");
7854
8023
  return asciiToBase64(string) || "";
7855
8024
  }
8025
+ function convertNumberToHex(cipher) {
8026
+ const hexString = cipher.toString(16);
8027
+ return hexString === "0" ? `0${hexString}` : hexString;
8028
+ }
8029
+
8030
+ // ../crypto/src/lib/crc32-hash.ts
8031
+ var CRC32Hash = class extends Hash {
8032
+ name = "crc32";
8033
+ constructor(options = {}) {
8034
+ super();
8035
+ this.options = {
8036
+ crypto: {},
8037
+ ...options
8038
+ };
8039
+ this.hashBatches = this.hashBatches.bind(this);
8040
+ }
8041
+ async hash(input, encoding) {
8042
+ return this.hashSync(input, encoding);
8043
+ }
8044
+ hashSync(input, encoding) {
8045
+ const hash = new CRC32();
8046
+ hash.update(input);
8047
+ const digest = hash.finalize();
8048
+ return encodeNumber(digest, encoding);
8049
+ }
8050
+ async *hashBatches(asyncIterator, encoding = "base64") {
8051
+ const hash = new CRC32();
8052
+ for await (const chunk of asyncIterator) {
8053
+ hash.update(chunk);
8054
+ yield chunk;
8055
+ }
8056
+ const digest = hash.finalize();
8057
+ this.options.crypto?.onEnd?.({
8058
+ hash: encodeNumber(digest, encoding)
8059
+ });
8060
+ }
8061
+ };
7856
8062
 
7857
8063
  // ../crypto/src/lib/algorithms/md5-wasm.ts
7858
8064
  var atb = typeof atob === "function" ? atob : typeof Buffer === "function" ? nodeATOB : identity;
@@ -8277,6 +8483,45 @@ var __exports__ = (() => {
8277
8483
  }
8278
8484
  };
8279
8485
 
8486
+ // src/parse-zip/zip-compozition.ts
8487
+ async function cutTheTailOff(provider) {
8488
+ const oldEoCDinfo = await parseEoCDRecord(provider);
8489
+ const oldCDStartOffset = oldEoCDinfo.cdStartOffset;
8490
+ const oldCDLength = Number(oldEoCDinfo.offsets.zip64EoCDOffset ? oldEoCDinfo.offsets.zip64EoCDOffset - oldCDStartOffset : oldEoCDinfo.offsets.zipEoCDOffset - oldCDStartOffset);
8491
+ const zipEnding = await provider.slice(oldCDStartOffset, provider.length);
8492
+ await provider.truncate(Number(oldCDStartOffset));
8493
+ const oldCDBody = zipEnding.slice(0, oldCDLength);
8494
+ const eocdBody = zipEnding.slice(oldCDLength, zipEnding.byteLength);
8495
+ return [oldCDBody, eocdBody, oldEoCDinfo];
8496
+ }
8497
+ async function generateFileHeaders(fileName, fileToAdd, localFileHeaderOffset) {
8498
+ const newFileCRC322 = parseInt(await new CRC32Hash().hash(fileToAdd, "hex"), 16);
8499
+ const newFileLocalHeader = generateLocalHeader({
8500
+ crc32: newFileCRC322,
8501
+ fileName,
8502
+ length: fileToAdd.byteLength
8503
+ });
8504
+ const newFileCDHeader = generateCDHeader({
8505
+ crc32: newFileCRC322,
8506
+ fileName,
8507
+ offset: localFileHeaderOffset,
8508
+ length: fileToAdd.byteLength
8509
+ });
8510
+ return [new Uint8Array(concatenateArrayBuffers(newFileLocalHeader, fileToAdd)), new Uint8Array(newFileCDHeader)];
8511
+ }
8512
+ async function addOneFile(zipUrl, fileToAdd, fileName) {
8513
+ const provider = new FileHandleFile(zipUrl, true);
8514
+ const [oldCDBody, eocdBody, oldEoCDinfo] = await cutTheTailOff(provider);
8515
+ const newFileOffset = provider.length;
8516
+ const [localPart, cdHeaderPart] = await generateFileHeaders(fileName, fileToAdd, newFileOffset);
8517
+ await provider.append(localPart);
8518
+ const newCDBody = concatenateArrayBuffers(oldCDBody, cdHeaderPart);
8519
+ const newCDStartOffset = provider.length;
8520
+ await provider.append(new Uint8Array(newCDBody));
8521
+ const eocdOffset = provider.length;
8522
+ await provider.append(await updateEoCD(eocdBody, oldEoCDinfo.offsets, newCDStartOffset, eocdOffset, oldEoCDinfo.cdRecordsNumber + 1n));
8523
+ }
8524
+
8280
8525
  // src/hash-file-utility.ts
8281
8526
  function parseHashTable(arrayBuffer) {
8282
8527
  const dataView = new DataView(arrayBuffer);
@@ -8304,6 +8549,23 @@ var __exports__ = (() => {
8304
8549
  }
8305
8550
  return hashTable;
8306
8551
  }
8552
+ async function composeHashFile(fileProvider) {
8553
+ const hashArray = await makeHashTableFromZipHeaders(fileProvider);
8554
+ const bufferArray = Object.entries(hashArray).map(([key, value]) => concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value))).sort(compareHashes);
8555
+ return concatenateArrayBuffersFromArray(bufferArray);
8556
+ }
8557
+ function compareHashes(arrA, arrB) {
8558
+ const a = new BigUint64Array(arrA);
8559
+ const b = new BigUint64Array(arrB);
8560
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
8561
+ }
8562
+ function hexStringToBuffer(str) {
8563
+ const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));
8564
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
8565
+ }
8566
+ function bigintToBuffer(n) {
8567
+ return new BigUint64Array([n]).buffer;
8568
+ }
8307
8569
 
8308
8570
  // ../compression/src/lib/compression.ts
8309
8571
  var Compression = class {
@@ -1 +1 @@
1
- {"version":3,"file":"zip-filesystem.d.ts","sourceRoot":"","sources":["../../src/filesystems/zip-filesystem.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,UAAU,EAAY,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAC,YAAY,EAAiB,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EAAC,eAAe,EAA0B,MAAM,6BAA6B,CAAC;AAiBrF;;;GAGG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC9C,oCAAoC;IACpC,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;gBACS,IAAI,EAAE,YAAY,GAAG,MAAM;IAcvC,yBAAyB;IACnB,OAAO;IAMb;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAYlC;;;;OAIG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IAKvE;;;;OAIG;IACG,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IA8BhD;;;;OAIG;YACW,eAAe;CAiB9B"}
1
+ {"version":3,"file":"zip-filesystem.d.ts","sourceRoot":"","sources":["../../src/filesystems/zip-filesystem.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,UAAU,EAAY,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAC,YAAY,EAAiB,MAAM,0BAA0B,CAAC;AAEtE,OAAO,EAAC,eAAe,EAA0B,MAAM,6BAA6B,CAAC;AAiBrF;;;GAGG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC9C,oCAAoC;IACpC,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;gBACS,IAAI,EAAE,YAAY,GAAG,MAAM;IAcvC,yBAAyB;IACnB,OAAO;IAMb;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAYlC;;;;OAIG;IACG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC;IAKvE;;;;OAIG;IACG,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IA8BhD;;;;OAIG;YACW,eAAe;CAiB9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"zip-filesystem.js","names":["isBrowser","isFileProvider","FileHandleFile","makeZipCDHeaderIterator","parseZipLocalFileHeader","DeflateCompression","COMPRESSION_METHODS","compressedFile","compression","raw","decompressedData","decompress","ZipFileSystem","constructor","file","fileProvider","fileName","Error","destroy","readdir","fileNames","zipCDIterator","cdHeader","push","stat","filename","cdFileHeader","getCDFileHeader","size","Number","uncompressedSize","fetch","localFileHeader","localHeaderOffset","compressionHandler","compressionMethod","toString","slice","fileDataOffset","compressedSize","uncompressedFile","response","Response","Object","defineProperty","value","result"],"sources":["../../src/filesystems/zip-filesystem.ts"],"sourcesContent":["// loaders.gl, MIT license\n// Copyright (c) vis.gl contributors\n\nimport {FileSystem, isBrowser} from '@loaders.gl/loader-utils';\nimport {FileProvider, isFileProvider} from '@loaders.gl/loader-utils';\nimport {FileHandleFile} from '@loaders.gl/loader-utils';\nimport {ZipCDFileHeader, makeZipCDHeaderIterator} from '../parse-zip/cd-file-header';\nimport {parseZipLocalFileHeader} from '../parse-zip/local-file-header';\nimport {DeflateCompression} from '@loaders.gl/compression';\n\ntype CompressionHandler = (compressedFile: ArrayBuffer) => Promise<ArrayBuffer>;\n/** Handling different compression types in zip */\nconst COMPRESSION_METHODS: {[key: number]: CompressionHandler} = {\n /** No compression */\n 0: async (compressedFile) => compressedFile,\n /** Deflation */\n 8: async (compressedFile) => {\n const compression = new DeflateCompression({raw: true});\n const decompressedData = await compression.decompress(compressedFile);\n return decompressedData;\n }\n};\n\n/**\n * FileSystem adapter for a ZIP file\n * Holds FileProvider object that provides random access to archived files\n */\nexport class ZipFileSystem implements FileSystem {\n /** FileProvider instance promise */\n protected fileProvider: FileProvider | null = null;\n public fileName?: string;\n\n /**\n * Constructor\n * @param file - instance of FileProvider or file path string\n */\n constructor(file: FileProvider | string) {\n // Try to open file in NodeJS\n if (typeof file === 'string') {\n this.fileName = file;\n if (!isBrowser) {\n this.fileProvider = new FileHandleFile(file);\n } else {\n throw new Error('Cannot open file for random access in a WEB browser');\n }\n } else if (isFileProvider(file)) {\n this.fileProvider = file;\n }\n }\n\n /** Clean up resources */\n async destroy() {\n if (this.fileProvider) {\n await this.fileProvider.destroy();\n }\n }\n\n /**\n * Get file names list from zip archive\n * @returns array of file names\n */\n async readdir(): Promise<string[]> {\n if (!this.fileProvider) {\n throw new Error('No data detected in the zip archive');\n }\n const fileNames: string[] = [];\n const zipCDIterator = makeZipCDHeaderIterator(this.fileProvider);\n for await (const cdHeader of zipCDIterator) {\n fileNames.push(cdHeader.fileName);\n }\n return fileNames;\n }\n\n /**\n * Get file metadata\n * @param filename - name of a file\n * @returns central directory data\n */\n async stat(filename: string): Promise<ZipCDFileHeader & {size: number}> {\n const cdFileHeader = await this.getCDFileHeader(filename);\n return {...cdFileHeader, size: Number(cdFileHeader.uncompressedSize)};\n }\n\n /**\n * Implementation of fetch against this file system\n * @param filename - name of a file\n * @returns - Response with file data\n */\n async fetch(filename: string): Promise<Response> {\n if (!this.fileProvider) {\n throw new Error('No data detected in the zip archive');\n }\n const cdFileHeader = await this.getCDFileHeader(filename);\n const localFileHeader = await parseZipLocalFileHeader(\n cdFileHeader.localHeaderOffset,\n this.fileProvider\n );\n if (!localFileHeader) {\n throw new Error('Local file header has not been found in the zip archive`');\n }\n\n const compressionHandler = COMPRESSION_METHODS[localFileHeader.compressionMethod.toString()];\n if (!compressionHandler) {\n throw Error('Only Deflation compression is supported');\n }\n\n const compressedFile = await this.fileProvider.slice(\n localFileHeader.fileDataOffset,\n localFileHeader.fileDataOffset + localFileHeader.compressedSize\n );\n\n const uncompressedFile = await compressionHandler(compressedFile);\n\n const response = new Response(uncompressedFile);\n Object.defineProperty(response, 'url', {value: `${this.fileName || ''}/${filename}`});\n return response;\n }\n\n /**\n * Get central directory file header\n * @param filename - name of a file\n * @returns central directory file header\n */\n private async getCDFileHeader(filename: string): Promise<ZipCDFileHeader> {\n if (!this.fileProvider) {\n throw new Error('No data detected in the zip archive');\n }\n const zipCDIterator = makeZipCDHeaderIterator(this.fileProvider);\n let result: ZipCDFileHeader | null = null;\n for await (const cdHeader of zipCDIterator) {\n if (cdHeader.fileName === filename) {\n result = cdHeader;\n break;\n }\n }\n if (!result) {\n throw new Error('File has not been found in the zip archive');\n }\n return result;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"zip-filesystem.js","names":["isBrowser","isFileProvider","FileHandleFile","makeZipCDHeaderIterator","parseZipLocalFileHeader","DeflateCompression","COMPRESSION_METHODS","compressedFile","compression","raw","decompressedData","decompress","ZipFileSystem","constructor","file","fileProvider","fileName","Error","destroy","readdir","fileNames","zipCDIterator","cdHeader","push","stat","filename","cdFileHeader","getCDFileHeader","size","Number","uncompressedSize","fetch","localFileHeader","localHeaderOffset","compressionHandler","compressionMethod","toString","slice","fileDataOffset","compressedSize","uncompressedFile","response","Response","Object","defineProperty","value","result"],"sources":["../../src/filesystems/zip-filesystem.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {FileSystem, isBrowser} from '@loaders.gl/loader-utils';\nimport {FileProvider, isFileProvider} from '@loaders.gl/loader-utils';\nimport {FileHandleFile} from '@loaders.gl/loader-utils';\nimport {ZipCDFileHeader, makeZipCDHeaderIterator} from '../parse-zip/cd-file-header';\nimport {parseZipLocalFileHeader} from '../parse-zip/local-file-header';\nimport {DeflateCompression} from '@loaders.gl/compression';\n\ntype CompressionHandler = (compressedFile: ArrayBuffer) => Promise<ArrayBuffer>;\n/** Handling different compression types in zip */\nconst COMPRESSION_METHODS: {[key: number]: CompressionHandler} = {\n /** No compression */\n 0: async (compressedFile) => compressedFile,\n /** Deflation */\n 8: async (compressedFile) => {\n const compression = new DeflateCompression({raw: true});\n const decompressedData = await compression.decompress(compressedFile);\n return decompressedData;\n }\n};\n\n/**\n * FileSystem adapter for a ZIP file\n * Holds FileProvider object that provides random access to archived files\n */\nexport class ZipFileSystem implements FileSystem {\n /** FileProvider instance promise */\n protected fileProvider: FileProvider | null = null;\n public fileName?: string;\n\n /**\n * Constructor\n * @param file - instance of FileProvider or file path string\n */\n constructor(file: FileProvider | string) {\n // Try to open file in NodeJS\n if (typeof file === 'string') {\n this.fileName = file;\n if (!isBrowser) {\n this.fileProvider = new FileHandleFile(file);\n } else {\n throw new Error('Cannot open file for random access in a WEB browser');\n }\n } else if (isFileProvider(file)) {\n this.fileProvider = file;\n }\n }\n\n /** Clean up resources */\n async destroy() {\n if (this.fileProvider) {\n await this.fileProvider.destroy();\n }\n }\n\n /**\n * Get file names list from zip archive\n * @returns array of file names\n */\n async readdir(): Promise<string[]> {\n if (!this.fileProvider) {\n throw new Error('No data detected in the zip archive');\n }\n const fileNames: string[] = [];\n const zipCDIterator = makeZipCDHeaderIterator(this.fileProvider);\n for await (const cdHeader of zipCDIterator) {\n fileNames.push(cdHeader.fileName);\n }\n return fileNames;\n }\n\n /**\n * Get file metadata\n * @param filename - name of a file\n * @returns central directory data\n */\n async stat(filename: string): Promise<ZipCDFileHeader & {size: number}> {\n const cdFileHeader = await this.getCDFileHeader(filename);\n return {...cdFileHeader, size: Number(cdFileHeader.uncompressedSize)};\n }\n\n /**\n * Implementation of fetch against this file system\n * @param filename - name of a file\n * @returns - Response with file data\n */\n async fetch(filename: string): Promise<Response> {\n if (!this.fileProvider) {\n throw new Error('No data detected in the zip archive');\n }\n const cdFileHeader = await this.getCDFileHeader(filename);\n const localFileHeader = await parseZipLocalFileHeader(\n cdFileHeader.localHeaderOffset,\n this.fileProvider\n );\n if (!localFileHeader) {\n throw new Error('Local file header has not been found in the zip archive`');\n }\n\n const compressionHandler = COMPRESSION_METHODS[localFileHeader.compressionMethod.toString()];\n if (!compressionHandler) {\n throw Error('Only Deflation compression is supported');\n }\n\n const compressedFile = await this.fileProvider.slice(\n localFileHeader.fileDataOffset,\n localFileHeader.fileDataOffset + localFileHeader.compressedSize\n );\n\n const uncompressedFile = await compressionHandler(compressedFile);\n\n const response = new Response(uncompressedFile);\n Object.defineProperty(response, 'url', {value: `${this.fileName || ''}/${filename}`});\n return response;\n }\n\n /**\n * Get central directory file header\n * @param filename - name of a file\n * @returns central directory file header\n */\n private async getCDFileHeader(filename: string): Promise<ZipCDFileHeader> {\n if (!this.fileProvider) {\n throw new Error('No data detected in the zip archive');\n }\n const zipCDIterator = makeZipCDHeaderIterator(this.fileProvider);\n let result: ZipCDFileHeader | null = null;\n for await (const cdHeader of zipCDIterator) {\n if (cdHeader.fileName === filename) {\n result = cdHeader;\n break;\n }\n }\n if (!result) {\n throw new Error('File has not been found in the zip archive');\n }\n return result;\n }\n}\n"],"mappings":"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"}
@@ -11,4 +11,10 @@ export declare function parseHashTable(arrayBuffer: ArrayBuffer): Record<string,
11
11
  * @returns ready to use hash info
12
12
  */
13
13
  export declare function makeHashTableFromZipHeaders(fileProvider: FileProvider): Promise<Record<string, bigint>>;
14
+ /**
15
+ * creates hash file that later can be added to the SLPK archive
16
+ * @param fileProvider SLPK archive where we need to add hash file
17
+ * @returns ArrayBuffer containing hash file
18
+ */
19
+ export declare function composeHashFile(fileProvider: FileProvider): Promise<ArrayBuffer>;
14
20
  //# sourceMappingURL=hash-file-utility.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash-file-utility.d.ts","sourceRoot":"","sources":["../src/hash-file-utility.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAGtD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY/E;AASD;;;;GAIG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAejC"}
1
+ {"version":3,"file":"hash-file-utility.d.ts","sourceRoot":"","sources":["../src/hash-file-utility.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,YAAY,EAGb,MAAM,0BAA0B,CAAC;AAGlC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY/E;AASD;;;;GAIG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAejC;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAMtF"}
@@ -1,4 +1,5 @@
1
1
  import { MD5Hash } from '@loaders.gl/crypto';
2
+ import { concatenateArrayBuffers, concatenateArrayBuffersFromArray } from '@loaders.gl/loader-utils';
2
3
  import { makeZipCDHeaderIterator } from "./parse-zip/cd-file-header.js";
3
4
  export function parseHashTable(arrayBuffer) {
4
5
  const dataView = new DataView(arrayBuffer);
@@ -26,4 +27,25 @@ export async function makeHashTableFromZipHeaders(fileProvider) {
26
27
  }
27
28
  return hashTable;
28
29
  }
30
+ export async function composeHashFile(fileProvider) {
31
+ const hashArray = await makeHashTableFromZipHeaders(fileProvider);
32
+ const bufferArray = Object.entries(hashArray).map(_ref => {
33
+ let [key, value] = _ref;
34
+ return concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value));
35
+ }).sort(compareHashes);
36
+ return concatenateArrayBuffersFromArray(bufferArray);
37
+ }
38
+ function compareHashes(arrA, arrB) {
39
+ const a = new BigUint64Array(arrA);
40
+ const b = new BigUint64Array(arrB);
41
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
42
+ }
43
+ function hexStringToBuffer(str) {
44
+ var _str$match;
45
+ const byteArray = (_str$match = str.match(/../g)) === null || _str$match === void 0 ? void 0 : _str$match.map(h => parseInt(h, 16));
46
+ return new Uint8Array(byteArray !== null && byteArray !== void 0 ? byteArray : new Array(16)).buffer;
47
+ }
48
+ function bigintToBuffer(n) {
49
+ return new BigUint64Array([n]).buffer;
50
+ }
29
51
  //# sourceMappingURL=hash-file-utility.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash-file-utility.js","names":["MD5Hash","makeZipCDHeaderIterator","parseHashTable","arrayBuffer","dataView","DataView","hashMap","i","byteLength","offset","getBigUint64","hash","bufferToHex","buffer","start","length","Uint8Array","map","x","toString","padStart","join","makeHashTableFromZipHeaders","fileProvider","zipCDIterator","md5Hash","textEncoder","TextEncoder","hashTable","cdHeader","filename","fileName","split","toLocaleLowerCase","encode","md5","localHeaderOffset"],"sources":["../src/hash-file-utility.ts"],"sourcesContent":["// loaders.gl, MIT license\n// Copyright (c) vis.gl contributors\n\nimport {MD5Hash} from '@loaders.gl/crypto';\nimport {FileProvider} from '@loaders.gl/loader-utils';\nimport {makeZipCDHeaderIterator} from './parse-zip/cd-file-header';\n\n/**\n * Reads hash file from buffer and returns it in ready-to-use form\n * @param arrayBuffer - buffer containing hash file\n * @returns Map containing hash and offset\n */\nexport function parseHashTable(arrayBuffer: ArrayBuffer): Record<string, bigint> {\n const dataView = new DataView(arrayBuffer);\n\n const hashMap: Record<string, bigint> = {};\n\n for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {\n const offset = dataView.getBigUint64(i + 16, true);\n const hash = bufferToHex(arrayBuffer, i, 16);\n hashMap[hash] = offset;\n }\n\n return hashMap;\n}\n\nfunction bufferToHex(buffer: ArrayBuffer, start: number, length: number): string {\n // buffer is an ArrayBuffer\n return [...new Uint8Array(buffer, start, length)]\n .map((x) => x.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * generates hash info from zip files \"central directory\"\n * @param fileProvider - provider of the archive\n * @returns ready to use hash info\n */\nexport async function makeHashTableFromZipHeaders(\n fileProvider: FileProvider\n): Promise<Record<string, bigint>> {\n const zipCDIterator = makeZipCDHeaderIterator(fileProvider);\n const md5Hash = new MD5Hash();\n const textEncoder = new TextEncoder();\n\n const hashTable: Record<string, bigint> = {};\n\n for await (const cdHeader of zipCDIterator) {\n const filename = cdHeader.fileName.split('\\\\').join('/').toLocaleLowerCase();\n const arrayBuffer = textEncoder.encode(filename).buffer;\n const md5 = await md5Hash.hash(arrayBuffer, 'hex');\n hashTable[md5] = cdHeader.localHeaderOffset;\n }\n\n return hashTable;\n}\n"],"mappings":"AAGA,SAAQA,OAAO,QAAO,oBAAoB;AAAC,SAEnCC,uBAAuB;AAO/B,OAAO,SAASC,cAAcA,CAACC,WAAwB,EAA0B;EAC/E,MAAMC,QAAQ,GAAG,IAAIC,QAAQ,CAACF,WAAW,CAAC;EAE1C,MAAMG,OAA+B,GAAG,CAAC,CAAC;EAE1C,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGJ,WAAW,CAACK,UAAU,EAAED,CAAC,GAAGA,CAAC,GAAG,EAAE,EAAE;IACtD,MAAME,MAAM,GAAGL,QAAQ,CAACM,YAAY,CAACH,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC;IAClD,MAAMI,IAAI,GAAGC,WAAW,CAACT,WAAW,EAAEI,CAAC,EAAE,EAAE,CAAC;IAC5CD,OAAO,CAACK,IAAI,CAAC,GAAGF,MAAM;EACxB;EAEA,OAAOH,OAAO;AAChB;AAEA,SAASM,WAAWA,CAACC,MAAmB,EAAEC,KAAa,EAAEC,MAAc,EAAU;EAE/E,OAAO,CAAC,GAAG,IAAIC,UAAU,CAACH,MAAM,EAAEC,KAAK,EAAEC,MAAM,CAAC,CAAC,CAC9CE,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAC3CC,IAAI,CAAC,EAAE,CAAC;AACb;AAOA,OAAO,eAAeC,2BAA2BA,CAC/CC,YAA0B,EACO;EACjC,MAAMC,aAAa,GAAGvB,uBAAuB,CAACsB,YAAY,CAAC;EAC3D,MAAME,OAAO,GAAG,IAAIzB,OAAO,CAAC,CAAC;EAC7B,MAAM0B,WAAW,GAAG,IAAIC,WAAW,CAAC,CAAC;EAErC,MAAMC,SAAiC,GAAG,CAAC,CAAC;EAE5C,WAAW,MAAMC,QAAQ,IAAIL,aAAa,EAAE;IAC1C,MAAMM,QAAQ,GAAGD,QAAQ,CAACE,QAAQ,CAACC,KAAK,CAAC,IAAI,CAAC,CAACX,IAAI,CAAC,GAAG,CAAC,CAACY,iBAAiB,CAAC,CAAC;IAC5E,MAAM9B,WAAW,GAAGuB,WAAW,CAACQ,MAAM,CAACJ,QAAQ,CAAC,CAACjB,MAAM;IACvD,MAAMsB,GAAG,GAAG,MAAMV,OAAO,CAACd,IAAI,CAACR,WAAW,EAAE,KAAK,CAAC;IAClDyB,SAAS,CAACO,GAAG,CAAC,GAAGN,QAAQ,CAACO,iBAAiB;EAC7C;EAEA,OAAOR,SAAS;AAClB"}
1
+ {"version":3,"file":"hash-file-utility.js","names":["MD5Hash","concatenateArrayBuffers","concatenateArrayBuffersFromArray","makeZipCDHeaderIterator","parseHashTable","arrayBuffer","dataView","DataView","hashMap","i","byteLength","offset","getBigUint64","hash","bufferToHex","buffer","start","length","Uint8Array","map","x","toString","padStart","join","makeHashTableFromZipHeaders","fileProvider","zipCDIterator","md5Hash","textEncoder","TextEncoder","hashTable","cdHeader","filename","fileName","split","toLocaleLowerCase","encode","md5","localHeaderOffset","composeHashFile","hashArray","bufferArray","Object","entries","_ref","key","value","hexStringToBuffer","bigintToBuffer","sort","compareHashes","arrA","arrB","a","BigUint64Array","b","Number","str","_str$match","byteArray","match","h","parseInt","Array","n"],"sources":["../src/hash-file-utility.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {MD5Hash} from '@loaders.gl/crypto';\nimport {\n FileProvider,\n concatenateArrayBuffers,\n concatenateArrayBuffersFromArray\n} from '@loaders.gl/loader-utils';\nimport {makeZipCDHeaderIterator} from './parse-zip/cd-file-header';\n\n/**\n * Reads hash file from buffer and returns it in ready-to-use form\n * @param arrayBuffer - buffer containing hash file\n * @returns Map containing hash and offset\n */\nexport function parseHashTable(arrayBuffer: ArrayBuffer): Record<string, bigint> {\n const dataView = new DataView(arrayBuffer);\n\n const hashMap: Record<string, bigint> = {};\n\n for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {\n const offset = dataView.getBigUint64(i + 16, true);\n const hash = bufferToHex(arrayBuffer, i, 16);\n hashMap[hash] = offset;\n }\n\n return hashMap;\n}\n\nfunction bufferToHex(buffer: ArrayBuffer, start: number, length: number): string {\n // buffer is an ArrayBuffer\n return [...new Uint8Array(buffer, start, length)]\n .map((x) => x.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * generates hash info from zip files \"central directory\"\n * @param fileProvider - provider of the archive\n * @returns ready to use hash info\n */\nexport async function makeHashTableFromZipHeaders(\n fileProvider: FileProvider\n): Promise<Record<string, bigint>> {\n const zipCDIterator = makeZipCDHeaderIterator(fileProvider);\n const md5Hash = new MD5Hash();\n const textEncoder = new TextEncoder();\n\n const hashTable: Record<string, bigint> = {};\n\n for await (const cdHeader of zipCDIterator) {\n const filename = cdHeader.fileName.split('\\\\').join('/').toLocaleLowerCase();\n const arrayBuffer = textEncoder.encode(filename).buffer;\n const md5 = await md5Hash.hash(arrayBuffer, 'hex');\n hashTable[md5] = cdHeader.localHeaderOffset;\n }\n\n return hashTable;\n}\n\n/**\n * creates hash file that later can be added to the SLPK archive\n * @param fileProvider SLPK archive where we need to add hash file\n * @returns ArrayBuffer containing hash file\n */\nexport async function composeHashFile(fileProvider: FileProvider): Promise<ArrayBuffer> {\n const hashArray = await makeHashTableFromZipHeaders(fileProvider);\n const bufferArray = Object.entries(hashArray)\n .map(([key, value]) => concatenateArrayBuffers(hexStringToBuffer(key), bigintToBuffer(value)))\n .sort(compareHashes);\n return concatenateArrayBuffersFromArray(bufferArray);\n}\n\n/**\n * Function to compare md5 hashes according to https://github.com/Esri/i3s-spec/blob/master/docs/2.0/slpk_hashtable.pcsl.md\n * @param arrA first hash to compare\n * @param arrB second hash to compare\n * @returns 0 if equal, negative number if a<b, pozitive if a>b\n */\nfunction compareHashes(arrA: ArrayBuffer, arrB: ArrayBuffer): number {\n const a = new BigUint64Array(arrA);\n const b = new BigUint64Array(arrB);\n\n return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);\n}\n\n/**\n * converts hex string to buffer\n * @param str hex string to convert\n * @returns conversion result\n */\nfunction hexStringToBuffer(str: string): ArrayBuffer {\n const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));\n return new Uint8Array(byteArray ?? new Array(16)).buffer;\n}\n\n/**\n * converts bigint to buffer\n * @param n bigint to convert\n * @returns convertion result\n */\nfunction bigintToBuffer(n: bigint): ArrayBuffer {\n return new BigUint64Array([n]).buffer;\n}\n"],"mappings":"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"}