@loaders.gl/zip 4.1.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 +98 -73
- package/dist/filesystems/IndexedArchive.d.ts +29 -0
- package/dist/filesystems/IndexedArchive.d.ts.map +1 -0
- package/dist/filesystems/IndexedArchive.js +15 -0
- package/dist/filesystems/IndexedArchive.js.map +1 -0
- package/dist/filesystems/zip-filesystem.d.ts +8 -1
- package/dist/filesystems/zip-filesystem.d.ts.map +1 -1
- package/dist/filesystems/zip-filesystem.js +26 -15
- package/dist/filesystems/zip-filesystem.js.map +1 -1
- package/dist/index.cjs +124 -86
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/zip-loader.js +1 -1
- package/dist/zip-loader.js.map +1 -1
- package/dist/zip-writer.js +1 -1
- package/dist/zip-writer.js.map +1 -1
- package/package.json +5 -5
- package/src/filesystems/IndexedArchive.ts +40 -0
- package/src/filesystems/zip-filesystem.ts +38 -24
- package/src/index.ts +3 -1
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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","
|
|
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
|
|
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 (!
|
|
1278
|
-
this.fileProvider = new
|
|
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 (
|
|
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
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
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", {
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|
package/dist/zip-loader.js
CHANGED
package/dist/zip-loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zip-loader.js","names":["JSZip","VERSION","ZipLoader","id","module","name","version","extensions","mimeTypes","category","tests","options","parse","parseZipAsync","data","arguments","length","undefined","promises","fileMap","jsZip","zip","loadAsync","forEach","relativePath","zipEntry","subFilename","promise","loadZipEntry","then","arrayBufferOrError","push","Promise","all","error","log","arrayBuffer","file","async","dataType"],"sources":["../src/zip-loader.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-utils';\nimport JSZip from 'jszip';\n\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';\n\ntype FileMap = Record<string, ArrayBuffer>;\n\nexport const ZipLoader: LoaderWithParser<FileMap, never, LoaderOptions> = {\n id: 'zip',\n module: 'zip',\n name: 'Zip Archive',\n version: VERSION,\n extensions: ['zip'],\n mimeTypes: ['application/zip'],\n category: 'archive',\n tests: ['PK'],\n options: {},\n parse: parseZipAsync\n};\n\n// TODO - Could return a map of promises, perhaps as an option...\nasync function parseZipAsync(data: any, options = {}): Promise<FileMap> {\n const promises: Promise<any>[] = [];\n const fileMap: Record<string, ArrayBuffer> = {};\n\n try {\n const jsZip = new JSZip();\n\n const zip = await jsZip.loadAsync(data, options);\n\n // start to load each file in this zip\n zip.forEach((relativePath, zipEntry) => {\n const subFilename = zipEntry.name;\n\n const promise = loadZipEntry(jsZip, subFilename, options).then((arrayBufferOrError) => {\n fileMap[relativePath] = arrayBufferOrError;\n });\n\n // Ensure Promise.all doesn't ignore rejected promises.\n promises.push(promise);\n });\n\n await Promise.all(promises);\n return fileMap;\n } catch (error) {\n // @ts-ignore\n options.log.error(`Unable to read zip archive: ${error}`);\n throw error;\n }\n}\n\nasync function loadZipEntry(jsZip: any, subFilename: string, options: any = {}) {\n // jszip supports both arraybuffer and text, the main loaders.gl types\n // https://stuk.github.io/jszip/documentation/api_zipobject/async.html\n try {\n const arrayBuffer = await jsZip.file(subFilename).async(options.dataType || 'arraybuffer');\n return arrayBuffer;\n } catch (error) {\n options.log.error(`Unable to read ${subFilename} from zip archive: ${error}`);\n // Store error in place of data in map\n return error;\n }\n}\n"],"mappings":"AAKA,OAAOA,KAAK,MAAM,OAAO;AAIzB,MAAMC,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"zip-loader.js","names":["JSZip","VERSION","ZipLoader","id","module","name","version","extensions","mimeTypes","category","tests","options","parse","parseZipAsync","data","arguments","length","undefined","promises","fileMap","jsZip","zip","loadAsync","forEach","relativePath","zipEntry","subFilename","promise","loadZipEntry","then","arrayBufferOrError","push","Promise","all","error","log","arrayBuffer","file","async","dataType"],"sources":["../src/zip-loader.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-utils';\nimport JSZip from 'jszip';\n\n// __VERSION__ is injected by babel-plugin-version-inline\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';\n\ntype FileMap = Record<string, ArrayBuffer>;\n\nexport const ZipLoader: LoaderWithParser<FileMap, never, LoaderOptions> = {\n id: 'zip',\n module: 'zip',\n name: 'Zip Archive',\n version: VERSION,\n extensions: ['zip'],\n mimeTypes: ['application/zip'],\n category: 'archive',\n tests: ['PK'],\n options: {},\n parse: parseZipAsync\n};\n\n// TODO - Could return a map of promises, perhaps as an option...\nasync function parseZipAsync(data: any, options = {}): Promise<FileMap> {\n const promises: Promise<any>[] = [];\n const fileMap: Record<string, ArrayBuffer> = {};\n\n try {\n const jsZip = new JSZip();\n\n const zip = await jsZip.loadAsync(data, options);\n\n // start to load each file in this zip\n zip.forEach((relativePath, zipEntry) => {\n const subFilename = zipEntry.name;\n\n const promise = loadZipEntry(jsZip, subFilename, options).then((arrayBufferOrError) => {\n fileMap[relativePath] = arrayBufferOrError;\n });\n\n // Ensure Promise.all doesn't ignore rejected promises.\n promises.push(promise);\n });\n\n await Promise.all(promises);\n return fileMap;\n } catch (error) {\n // @ts-ignore\n options.log.error(`Unable to read zip archive: ${error}`);\n throw error;\n }\n}\n\nasync function loadZipEntry(jsZip: any, subFilename: string, options: any = {}) {\n // jszip supports both arraybuffer and text, the main loaders.gl types\n // https://stuk.github.io/jszip/documentation/api_zipobject/async.html\n try {\n const arrayBuffer = await jsZip.file(subFilename).async(options.dataType || 'arraybuffer');\n return arrayBuffer;\n } catch (error) {\n options.log.error(`Unable to read ${subFilename} from zip archive: ${error}`);\n // Store error in place of data in map\n return error;\n }\n}\n"],"mappings":"AAKA,OAAOA,KAAK,MAAM,OAAO;AAIzB,MAAMC,OAAO,GAAG,sBAAkB,KAAK,WAAW,qBAAiB,QAAQ;AAI3E,OAAO,MAAMC,SAA0D,GAAG;EACxEC,EAAE,EAAE,KAAK;EACTC,MAAM,EAAE,KAAK;EACbC,IAAI,EAAE,aAAa;EACnBC,OAAO,EAAEL,OAAO;EAChBM,UAAU,EAAE,CAAC,KAAK,CAAC;EACnBC,SAAS,EAAE,CAAC,iBAAiB,CAAC;EAC9BC,QAAQ,EAAE,SAAS;EACnBC,KAAK,EAAE,CAAC,IAAI,CAAC;EACbC,OAAO,EAAE,CAAC,CAAC;EACXC,KAAK,EAAEC;AACT,CAAC;AAGD,eAAeA,aAAaA,CAACC,IAAS,EAAkC;EAAA,IAAhCH,OAAO,GAAAI,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EAClD,MAAMG,QAAwB,GAAG,EAAE;EACnC,MAAMC,OAAoC,GAAG,CAAC,CAAC;EAE/C,IAAI;IACF,MAAMC,KAAK,GAAG,IAAIpB,KAAK,CAAC,CAAC;IAEzB,MAAMqB,GAAG,GAAG,MAAMD,KAAK,CAACE,SAAS,CAACR,IAAI,EAAEH,OAAO,CAAC;IAGhDU,GAAG,CAACE,OAAO,CAAC,CAACC,YAAY,EAAEC,QAAQ,KAAK;MACtC,MAAMC,WAAW,GAAGD,QAAQ,CAACpB,IAAI;MAEjC,MAAMsB,OAAO,GAAGC,YAAY,CAACR,KAAK,EAAEM,WAAW,EAAEf,OAAO,CAAC,CAACkB,IAAI,CAAEC,kBAAkB,IAAK;QACrFX,OAAO,CAACK,YAAY,CAAC,GAAGM,kBAAkB;MAC5C,CAAC,CAAC;MAGFZ,QAAQ,CAACa,IAAI,CAACJ,OAAO,CAAC;IACxB,CAAC,CAAC;IAEF,MAAMK,OAAO,CAACC,GAAG,CAACf,QAAQ,CAAC;IAC3B,OAAOC,OAAO;EAChB,CAAC,CAAC,OAAOe,KAAK,EAAE;IAEdvB,OAAO,CAACwB,GAAG,CAACD,KAAK,CAAE,+BAA8BA,KAAM,EAAC,CAAC;IACzD,MAAMA,KAAK;EACb;AACF;AAEA,eAAeN,YAAYA,CAACR,KAAU,EAAEM,WAAmB,EAAqB;EAAA,IAAnBf,OAAY,GAAAI,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EAG5E,IAAI;IACF,MAAMqB,WAAW,GAAG,MAAMhB,KAAK,CAACiB,IAAI,CAACX,WAAW,CAAC,CAACY,KAAK,CAAC3B,OAAO,CAAC4B,QAAQ,IAAI,aAAa,CAAC;IAC1F,OAAOH,WAAW;EACpB,CAAC,CAAC,OAAOF,KAAK,EAAE;IACdvB,OAAO,CAACwB,GAAG,CAACD,KAAK,CAAE,kBAAiBR,WAAY,sBAAqBQ,KAAM,EAAC,CAAC;IAE7E,OAAOA,KAAK;EACd;AACF"}
|
package/dist/zip-writer.js
CHANGED
package/dist/zip-writer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zip-writer.js","names":["JSZip","VERSION","ZipWriter","name","id","module","version","extensions","category","mimeTypes","options","zip","onUpdate","jszip","encode","encodeZipAsync","fileMap","_ZipWriter$options","arguments","length","undefined","jsZip","subFileName","subFileData","file","zipOptions","jszipOptions","generateAsync","type","error","log"],"sources":["../src/zip-writer.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {WriterWithEncoder, WriterOptions} from '@loaders.gl/loader-utils';\nimport JSZip, {JSZipGeneratorOptions} from 'jszip';\n\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';\n\nexport type ZipWriterOptions = WriterOptions & {\n zip?: {\n onUpdate?: (metadata: {percent: number}) => void;\n };\n /** Passthrough options to jszip */\n jszip?: JSZipGeneratorOptions;\n};\n\n/**\n * Zip exporter\n */\nexport const ZipWriter: WriterWithEncoder<Record<string, ArrayBuffer>, never, ZipWriterOptions> = {\n name: 'Zip Archive',\n id: 'zip',\n module: 'zip',\n version: VERSION,\n extensions: ['zip'],\n category: 'archive',\n mimeTypes: ['application/zip'],\n options: {\n zip: {\n onUpdate: () => {}\n },\n jszip: {}\n },\n encode: encodeZipAsync\n};\n\nasync function encodeZipAsync(\n fileMap: Record<string, ArrayBuffer>,\n options: ZipWriterOptions = {}\n): Promise<ArrayBuffer> {\n const jsZip = new JSZip();\n // add files to the zip\n for (const subFileName in fileMap) {\n const subFileData = fileMap[subFileName];\n\n // jszip supports both arraybuffer and string data (the main loaders.gl types)\n // https://stuk.github.io/jszip/documentation/api_zipobject/async.html\n jsZip.file(subFileName, subFileData, options?.jszip || {});\n }\n\n const zipOptions = {...ZipWriter.options.zip, ...options?.zip};\n const jszipOptions: JSZipGeneratorOptions = {...ZipWriter.options?.jszip, ...options.jszip};\n\n try {\n return await jsZip.generateAsync(\n {...jszipOptions, type: 'arraybuffer'}, // generate an arraybuffer\n zipOptions.onUpdate\n );\n } catch (error) {\n options.log.error(`Unable to encode zip archive: ${error}`);\n throw error;\n }\n}\n"],"mappings":"AAKA,OAAOA,KAAK,MAA+B,OAAO;AAGlD,MAAMC,OAAO,GAAG,
|
|
1
|
+
{"version":3,"file":"zip-writer.js","names":["JSZip","VERSION","ZipWriter","name","id","module","version","extensions","category","mimeTypes","options","zip","onUpdate","jszip","encode","encodeZipAsync","fileMap","_ZipWriter$options","arguments","length","undefined","jsZip","subFileName","subFileData","file","zipOptions","jszipOptions","generateAsync","type","error","log"],"sources":["../src/zip-writer.ts"],"sourcesContent":["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {WriterWithEncoder, WriterOptions} from '@loaders.gl/loader-utils';\nimport JSZip, {JSZipGeneratorOptions} from 'jszip';\n\n// @ts-ignore TS2304: Cannot find name '__VERSION__'.\nconst VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';\n\nexport type ZipWriterOptions = WriterOptions & {\n zip?: {\n onUpdate?: (metadata: {percent: number}) => void;\n };\n /** Passthrough options to jszip */\n jszip?: JSZipGeneratorOptions;\n};\n\n/**\n * Zip exporter\n */\nexport const ZipWriter: WriterWithEncoder<Record<string, ArrayBuffer>, never, ZipWriterOptions> = {\n name: 'Zip Archive',\n id: 'zip',\n module: 'zip',\n version: VERSION,\n extensions: ['zip'],\n category: 'archive',\n mimeTypes: ['application/zip'],\n options: {\n zip: {\n onUpdate: () => {}\n },\n jszip: {}\n },\n encode: encodeZipAsync\n};\n\nasync function encodeZipAsync(\n fileMap: Record<string, ArrayBuffer>,\n options: ZipWriterOptions = {}\n): Promise<ArrayBuffer> {\n const jsZip = new JSZip();\n // add files to the zip\n for (const subFileName in fileMap) {\n const subFileData = fileMap[subFileName];\n\n // jszip supports both arraybuffer and string data (the main loaders.gl types)\n // https://stuk.github.io/jszip/documentation/api_zipobject/async.html\n jsZip.file(subFileName, subFileData, options?.jszip || {});\n }\n\n const zipOptions = {...ZipWriter.options.zip, ...options?.zip};\n const jszipOptions: JSZipGeneratorOptions = {...ZipWriter.options?.jszip, ...options.jszip};\n\n try {\n return await jsZip.generateAsync(\n {...jszipOptions, type: 'arraybuffer'}, // generate an arraybuffer\n zipOptions.onUpdate\n );\n } catch (error) {\n options.log.error(`Unable to encode zip archive: ${error}`);\n throw error;\n }\n}\n"],"mappings":"AAKA,OAAOA,KAAK,MAA+B,OAAO;AAGlD,MAAMC,OAAO,GAAG,sBAAkB,KAAK,WAAW,qBAAiB,QAAQ;AAa3E,OAAO,MAAMC,SAAkF,GAAG;EAChGC,IAAI,EAAE,aAAa;EACnBC,EAAE,EAAE,KAAK;EACTC,MAAM,EAAE,KAAK;EACbC,OAAO,EAAEL,OAAO;EAChBM,UAAU,EAAE,CAAC,KAAK,CAAC;EACnBC,QAAQ,EAAE,SAAS;EACnBC,SAAS,EAAE,CAAC,iBAAiB,CAAC;EAC9BC,OAAO,EAAE;IACPC,GAAG,EAAE;MACHC,QAAQ,EAAEA,CAAA,KAAM,CAAC;IACnB,CAAC;IACDC,KAAK,EAAE,CAAC;EACV,CAAC;EACDC,MAAM,EAAEC;AACV,CAAC;AAED,eAAeA,cAAcA,CAC3BC,OAAoC,EAEd;EAAA,IAAAC,kBAAA;EAAA,IADtBP,OAAyB,GAAAQ,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAG,CAAC,CAAC;EAE9B,MAAMG,KAAK,GAAG,IAAIrB,KAAK,CAAC,CAAC;EAEzB,KAAK,MAAMsB,WAAW,IAAIN,OAAO,EAAE;IACjC,MAAMO,WAAW,GAAGP,OAAO,CAACM,WAAW,CAAC;IAIxCD,KAAK,CAACG,IAAI,CAACF,WAAW,EAAEC,WAAW,EAAE,CAAAb,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEG,KAAK,KAAI,CAAC,CAAC,CAAC;EAC5D;EAEA,MAAMY,UAAU,GAAG;IAAC,GAAGvB,SAAS,CAACQ,OAAO,CAACC,GAAG;IAAE,IAAGD,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAEC,GAAG;EAAA,CAAC;EAC9D,MAAMe,YAAmC,GAAG;IAAC,KAAAT,kBAAA,GAAGf,SAAS,CAACQ,OAAO,cAAAO,kBAAA,uBAAjBA,kBAAA,CAAmBJ,KAAK;IAAE,GAAGH,OAAO,CAACG;EAAK,CAAC;EAE3F,IAAI;IACF,OAAO,MAAMQ,KAAK,CAACM,aAAa,CAC9B;MAAC,GAAGD,YAAY;MAAEE,IAAI,EAAE;IAAa,CAAC,EACtCH,UAAU,CAACb,QACb,CAAC;EACH,CAAC,CAAC,OAAOiB,KAAK,EAAE;IACdnB,OAAO,CAACoB,GAAG,CAACD,KAAK,CAAE,iCAAgCA,KAAM,EAAC,CAAC;IAC3D,MAAMA,KAAK;EACb;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loaders.gl/zip",
|
|
3
|
-
"version": "4.
|
|
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.
|
|
42
|
-
"@loaders.gl/crypto": "4.
|
|
43
|
-
"@loaders.gl/loader-utils": "4.
|
|
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": "
|
|
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
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
const compressedFile = await this.fileProvider.slice(
|
|
120
|
+
localFileHeader.fileDataOffset,
|
|
121
|
+
localFileHeader.fileDataOffset + localFileHeader.compressedSize
|
|
122
|
+
);
|
|
112
123
|
|
|
113
|
-
|
|
124
|
+
uncompressedFile = await compressionHandler(compressedFile);
|
|
125
|
+
}
|
|
114
126
|
|
|
115
127
|
const response = new Response(uncompressedFile);
|
|
116
|
-
Object.defineProperty(response, 'url', {
|
|
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';
|