@loaders.gl/zip 4.2.0-alpha.1 → 4.2.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dist.dev.js CHANGED
@@ -6952,7 +6952,9 @@ var __exports__ = (() => {
6952
6952
  var src_exports = {};
6953
6953
  __export(src_exports, {
6954
6954
  CD_HEADER_SIGNATURE: () => signature2,
6955
+ IndexedArchive: () => IndexedArchive,
6955
6956
  TarBuilder: () => TarBuilder,
6957
+ ZIP_COMPRESSION_HANDLERS: () => ZIP_COMPRESSION_HANDLERS,
6956
6958
  ZipFileSystem: () => ZipFileSystem,
6957
6959
  ZipLoader: () => ZipLoader,
6958
6960
  ZipWriter: () => ZipWriter,
@@ -6973,7 +6975,7 @@ var __exports__ = (() => {
6973
6975
 
6974
6976
  // src/zip-loader.ts
6975
6977
  var import_jszip = __toESM(require_jszip_min(), 1);
6976
- var VERSION = true ? "4.2.0-alpha.1" : "latest";
6978
+ var VERSION = true ? "4.2.0-alpha.2" : "latest";
6977
6979
  var ZipLoader = {
6978
6980
  id: "zip",
6979
6981
  module: "zip",
@@ -7018,7 +7020,7 @@ var __exports__ = (() => {
7018
7020
 
7019
7021
  // src/zip-writer.ts
7020
7022
  var import_jszip2 = __toESM(require_jszip_min(), 1);
7021
- var VERSION2 = true ? "4.2.0-alpha.1" : "latest";
7023
+ var VERSION2 = true ? "4.2.0-alpha.2" : "latest";
7022
7024
  var ZipWriter = {
7023
7025
  name: "Zip Archive",
7024
7026
  id: "zip",
@@ -9059,62 +9061,6 @@ var __exports__ = (() => {
9059
9061
  return path_exports.join(...resPaths);
9060
9062
  }
9061
9063
 
9062
- // src/hash-file-utility.ts
9063
- function parseHashTable(arrayBuffer) {
9064
- const dataView = new DataView(arrayBuffer);
9065
- const hashMap = {};
9066
- for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {
9067
- const offset = dataView.getBigUint64(i + 16, true);
9068
- const hash = bufferToHex(arrayBuffer, i, 16);
9069
- hashMap[hash] = offset;
9070
- }
9071
- return hashMap;
9072
- }
9073
- function bufferToHex(buffer, start, length) {
9074
- return [...new Uint8Array(buffer, start, length)].map((x) => x.toString(16).padStart(2, "0")).join("");
9075
- }
9076
- async function makeHashTableFromZipHeaders(fileProvider) {
9077
- const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
9078
- return getHashTable(zipCDIterator);
9079
- }
9080
- async function getHashTable(zipCDIterator) {
9081
- const md5Hash = new MD5Hash();
9082
- const textEncoder = new TextEncoder();
9083
- const hashTable = {};
9084
- for await (const cdHeader of zipCDIterator) {
9085
- const filename2 = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
9086
- const arrayBuffer = textEncoder.encode(filename2).buffer;
9087
- const md5 = await md5Hash.hash(arrayBuffer, "hex");
9088
- hashTable[md5] = cdHeader.localHeaderOffset;
9089
- }
9090
- return hashTable;
9091
- }
9092
- async function composeHashFile(zipCDIterator) {
9093
- const md5Hash = new MD5Hash();
9094
- const textEncoder = new TextEncoder();
9095
- const hashArray = [];
9096
- for await (const cdHeader of zipCDIterator) {
9097
- const filename2 = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
9098
- const arrayBuffer = textEncoder.encode(filename2).buffer;
9099
- const md5 = await md5Hash.hash(arrayBuffer, "hex");
9100
- hashArray.push(concatenateArrayBuffers(hexStringToBuffer(md5), bigintToBuffer(cdHeader.localHeaderOffset)));
9101
- }
9102
- const bufferArray = hashArray.sort(compareHashes);
9103
- return concatenateArrayBuffersFromArray(bufferArray);
9104
- }
9105
- function compareHashes(arrA, arrB) {
9106
- const a = new BigUint64Array(arrA);
9107
- const b = new BigUint64Array(arrB);
9108
- return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
9109
- }
9110
- function hexStringToBuffer(str) {
9111
- const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));
9112
- return new Uint8Array(byteArray ?? new Array(16)).buffer;
9113
- }
9114
- function bigintToBuffer(n) {
9115
- return new BigUint64Array([n]).buffer;
9116
- }
9117
-
9118
9064
  // ../compression/src/lib/compression.ts
9119
9065
  var Compression = class {
9120
9066
  constructor(options) {
@@ -9263,7 +9209,7 @@ var __exports__ = (() => {
9263
9209
  };
9264
9210
 
9265
9211
  // src/filesystems/zip-filesystem.ts
9266
- var COMPRESSION_METHODS = {
9212
+ var ZIP_COMPRESSION_HANDLERS = {
9267
9213
  0: async (compressedFile) => compressedFile,
9268
9214
  8: async (compressedFile) => {
9269
9215
  const compression = new DeflateCompression({
@@ -9275,6 +9221,7 @@ var __exports__ = (() => {
9275
9221
  };
9276
9222
  var ZipFileSystem = class {
9277
9223
  fileProvider = null;
9224
+ archive = null;
9278
9225
  constructor(file) {
9279
9226
  if (typeof file === "string") {
9280
9227
  this.fileName = file;
@@ -9283,6 +9230,10 @@ var __exports__ = (() => {
9283
9230
  } else {
9284
9231
  throw new Error("Cannot open file for random access in a WEB browser");
9285
9232
  }
9233
+ } else if (file instanceof IndexedArchive) {
9234
+ this.fileProvider = file.fileProvider;
9235
+ this.archive = file;
9236
+ this.fileName = file.fileName;
9286
9237
  } else if (isFileProvider(file)) {
9287
9238
  this.fileProvider = file;
9288
9239
  }
@@ -9311,23 +9262,28 @@ var __exports__ = (() => {
9311
9262
  };
9312
9263
  }
9313
9264
  async fetch(filename2) {
9314
- if (!this.fileProvider) {
9315
- throw new Error("No data detected in the zip archive");
9316
- }
9317
- const cdFileHeader = await this.getCDFileHeader(filename2);
9318
- const localFileHeader = await parseZipLocalFileHeader(cdFileHeader.localHeaderOffset, this.fileProvider);
9319
- if (!localFileHeader) {
9320
- throw new Error("Local file header has not been found in the zip archive`");
9321
- }
9322
- const compressionHandler = COMPRESSION_METHODS[localFileHeader.compressionMethod.toString()];
9323
- if (!compressionHandler) {
9324
- throw Error("Only Deflation compression is supported");
9265
+ let uncompressedFile;
9266
+ if (this.archive) {
9267
+ uncompressedFile = await this.archive.getFile(filename2, "http");
9268
+ } else {
9269
+ if (!this.fileProvider) {
9270
+ throw new Error("No data detected in the zip archive");
9271
+ }
9272
+ const cdFileHeader = await this.getCDFileHeader(filename2);
9273
+ const localFileHeader = await parseZipLocalFileHeader(cdFileHeader.localHeaderOffset, this.fileProvider);
9274
+ if (!localFileHeader) {
9275
+ throw new Error("Local file header has not been found in the zip archive`");
9276
+ }
9277
+ const compressionHandler = ZIP_COMPRESSION_HANDLERS[localFileHeader.compressionMethod.toString()];
9278
+ if (!compressionHandler) {
9279
+ throw Error("Only Deflation compression is supported");
9280
+ }
9281
+ const compressedFile = await this.fileProvider.slice(localFileHeader.fileDataOffset, localFileHeader.fileDataOffset + localFileHeader.compressedSize);
9282
+ uncompressedFile = await compressionHandler(compressedFile);
9325
9283
  }
9326
- const compressedFile = await this.fileProvider.slice(localFileHeader.fileDataOffset, localFileHeader.fileDataOffset + localFileHeader.compressedSize);
9327
- const uncompressedFile = await compressionHandler(compressedFile);
9328
9284
  const response = new Response(uncompressedFile);
9329
9285
  Object.defineProperty(response, "url", {
9330
- value: `${this.fileName || ""}/${filename2}`
9286
+ value: filename2 ? `${this.fileName || ""}/${filename2}` : this.fileName || ""
9331
9287
  });
9332
9288
  return response;
9333
9289
  }
@@ -9349,6 +9305,75 @@ var __exports__ = (() => {
9349
9305
  return result;
9350
9306
  }
9351
9307
  };
9308
+
9309
+ // src/filesystems/IndexedArchive.ts
9310
+ var IndexedArchive = class {
9311
+ constructor(fileProvider, hashTable, fileName) {
9312
+ this.fileProvider = fileProvider;
9313
+ this.fileName = fileName;
9314
+ }
9315
+ async getFileWithoutHash(filename2) {
9316
+ const zipFS = new ZipFileSystem(this.fileProvider);
9317
+ const response = await zipFS.fetch(filename2);
9318
+ return await response.arrayBuffer();
9319
+ }
9320
+ };
9321
+
9322
+ // src/hash-file-utility.ts
9323
+ function parseHashTable(arrayBuffer) {
9324
+ const dataView = new DataView(arrayBuffer);
9325
+ const hashMap = {};
9326
+ for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {
9327
+ const offset = dataView.getBigUint64(i + 16, true);
9328
+ const hash = bufferToHex(arrayBuffer, i, 16);
9329
+ hashMap[hash] = offset;
9330
+ }
9331
+ return hashMap;
9332
+ }
9333
+ function bufferToHex(buffer, start, length) {
9334
+ return [...new Uint8Array(buffer, start, length)].map((x) => x.toString(16).padStart(2, "0")).join("");
9335
+ }
9336
+ async function makeHashTableFromZipHeaders(fileProvider) {
9337
+ const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
9338
+ return getHashTable(zipCDIterator);
9339
+ }
9340
+ async function getHashTable(zipCDIterator) {
9341
+ const md5Hash = new MD5Hash();
9342
+ const textEncoder = new TextEncoder();
9343
+ const hashTable = {};
9344
+ for await (const cdHeader of zipCDIterator) {
9345
+ const filename2 = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
9346
+ const arrayBuffer = textEncoder.encode(filename2).buffer;
9347
+ const md5 = await md5Hash.hash(arrayBuffer, "hex");
9348
+ hashTable[md5] = cdHeader.localHeaderOffset;
9349
+ }
9350
+ return hashTable;
9351
+ }
9352
+ async function composeHashFile(zipCDIterator) {
9353
+ const md5Hash = new MD5Hash();
9354
+ const textEncoder = new TextEncoder();
9355
+ const hashArray = [];
9356
+ for await (const cdHeader of zipCDIterator) {
9357
+ const filename2 = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
9358
+ const arrayBuffer = textEncoder.encode(filename2).buffer;
9359
+ const md5 = await md5Hash.hash(arrayBuffer, "hex");
9360
+ hashArray.push(concatenateArrayBuffers(hexStringToBuffer(md5), bigintToBuffer(cdHeader.localHeaderOffset)));
9361
+ }
9362
+ const bufferArray = hashArray.sort(compareHashes);
9363
+ return concatenateArrayBuffersFromArray(bufferArray);
9364
+ }
9365
+ function compareHashes(arrA, arrB) {
9366
+ const a = new BigUint64Array(arrA);
9367
+ const b = new BigUint64Array(arrB);
9368
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
9369
+ }
9370
+ function hexStringToBuffer(str) {
9371
+ const byteArray = str.match(/../g)?.map((h) => parseInt(h, 16));
9372
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
9373
+ }
9374
+ function bigintToBuffer(n) {
9375
+ return new BigUint64Array([n]).buffer;
9376
+ }
9352
9377
  return __toCommonJS(src_exports);
9353
9378
  })();
9354
9379
  /*! Bundled license information:
@@ -0,0 +1,29 @@
1
+ import { FileProvider } from '@loaders.gl/loader-utils';
2
+ /**
3
+ * Abstract class for fetching indexed archive formats (SLPK, 3TZ). Those types of zip archive has
4
+ * a hash file inside that allows to increase reading speed
5
+ */
6
+ export declare abstract class IndexedArchive {
7
+ fileProvider: FileProvider;
8
+ fileName?: string;
9
+ /**
10
+ * Constructor
11
+ * @param fileProvider - instance of a binary data reader
12
+ * @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
13
+ * @param fileName - name of the archive. It is used to add to an URL of a loader context
14
+ */
15
+ constructor(fileProvider: FileProvider, hashTable?: Record<string, bigint>, fileName?: string);
16
+ /**
17
+ * Get internal file from the archive
18
+ * @param path - path to the file
19
+ * @param mode - path mode - the logic is implemented in subclasses
20
+ */
21
+ abstract getFile(path: string, mode?: string): Promise<ArrayBuffer>;
22
+ /**
23
+ * Get file as from order ZIP arhive without using the hash file
24
+ * @param filename - path to the internal file
25
+ * @returns
26
+ */
27
+ protected getFileWithoutHash(filename: string): Promise<ArrayBuffer>;
28
+ }
29
+ //# sourceMappingURL=IndexedArchive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexedArchive.d.ts","sourceRoot":"","sources":["../../src/filesystems/IndexedArchive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAGtD;;;GAGG;AACH,8BAAsB,cAAc;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;gBACS,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM;IAK7F;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAEnE;;;;OAIG;cACa,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAK3E"}
@@ -0,0 +1,15 @@
1
+ import { ZipFileSystem } from "./zip-filesystem.js";
2
+ export class IndexedArchive {
3
+ constructor(fileProvider, hashTable, fileName) {
4
+ this.fileProvider = void 0;
5
+ this.fileName = void 0;
6
+ this.fileProvider = fileProvider;
7
+ this.fileName = fileName;
8
+ }
9
+ async getFileWithoutHash(filename) {
10
+ const zipFS = new ZipFileSystem(this.fileProvider);
11
+ const response = await zipFS.fetch(filename);
12
+ return await response.arrayBuffer();
13
+ }
14
+ }
15
+ //# sourceMappingURL=IndexedArchive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexedArchive.js","names":["ZipFileSystem","IndexedArchive","constructor","fileProvider","hashTable","fileName","getFileWithoutHash","filename","zipFS","response","fetch","arrayBuffer"],"sources":["../../src/filesystems/IndexedArchive.ts"],"sourcesContent":["import {FileProvider} from '@loaders.gl/loader-utils';\nimport {ZipFileSystem} from './zip-filesystem';\n\n/**\n * Abstract class for fetching indexed archive formats (SLPK, 3TZ). Those types of zip archive has\n * a hash file inside that allows to increase reading speed\n */\nexport abstract class IndexedArchive {\n public fileProvider: FileProvider;\n public fileName?: string;\n\n /**\n * Constructor\n * @param fileProvider - instance of a binary data reader\n * @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file\n * @param fileName - name of the archive. It is used to add to an URL of a loader context\n */\n constructor(fileProvider: FileProvider, hashTable?: Record<string, bigint>, fileName?: string) {\n this.fileProvider = fileProvider;\n this.fileName = fileName;\n }\n\n /**\n * Get internal file from the archive\n * @param path - path to the file\n * @param mode - path mode - the logic is implemented in subclasses\n */\n abstract getFile(path: string, mode?: string): Promise<ArrayBuffer>;\n\n /**\n * Get file as from order ZIP arhive without using the hash file\n * @param filename - path to the internal file\n * @returns\n */\n protected async getFileWithoutHash(filename: string): Promise<ArrayBuffer> {\n const zipFS = new ZipFileSystem(this.fileProvider);\n const response = await zipFS.fetch(filename);\n return await response.arrayBuffer();\n }\n}\n"],"mappings":"SACQA,aAAa;AAMrB,OAAO,MAAeC,cAAc,CAAC;EAUnCC,WAAWA,CAACC,YAA0B,EAAEC,SAAkC,EAAEC,QAAiB,EAAE;IAAA,KATxFF,YAAY;IAAA,KACZE,QAAQ;IASb,IAAI,CAACF,YAAY,GAAGA,YAAY;IAChC,IAAI,CAACE,QAAQ,GAAGA,QAAQ;EAC1B;EAcA,MAAgBC,kBAAkBA,CAACC,QAAgB,EAAwB;IACzE,MAAMC,KAAK,GAAG,IAAIR,aAAa,CAAC,IAAI,CAACG,YAAY,CAAC;IAClD,MAAMM,QAAQ,GAAG,MAAMD,KAAK,CAACE,KAAK,CAACH,QAAQ,CAAC;IAC5C,OAAO,MAAME,QAAQ,CAACE,WAAW,CAAC,CAAC;EACrC;AACF"}
@@ -1,6 +1,12 @@
1
1
  import { FileSystem } from '@loaders.gl/loader-utils';
2
2
  import { FileProvider } from '@loaders.gl/loader-utils';
3
3
  import { ZipCDFileHeader } from '../parse-zip/cd-file-header';
4
+ import { IndexedArchive } from './IndexedArchive';
5
+ export type CompressionHandler = (compressedFile: ArrayBuffer) => Promise<ArrayBuffer>;
6
+ /** Handling different compression types in zip */
7
+ export declare const ZIP_COMPRESSION_HANDLERS: {
8
+ [key: number]: CompressionHandler;
9
+ };
4
10
  /**
5
11
  * FileSystem adapter for a ZIP file
6
12
  * Holds FileProvider object that provides random access to archived files
@@ -9,11 +15,12 @@ export declare class ZipFileSystem implements FileSystem {
9
15
  /** FileProvider instance promise */
10
16
  protected fileProvider: FileProvider | null;
11
17
  fileName?: string;
18
+ archive: IndexedArchive | null;
12
19
  /**
13
20
  * Constructor
14
21
  * @param file - instance of FileProvider or file path string
15
22
  */
16
- constructor(file: FileProvider | string);
23
+ constructor(file: FileProvider | IndexedArchive | string);
17
24
  /** Clean up resources */
18
25
  destroy(): Promise<void>;
19
26
  /**
@@ -1 +1 @@
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
+ {"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;AAGrF,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAEhD,MAAM,MAAM,kBAAkB,GAAG,CAAC,cAAc,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AACvF,kDAAkD;AAClD,eAAO,MAAM,wBAAwB,EAAE;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAAA;CASxE,CAAC;AAEF;;;GAGG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC9C,oCAAoC;IACpC,SAAS,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,GAAG,IAAI,CAAQ;IAE7C;;;OAGG;gBACS,IAAI,EAAE,YAAY,GAAG,cAAc,GAAG,MAAM;IAkBxD,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;IAsChD;;;;OAIG;YACW,eAAe;CAiB9B"}
@@ -4,7 +4,8 @@ import { FileHandleFile } from '@loaders.gl/loader-utils';
4
4
  import { makeZipCDHeaderIterator } from "../parse-zip/cd-file-header.js";
5
5
  import { parseZipLocalFileHeader } from "../parse-zip/local-file-header.js";
6
6
  import { DeflateCompression } from '@loaders.gl/compression';
7
- const COMPRESSION_METHODS = {
7
+ import { IndexedArchive } from "./IndexedArchive.js";
8
+ export const ZIP_COMPRESSION_HANDLERS = {
8
9
  0: async compressedFile => compressedFile,
9
10
  8: async compressedFile => {
10
11
  const compression = new DeflateCompression({
@@ -18,6 +19,7 @@ export class ZipFileSystem {
18
19
  constructor(file) {
19
20
  this.fileProvider = null;
20
21
  this.fileName = void 0;
22
+ this.archive = null;
21
23
  if (typeof file === 'string') {
22
24
  this.fileName = file;
23
25
  if (!isBrowser) {
@@ -25,6 +27,10 @@ export class ZipFileSystem {
25
27
  } else {
26
28
  throw new Error('Cannot open file for random access in a WEB browser');
27
29
  }
30
+ } else if (file instanceof IndexedArchive) {
31
+ this.fileProvider = file.fileProvider;
32
+ this.archive = file;
33
+ this.fileName = file.fileName;
28
34
  } else if (isFileProvider(file)) {
29
35
  this.fileProvider = file;
30
36
  }
@@ -53,23 +59,28 @@ export class ZipFileSystem {
53
59
  };
54
60
  }
55
61
  async fetch(filename) {
56
- if (!this.fileProvider) {
57
- throw new Error('No data detected in the zip archive');
58
- }
59
- const cdFileHeader = await this.getCDFileHeader(filename);
60
- const localFileHeader = await parseZipLocalFileHeader(cdFileHeader.localHeaderOffset, this.fileProvider);
61
- if (!localFileHeader) {
62
- throw new Error('Local file header has not been found in the zip archive`');
63
- }
64
- const compressionHandler = COMPRESSION_METHODS[localFileHeader.compressionMethod.toString()];
65
- if (!compressionHandler) {
66
- throw Error('Only Deflation compression is supported');
62
+ let uncompressedFile;
63
+ if (this.archive) {
64
+ uncompressedFile = await this.archive.getFile(filename, 'http');
65
+ } else {
66
+ if (!this.fileProvider) {
67
+ throw new Error('No data detected in the zip archive');
68
+ }
69
+ const cdFileHeader = await this.getCDFileHeader(filename);
70
+ const localFileHeader = await parseZipLocalFileHeader(cdFileHeader.localHeaderOffset, this.fileProvider);
71
+ if (!localFileHeader) {
72
+ throw new Error('Local file header has not been found in the zip archive`');
73
+ }
74
+ const compressionHandler = ZIP_COMPRESSION_HANDLERS[localFileHeader.compressionMethod.toString()];
75
+ if (!compressionHandler) {
76
+ throw Error('Only Deflation compression is supported');
77
+ }
78
+ const compressedFile = await this.fileProvider.slice(localFileHeader.fileDataOffset, localFileHeader.fileDataOffset + localFileHeader.compressedSize);
79
+ uncompressedFile = await compressionHandler(compressedFile);
67
80
  }
68
- const compressedFile = await this.fileProvider.slice(localFileHeader.fileDataOffset, localFileHeader.fileDataOffset + localFileHeader.compressedSize);
69
- const uncompressedFile = await compressionHandler(compressedFile);
70
81
  const response = new Response(uncompressedFile);
71
82
  Object.defineProperty(response, 'url', {
72
- value: `${this.fileName || ''}/${filename}`
83
+ value: filename ? `${this.fileName || ''}/${filename}` : this.fileName || ''
73
84
  });
74
85
  return response;
75
86
  }
@@ -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\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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"}
1
+ {"version":3,"file":"zip-filesystem.js","names":["isBrowser","isFileProvider","FileHandleFile","makeZipCDHeaderIterator","parseZipLocalFileHeader","DeflateCompression","IndexedArchive","ZIP_COMPRESSION_HANDLERS","compressedFile","compression","raw","decompressedData","decompress","ZipFileSystem","constructor","file","fileProvider","fileName","archive","Error","destroy","readdir","fileNames","zipCDIterator","cdHeader","push","stat","filename","cdFileHeader","getCDFileHeader","size","Number","uncompressedSize","fetch","uncompressedFile","getFile","localFileHeader","localHeaderOffset","compressionHandler","compressionMethod","toString","slice","fileDataOffset","compressedSize","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';\nimport {IndexedArchive} from './IndexedArchive';\n\nexport type CompressionHandler = (compressedFile: ArrayBuffer) => Promise<ArrayBuffer>;\n/** Handling different compression types in zip */\nexport const ZIP_COMPRESSION_HANDLERS: {[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 public archive: IndexedArchive | null = null;\n\n /**\n * Constructor\n * @param file - instance of FileProvider or file path string\n */\n constructor(file: FileProvider | IndexedArchive | 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 (file instanceof IndexedArchive) {\n this.fileProvider = file.fileProvider;\n this.archive = file;\n this.fileName = file.fileName;\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 let uncompressedFile: ArrayBuffer;\n if (this.archive) {\n uncompressedFile = await this.archive.getFile(filename, 'http');\n } else {\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 =\n ZIP_COMPRESSION_HANDLERS[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 uncompressedFile = await compressionHandler(compressedFile);\n }\n\n const response = new Response(uncompressedFile);\n Object.defineProperty(response, 'url', {\n value: filename ? `${this.fileName || ''}/${filename}` : this.fileName || ''\n });\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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"}
package/dist/index.cjs CHANGED
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  CD_HEADER_SIGNATURE: () => signature2,
34
+ IndexedArchive: () => IndexedArchive,
34
35
  TarBuilder: () => TarBuilder,
36
+ ZIP_COMPRESSION_HANDLERS: () => ZIP_COMPRESSION_HANDLERS,
35
37
  ZipFileSystem: () => ZipFileSystem,
36
38
  ZipLoader: () => ZipLoader,
37
39
  ZipWriter: () => ZipWriter,
@@ -1188,73 +1190,12 @@ function pathJoin(...paths) {
1188
1190
  return import_loader_utils5.path.join(...resPaths);
1189
1191
  }
1190
1192
 
1191
- // src/hash-file-utility.ts
1192
- var import_crypto2 = require("@loaders.gl/crypto");
1193
- var import_loader_utils6 = require("@loaders.gl/loader-utils");
1194
- function parseHashTable(arrayBuffer) {
1195
- const dataView = new DataView(arrayBuffer);
1196
- const hashMap = {};
1197
- for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {
1198
- const offset = dataView.getBigUint64(i + 16, true);
1199
- const hash = bufferToHex(arrayBuffer, i, 16);
1200
- hashMap[hash] = offset;
1201
- }
1202
- return hashMap;
1203
- }
1204
- function bufferToHex(buffer, start, length) {
1205
- return [...new Uint8Array(buffer, start, length)].map((x) => x.toString(16).padStart(2, "0")).join("");
1206
- }
1207
- async function makeHashTableFromZipHeaders(fileProvider) {
1208
- const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
1209
- return getHashTable(zipCDIterator);
1210
- }
1211
- async function getHashTable(zipCDIterator) {
1212
- const md5Hash = new import_crypto2.MD5Hash();
1213
- const textEncoder = new TextEncoder();
1214
- const hashTable = {};
1215
- for await (const cdHeader of zipCDIterator) {
1216
- const filename = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
1217
- const arrayBuffer = textEncoder.encode(filename).buffer;
1218
- const md5 = await md5Hash.hash(arrayBuffer, "hex");
1219
- hashTable[md5] = cdHeader.localHeaderOffset;
1220
- }
1221
- return hashTable;
1222
- }
1223
- async function composeHashFile(zipCDIterator) {
1224
- const md5Hash = new import_crypto2.MD5Hash();
1225
- const textEncoder = new TextEncoder();
1226
- const hashArray = [];
1227
- for await (const cdHeader of zipCDIterator) {
1228
- const filename = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
1229
- const arrayBuffer = textEncoder.encode(filename).buffer;
1230
- const md5 = await md5Hash.hash(arrayBuffer, "hex");
1231
- hashArray.push(
1232
- (0, import_loader_utils6.concatenateArrayBuffers)(hexStringToBuffer(md5), bigintToBuffer(cdHeader.localHeaderOffset))
1233
- );
1234
- }
1235
- const bufferArray = hashArray.sort(compareHashes);
1236
- return (0, import_loader_utils6.concatenateArrayBuffersFromArray)(bufferArray);
1237
- }
1238
- function compareHashes(arrA, arrB) {
1239
- const a = new BigUint64Array(arrA);
1240
- const b = new BigUint64Array(arrB);
1241
- return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
1242
- }
1243
- function hexStringToBuffer(str) {
1244
- var _a;
1245
- const byteArray = (_a = str.match(/../g)) == null ? void 0 : _a.map((h) => parseInt(h, 16));
1246
- return new Uint8Array(byteArray ?? new Array(16)).buffer;
1247
- }
1248
- function bigintToBuffer(n) {
1249
- return new BigUint64Array([n]).buffer;
1250
- }
1251
-
1252
1193
  // src/filesystems/zip-filesystem.ts
1194
+ var import_loader_utils6 = require("@loaders.gl/loader-utils");
1253
1195
  var import_loader_utils7 = require("@loaders.gl/loader-utils");
1254
1196
  var import_loader_utils8 = require("@loaders.gl/loader-utils");
1255
- var import_loader_utils9 = require("@loaders.gl/loader-utils");
1256
1197
  var import_compression = require("@loaders.gl/compression");
1257
- var COMPRESSION_METHODS = {
1198
+ var ZIP_COMPRESSION_HANDLERS = {
1258
1199
  /** No compression */
1259
1200
  0: async (compressedFile) => compressedFile,
1260
1201
  /** Deflation */
@@ -1272,14 +1213,19 @@ var ZipFileSystem = class {
1272
1213
  constructor(file) {
1273
1214
  /** FileProvider instance promise */
1274
1215
  this.fileProvider = null;
1216
+ this.archive = null;
1275
1217
  if (typeof file === "string") {
1276
1218
  this.fileName = file;
1277
- if (!import_loader_utils7.isBrowser) {
1278
- this.fileProvider = new import_loader_utils9.FileHandleFile(file);
1219
+ if (!import_loader_utils6.isBrowser) {
1220
+ this.fileProvider = new import_loader_utils8.FileHandleFile(file);
1279
1221
  } else {
1280
1222
  throw new Error("Cannot open file for random access in a WEB browser");
1281
1223
  }
1282
- } else if ((0, import_loader_utils8.isFileProvider)(file)) {
1224
+ } else if (file instanceof IndexedArchive) {
1225
+ this.fileProvider = file.fileProvider;
1226
+ this.archive = file;
1227
+ this.fileName = file.fileName;
1228
+ } else if ((0, import_loader_utils7.isFileProvider)(file)) {
1283
1229
  this.fileProvider = file;
1284
1230
  }
1285
1231
  }
@@ -1319,28 +1265,35 @@ var ZipFileSystem = class {
1319
1265
  * @returns - Response with file data
1320
1266
  */
1321
1267
  async fetch(filename) {
1322
- if (!this.fileProvider) {
1323
- throw new Error("No data detected in the zip archive");
1324
- }
1325
- const cdFileHeader = await this.getCDFileHeader(filename);
1326
- const localFileHeader = await parseZipLocalFileHeader(
1327
- cdFileHeader.localHeaderOffset,
1328
- this.fileProvider
1329
- );
1330
- if (!localFileHeader) {
1331
- throw new Error("Local file header has not been found in the zip archive`");
1332
- }
1333
- const compressionHandler = COMPRESSION_METHODS[localFileHeader.compressionMethod.toString()];
1334
- if (!compressionHandler) {
1335
- throw Error("Only Deflation compression is supported");
1268
+ let uncompressedFile;
1269
+ if (this.archive) {
1270
+ uncompressedFile = await this.archive.getFile(filename, "http");
1271
+ } else {
1272
+ if (!this.fileProvider) {
1273
+ throw new Error("No data detected in the zip archive");
1274
+ }
1275
+ const cdFileHeader = await this.getCDFileHeader(filename);
1276
+ const localFileHeader = await parseZipLocalFileHeader(
1277
+ cdFileHeader.localHeaderOffset,
1278
+ this.fileProvider
1279
+ );
1280
+ if (!localFileHeader) {
1281
+ throw new Error("Local file header has not been found in the zip archive`");
1282
+ }
1283
+ const compressionHandler = ZIP_COMPRESSION_HANDLERS[localFileHeader.compressionMethod.toString()];
1284
+ if (!compressionHandler) {
1285
+ throw Error("Only Deflation compression is supported");
1286
+ }
1287
+ const compressedFile = await this.fileProvider.slice(
1288
+ localFileHeader.fileDataOffset,
1289
+ localFileHeader.fileDataOffset + localFileHeader.compressedSize
1290
+ );
1291
+ uncompressedFile = await compressionHandler(compressedFile);
1336
1292
  }
1337
- const compressedFile = await this.fileProvider.slice(
1338
- localFileHeader.fileDataOffset,
1339
- localFileHeader.fileDataOffset + localFileHeader.compressedSize
1340
- );
1341
- const uncompressedFile = await compressionHandler(compressedFile);
1342
1293
  const response = new Response(uncompressedFile);
1343
- Object.defineProperty(response, "url", { value: `${this.fileName || ""}/${filename}` });
1294
+ Object.defineProperty(response, "url", {
1295
+ value: filename ? `${this.fileName || ""}/${filename}` : this.fileName || ""
1296
+ });
1344
1297
  return response;
1345
1298
  }
1346
1299
  /**
@@ -1366,3 +1319,88 @@ var ZipFileSystem = class {
1366
1319
  return result;
1367
1320
  }
1368
1321
  };
1322
+
1323
+ // src/filesystems/IndexedArchive.ts
1324
+ var IndexedArchive = class {
1325
+ /**
1326
+ * Constructor
1327
+ * @param fileProvider - instance of a binary data reader
1328
+ * @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
1329
+ * @param fileName - name of the archive. It is used to add to an URL of a loader context
1330
+ */
1331
+ constructor(fileProvider, hashTable, fileName) {
1332
+ this.fileProvider = fileProvider;
1333
+ this.fileName = fileName;
1334
+ }
1335
+ /**
1336
+ * Get file as from order ZIP arhive without using the hash file
1337
+ * @param filename - path to the internal file
1338
+ * @returns
1339
+ */
1340
+ async getFileWithoutHash(filename) {
1341
+ const zipFS = new ZipFileSystem(this.fileProvider);
1342
+ const response = await zipFS.fetch(filename);
1343
+ return await response.arrayBuffer();
1344
+ }
1345
+ };
1346
+
1347
+ // src/hash-file-utility.ts
1348
+ var import_crypto2 = require("@loaders.gl/crypto");
1349
+ var import_loader_utils9 = require("@loaders.gl/loader-utils");
1350
+ function parseHashTable(arrayBuffer) {
1351
+ const dataView = new DataView(arrayBuffer);
1352
+ const hashMap = {};
1353
+ for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {
1354
+ const offset = dataView.getBigUint64(i + 16, true);
1355
+ const hash = bufferToHex(arrayBuffer, i, 16);
1356
+ hashMap[hash] = offset;
1357
+ }
1358
+ return hashMap;
1359
+ }
1360
+ function bufferToHex(buffer, start, length) {
1361
+ return [...new Uint8Array(buffer, start, length)].map((x) => x.toString(16).padStart(2, "0")).join("");
1362
+ }
1363
+ async function makeHashTableFromZipHeaders(fileProvider) {
1364
+ const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
1365
+ return getHashTable(zipCDIterator);
1366
+ }
1367
+ async function getHashTable(zipCDIterator) {
1368
+ const md5Hash = new import_crypto2.MD5Hash();
1369
+ const textEncoder = new TextEncoder();
1370
+ const hashTable = {};
1371
+ for await (const cdHeader of zipCDIterator) {
1372
+ const filename = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
1373
+ const arrayBuffer = textEncoder.encode(filename).buffer;
1374
+ const md5 = await md5Hash.hash(arrayBuffer, "hex");
1375
+ hashTable[md5] = cdHeader.localHeaderOffset;
1376
+ }
1377
+ return hashTable;
1378
+ }
1379
+ async function composeHashFile(zipCDIterator) {
1380
+ const md5Hash = new import_crypto2.MD5Hash();
1381
+ const textEncoder = new TextEncoder();
1382
+ const hashArray = [];
1383
+ for await (const cdHeader of zipCDIterator) {
1384
+ const filename = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
1385
+ const arrayBuffer = textEncoder.encode(filename).buffer;
1386
+ const md5 = await md5Hash.hash(arrayBuffer, "hex");
1387
+ hashArray.push(
1388
+ (0, import_loader_utils9.concatenateArrayBuffers)(hexStringToBuffer(md5), bigintToBuffer(cdHeader.localHeaderOffset))
1389
+ );
1390
+ }
1391
+ const bufferArray = hashArray.sort(compareHashes);
1392
+ return (0, import_loader_utils9.concatenateArrayBuffersFromArray)(bufferArray);
1393
+ }
1394
+ function compareHashes(arrA, arrB) {
1395
+ const a = new BigUint64Array(arrA);
1396
+ const b = new BigUint64Array(arrB);
1397
+ return Number(a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
1398
+ }
1399
+ function hexStringToBuffer(str) {
1400
+ var _a;
1401
+ const byteArray = (_a = str.match(/../g)) == null ? void 0 : _a.map((h) => parseInt(h, 16));
1402
+ return new Uint8Array(byteArray ?? new Array(16)).buffer;
1403
+ }
1404
+ function bigintToBuffer(n) {
1405
+ return new BigUint64Array([n]).buffer;
1406
+ }
package/dist/index.d.ts CHANGED
@@ -6,6 +6,8 @@ export { parseZipLocalFileHeader, signature as localHeaderSignature, generateLoc
6
6
  export { parseEoCDRecord } from './parse-zip/end-of-central-directory';
7
7
  export { searchFromTheEnd } from './parse-zip/search-from-the-end';
8
8
  export { addOneFile, createZip } from './parse-zip/zip-composition';
9
+ export { IndexedArchive } from './filesystems/IndexedArchive';
9
10
  export { parseHashTable, makeHashTableFromZipHeaders, composeHashFile } from './hash-file-utility';
10
- export { ZipFileSystem } from './filesystems/zip-filesystem';
11
+ export { ZipFileSystem, ZIP_COMPRESSION_HANDLERS } from './filesystems/zip-filesystem';
12
+ export type { CompressionHandler } from './filesystems/zip-filesystem';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAEzC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,SAAS,IAAI,mBAAmB,EAChC,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,uBAAuB,EACvB,SAAS,IAAI,oBAAoB,EACjC,mBAAmB,EACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAC,UAAU,EAAE,SAAS,EAAC,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAC,cAAc,EAAE,2BAA2B,EAAE,eAAe,EAAC,MAAM,qBAAqB,CAAC;AAEjG,OAAO,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AACvC,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAC;AAEzC,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,SAAS,IAAI,mBAAmB,EAChC,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,uBAAuB,EACvB,SAAS,IAAI,oBAAoB,EACjC,mBAAmB,EACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAC,gBAAgB,EAAC,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAC,UAAU,EAAE,SAAS,EAAC,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAC,cAAc,EAAC,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAC,cAAc,EAAE,2BAA2B,EAAE,eAAe,EAAC,MAAM,qBAAqB,CAAC;AAEjG,OAAO,EAAC,aAAa,EAAE,wBAAwB,EAAC,MAAM,8BAA8B,CAAC;AACrF,YAAY,EAAC,kBAAkB,EAAC,MAAM,8BAA8B,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { parseZipLocalFileHeader, signature as localHeaderSignature, generateLoc
6
6
  export { parseEoCDRecord } from "./parse-zip/end-of-central-directory.js";
7
7
  export { searchFromTheEnd } from "./parse-zip/search-from-the-end.js";
8
8
  export { addOneFile, createZip } from "./parse-zip/zip-composition.js";
9
+ export { IndexedArchive } from "./filesystems/IndexedArchive.js";
9
10
  export { parseHashTable, makeHashTableFromZipHeaders, composeHashFile } from "./hash-file-utility.js";
10
- export { ZipFileSystem } from "./filesystems/zip-filesystem.js";
11
+ export { ZipFileSystem, ZIP_COMPRESSION_HANDLERS } from "./filesystems/zip-filesystem.js";
11
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ZipLoader","ZipWriter","TarBuilder","parseZipCDFileHeader","makeZipCDHeaderIterator","signature","CD_HEADER_SIGNATURE","generateCDHeader","parseZipLocalFileHeader","localHeaderSignature","generateLocalHeader","parseEoCDRecord","searchFromTheEnd","addOneFile","createZip","parseHashTable","makeHashTableFromZipHeaders","composeHashFile","ZipFileSystem"],"sources":["../src/index.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nexport {ZipLoader} from './zip-loader';\nexport {ZipWriter} from './zip-writer';\nexport {TarBuilder} from './tar-builder';\n\nexport {\n parseZipCDFileHeader,\n makeZipCDHeaderIterator,\n signature as CD_HEADER_SIGNATURE,\n generateCDHeader\n} from './parse-zip/cd-file-header';\nexport {\n parseZipLocalFileHeader,\n signature as localHeaderSignature,\n generateLocalHeader\n} from './parse-zip/local-file-header';\nexport {parseEoCDRecord} from './parse-zip/end-of-central-directory';\nexport {searchFromTheEnd} from './parse-zip/search-from-the-end';\nexport {addOneFile, createZip} from './parse-zip/zip-composition';\n\n// export type {HashElement} from './hash-file-utility';\nexport {parseHashTable, makeHashTableFromZipHeaders, composeHashFile} from './hash-file-utility';\n\nexport {ZipFileSystem} from './filesystems/zip-filesystem';\n"],"mappings":"SAIQA,SAAS;AAAA,SACTC,SAAS;AAAA,SACTC,UAAU;AAAA,SAGhBC,oBAAoB,EACpBC,uBAAuB,EACvBC,SAAS,IAAIC,mBAAmB,EAChCC,gBAAgB;AAAA,SAGhBC,uBAAuB,EACvBH,SAAS,IAAII,oBAAoB,EACjCC,mBAAmB;AAAA,SAEbC,eAAe;AAAA,SACfC,gBAAgB;AAAA,SAChBC,UAAU,EAAEC,SAAS;AAAA,SAGrBC,cAAc,EAAEC,2BAA2B,EAAEC,eAAe;AAAA,SAE5DC,aAAa"}
1
+ {"version":3,"file":"index.js","names":["ZipLoader","ZipWriter","TarBuilder","parseZipCDFileHeader","makeZipCDHeaderIterator","signature","CD_HEADER_SIGNATURE","generateCDHeader","parseZipLocalFileHeader","localHeaderSignature","generateLocalHeader","parseEoCDRecord","searchFromTheEnd","addOneFile","createZip","IndexedArchive","parseHashTable","makeHashTableFromZipHeaders","composeHashFile","ZipFileSystem","ZIP_COMPRESSION_HANDLERS"],"sources":["../src/index.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nexport {ZipLoader} from './zip-loader';\nexport {ZipWriter} from './zip-writer';\nexport {TarBuilder} from './tar-builder';\n\nexport {\n parseZipCDFileHeader,\n makeZipCDHeaderIterator,\n signature as CD_HEADER_SIGNATURE,\n generateCDHeader\n} from './parse-zip/cd-file-header';\nexport {\n parseZipLocalFileHeader,\n signature as localHeaderSignature,\n generateLocalHeader\n} from './parse-zip/local-file-header';\nexport {parseEoCDRecord} from './parse-zip/end-of-central-directory';\nexport {searchFromTheEnd} from './parse-zip/search-from-the-end';\nexport {addOneFile, createZip} from './parse-zip/zip-composition';\n\n// export type {HashElement} from './hash-file-utility';\nexport {IndexedArchive} from './filesystems/IndexedArchive';\nexport {parseHashTable, makeHashTableFromZipHeaders, composeHashFile} from './hash-file-utility';\n\nexport {ZipFileSystem, ZIP_COMPRESSION_HANDLERS} from './filesystems/zip-filesystem';\nexport type {CompressionHandler} from './filesystems/zip-filesystem';\n"],"mappings":"SAIQA,SAAS;AAAA,SACTC,SAAS;AAAA,SACTC,UAAU;AAAA,SAGhBC,oBAAoB,EACpBC,uBAAuB,EACvBC,SAAS,IAAIC,mBAAmB,EAChCC,gBAAgB;AAAA,SAGhBC,uBAAuB,EACvBH,SAAS,IAAII,oBAAoB,EACjCC,mBAAmB;AAAA,SAEbC,eAAe;AAAA,SACfC,gBAAgB;AAAA,SAChBC,UAAU,EAAEC,SAAS;AAAA,SAGrBC,cAAc;AAAA,SACdC,cAAc,EAAEC,2BAA2B,EAAEC,eAAe;AAAA,SAE5DC,aAAa,EAAEC,wBAAwB"}
@@ -1,5 +1,5 @@
1
1
  import JSZip from 'jszip';
2
- const VERSION = typeof "4.2.0-alpha.1" !== 'undefined' ? "4.2.0-alpha.1" : 'latest';
2
+ const VERSION = typeof "4.2.0-alpha.2" !== 'undefined' ? "4.2.0-alpha.2" : 'latest';
3
3
  export const ZipLoader = {
4
4
  id: 'zip',
5
5
  module: 'zip',
@@ -1,5 +1,5 @@
1
1
  import JSZip from 'jszip';
2
- const VERSION = typeof "4.2.0-alpha.1" !== 'undefined' ? "4.2.0-alpha.1" : 'latest';
2
+ const VERSION = typeof "4.2.0-alpha.2" !== 'undefined' ? "4.2.0-alpha.2" : 'latest';
3
3
  export const ZipWriter = {
4
4
  name: 'Zip Archive',
5
5
  id: 'zip',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/zip",
3
- "version": "4.2.0-alpha.1",
3
+ "version": "4.2.0-alpha.2",
4
4
  "description": "Zip Archive Loader",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -38,11 +38,11 @@
38
38
  "build-bundle": "ocular-bundle ./src/index.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@loaders.gl/compression": "4.2.0-alpha.1",
42
- "@loaders.gl/crypto": "4.2.0-alpha.1",
43
- "@loaders.gl/loader-utils": "4.2.0-alpha.1",
41
+ "@loaders.gl/compression": "4.2.0-alpha.2",
42
+ "@loaders.gl/crypto": "4.2.0-alpha.2",
43
+ "@loaders.gl/loader-utils": "4.2.0-alpha.2",
44
44
  "jszip": "^3.1.5",
45
45
  "md5": "^2.3.0"
46
46
  },
47
- "gitHead": "d4da81f4d8fb2a3b43b0e025109cf7ccfb317d4c"
47
+ "gitHead": "d66a6a4626ea84c5f2cad5fa5cf7ebb6943c57c8"
48
48
  }
@@ -0,0 +1,40 @@
1
+ import {FileProvider} from '@loaders.gl/loader-utils';
2
+ import {ZipFileSystem} from './zip-filesystem';
3
+
4
+ /**
5
+ * Abstract class for fetching indexed archive formats (SLPK, 3TZ). Those types of zip archive has
6
+ * a hash file inside that allows to increase reading speed
7
+ */
8
+ export abstract class IndexedArchive {
9
+ public fileProvider: FileProvider;
10
+ public fileName?: string;
11
+
12
+ /**
13
+ * Constructor
14
+ * @param fileProvider - instance of a binary data reader
15
+ * @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
16
+ * @param fileName - name of the archive. It is used to add to an URL of a loader context
17
+ */
18
+ constructor(fileProvider: FileProvider, hashTable?: Record<string, bigint>, fileName?: string) {
19
+ this.fileProvider = fileProvider;
20
+ this.fileName = fileName;
21
+ }
22
+
23
+ /**
24
+ * Get internal file from the archive
25
+ * @param path - path to the file
26
+ * @param mode - path mode - the logic is implemented in subclasses
27
+ */
28
+ abstract getFile(path: string, mode?: string): Promise<ArrayBuffer>;
29
+
30
+ /**
31
+ * Get file as from order ZIP arhive without using the hash file
32
+ * @param filename - path to the internal file
33
+ * @returns
34
+ */
35
+ protected async getFileWithoutHash(filename: string): Promise<ArrayBuffer> {
36
+ const zipFS = new ZipFileSystem(this.fileProvider);
37
+ const response = await zipFS.fetch(filename);
38
+ return await response.arrayBuffer();
39
+ }
40
+ }
@@ -8,10 +8,11 @@ import {FileHandleFile} from '@loaders.gl/loader-utils';
8
8
  import {ZipCDFileHeader, makeZipCDHeaderIterator} from '../parse-zip/cd-file-header';
9
9
  import {parseZipLocalFileHeader} from '../parse-zip/local-file-header';
10
10
  import {DeflateCompression} from '@loaders.gl/compression';
11
+ import {IndexedArchive} from './IndexedArchive';
11
12
 
12
- type CompressionHandler = (compressedFile: ArrayBuffer) => Promise<ArrayBuffer>;
13
+ export type CompressionHandler = (compressedFile: ArrayBuffer) => Promise<ArrayBuffer>;
13
14
  /** Handling different compression types in zip */
14
- const COMPRESSION_METHODS: {[key: number]: CompressionHandler} = {
15
+ export const ZIP_COMPRESSION_HANDLERS: {[key: number]: CompressionHandler} = {
15
16
  /** No compression */
16
17
  0: async (compressedFile) => compressedFile,
17
18
  /** Deflation */
@@ -30,12 +31,13 @@ export class ZipFileSystem implements FileSystem {
30
31
  /** FileProvider instance promise */
31
32
  protected fileProvider: FileProvider | null = null;
32
33
  public fileName?: string;
34
+ public archive: IndexedArchive | null = null;
33
35
 
34
36
  /**
35
37
  * Constructor
36
38
  * @param file - instance of FileProvider or file path string
37
39
  */
38
- constructor(file: FileProvider | string) {
40
+ constructor(file: FileProvider | IndexedArchive | string) {
39
41
  // Try to open file in NodeJS
40
42
  if (typeof file === 'string') {
41
43
  this.fileName = file;
@@ -44,6 +46,10 @@ export class ZipFileSystem implements FileSystem {
44
46
  } else {
45
47
  throw new Error('Cannot open file for random access in a WEB browser');
46
48
  }
49
+ } else if (file instanceof IndexedArchive) {
50
+ this.fileProvider = file.fileProvider;
51
+ this.archive = file;
52
+ this.fileName = file.fileName;
47
53
  } else if (isFileProvider(file)) {
48
54
  this.fileProvider = file;
49
55
  }
@@ -88,32 +94,40 @@ export class ZipFileSystem implements FileSystem {
88
94
  * @returns - Response with file data
89
95
  */
90
96
  async fetch(filename: string): Promise<Response> {
91
- if (!this.fileProvider) {
92
- throw new Error('No data detected in the zip archive');
93
- }
94
- const cdFileHeader = await this.getCDFileHeader(filename);
95
- const localFileHeader = await parseZipLocalFileHeader(
96
- cdFileHeader.localHeaderOffset,
97
- this.fileProvider
98
- );
99
- if (!localFileHeader) {
100
- throw new Error('Local file header has not been found in the zip archive`');
101
- }
97
+ let uncompressedFile: ArrayBuffer;
98
+ if (this.archive) {
99
+ uncompressedFile = await this.archive.getFile(filename, 'http');
100
+ } else {
101
+ if (!this.fileProvider) {
102
+ throw new Error('No data detected in the zip archive');
103
+ }
104
+ const cdFileHeader = await this.getCDFileHeader(filename);
105
+ const localFileHeader = await parseZipLocalFileHeader(
106
+ cdFileHeader.localHeaderOffset,
107
+ this.fileProvider
108
+ );
109
+ if (!localFileHeader) {
110
+ throw new Error('Local file header has not been found in the zip archive`');
111
+ }
102
112
 
103
- const compressionHandler = COMPRESSION_METHODS[localFileHeader.compressionMethod.toString()];
104
- if (!compressionHandler) {
105
- throw Error('Only Deflation compression is supported');
106
- }
113
+ const compressionHandler =
114
+ ZIP_COMPRESSION_HANDLERS[localFileHeader.compressionMethod.toString()];
115
+ if (!compressionHandler) {
116
+ throw Error('Only Deflation compression is supported');
117
+ }
107
118
 
108
- const compressedFile = await this.fileProvider.slice(
109
- localFileHeader.fileDataOffset,
110
- localFileHeader.fileDataOffset + localFileHeader.compressedSize
111
- );
119
+ const compressedFile = await this.fileProvider.slice(
120
+ localFileHeader.fileDataOffset,
121
+ localFileHeader.fileDataOffset + localFileHeader.compressedSize
122
+ );
112
123
 
113
- const uncompressedFile = await compressionHandler(compressedFile);
124
+ uncompressedFile = await compressionHandler(compressedFile);
125
+ }
114
126
 
115
127
  const response = new Response(uncompressedFile);
116
- Object.defineProperty(response, 'url', {value: `${this.fileName || ''}/${filename}`});
128
+ Object.defineProperty(response, 'url', {
129
+ value: filename ? `${this.fileName || ''}/${filename}` : this.fileName || ''
130
+ });
117
131
  return response;
118
132
  }
119
133
 
package/src/index.ts CHANGED
@@ -22,6 +22,8 @@ export {searchFromTheEnd} from './parse-zip/search-from-the-end';
22
22
  export {addOneFile, createZip} from './parse-zip/zip-composition';
23
23
 
24
24
  // export type {HashElement} from './hash-file-utility';
25
+ export {IndexedArchive} from './filesystems/IndexedArchive';
25
26
  export {parseHashTable, makeHashTableFromZipHeaders, composeHashFile} from './hash-file-utility';
26
27
 
27
- export {ZipFileSystem} from './filesystems/zip-filesystem';
28
+ export {ZipFileSystem, ZIP_COMPRESSION_HANDLERS} from './filesystems/zip-filesystem';
29
+ export type {CompressionHandler} from './filesystems/zip-filesystem';