@loaders.gl/tile-converter 5.0.0-alpha.11 → 5.0.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +178 -2
  2. package/bin/converter-v5.js +2 -0
  3. package/dist/converter.min.cjs +162 -163
  4. package/dist/i3s-server/bin/i3s-server.min.cjs +73 -73
  5. package/dist/index.cjs +1749 -2152
  6. package/dist/index.js +1748 -2162
  7. package/dist/v5/adapters.cjs +1550 -128
  8. package/dist/v5/adapters.d.ts +16 -0
  9. package/dist/v5/adapters.js +1558 -117
  10. package/dist/v5/archive-source.d.ts +36 -0
  11. package/dist/v5/browser-tileset-source.d.ts +55 -11
  12. package/dist/v5/browser.cjs +18 -0
  13. package/dist/v5/browser.d.ts +14 -0
  14. package/dist/v5/browser.js +26 -0
  15. package/dist/v5/conversion-api.d.ts +9 -0
  16. package/dist/v5/converter-cli.d.ts +1 -0
  17. package/dist/v5/converter-cli.js +1214 -0
  18. package/dist/v5/core.cjs +471 -60
  19. package/dist/v5/core.d.ts +2 -0
  20. package/dist/v5/core.js +471 -60
  21. package/dist/v5/i3s-mesh-conversion.d.ts +4 -0
  22. package/dist/v5/i3s-selection-source.d.ts +70 -0
  23. package/dist/v5/index.cjs +10 -0
  24. package/dist/v5/index.d.ts +8 -0
  25. package/dist/v5/index.js +14 -0
  26. package/dist/v5/mesh-conversion.d.ts +18 -0
  27. package/dist/v5/mesh-hierarchy.d.ts +47 -0
  28. package/dist/v5/mesh-source-features.d.ts +2 -1
  29. package/dist/v5/mesh-source-schema.d.ts +12 -0
  30. package/dist/v5/mesh-source.d.ts +5 -2
  31. package/dist/v5/mesh-tileset-sink.d.ts +5 -0
  32. package/dist/v5/node-cli.d.ts +9 -0
  33. package/dist/v5/node-conversion.d.ts +32 -0
  34. package/dist/v5/node-feature-schema.d.ts +3 -0
  35. package/dist/v5/node-i3s-source.d.ts +41 -0
  36. package/dist/v5/node-source.d.ts +47 -0
  37. package/dist/v5/node.cjs +900 -0
  38. package/dist/v5/node.d.ts +6 -0
  39. package/dist/v5/node.js +877 -0
  40. package/dist/v5/point-cloud-file.d.ts +83 -0
  41. package/dist/v5/point-cloud-potree.d.ts +47 -0
  42. package/dist/v5/point-cloud-tileset.d.ts +44 -0
  43. package/dist/v5/resource-manifest.d.ts +10 -1
  44. package/dist/v5/selected-mesh-source.d.ts +53 -0
  45. package/package.json +33 -25
  46. package/src/index.ts +4 -1
  47. package/src/v4/3d-tiles-converter/helpers/load-i3s.ts +2 -4
  48. package/src/v4/converter-cli.ts +8 -2
  49. package/src/v4/i3s-converter/helpers/load-3d-tiles.ts +3 -51
  50. package/src/v4/i3s-converter/helpers/node-index-document.ts +5 -2
  51. package/src/v4/i3s-converter/helpers/preprocess-3d-tiles.ts +1 -1
  52. package/src/v4/i3s-converter/json-templates/store.ts +2 -1
  53. package/src/v5/adapters.ts +48 -0
  54. package/src/v5/archive-source.ts +235 -0
  55. package/src/v5/browser-tileset-source.ts +418 -48
  56. package/src/v5/browser.ts +45 -0
  57. package/src/v5/conversion-api.ts +69 -9
  58. package/src/v5/converter-cli.ts +28 -0
  59. package/src/v5/core.ts +6 -0
  60. package/src/v5/i3s-mesh-conversion.ts +40 -2
  61. package/src/v5/i3s-mesh-sink.ts +1 -1
  62. package/src/v5/i3s-mesh-source.ts +1 -0
  63. package/src/v5/i3s-selection-source.ts +298 -0
  64. package/src/v5/index.ts +26 -0
  65. package/src/v5/mesh-conversion.ts +20 -0
  66. package/src/v5/mesh-hierarchy.ts +648 -0
  67. package/src/v5/mesh-source-features.ts +39 -7
  68. package/src/v5/mesh-source-schema.ts +134 -0
  69. package/src/v5/mesh-source.ts +16 -4
  70. package/src/v5/mesh-tileset-sink.ts +1 -1
  71. package/src/v5/node-cli.ts +197 -0
  72. package/src/v5/node-conversion.ts +345 -0
  73. package/src/v5/node-feature-schema.ts +155 -0
  74. package/src/v5/node-i3s-source.ts +181 -0
  75. package/src/v5/node-source.ts +328 -0
  76. package/src/v5/node.ts +16 -0
  77. package/src/v5/point-cloud-file.ts +306 -0
  78. package/src/v5/point-cloud-potree.ts +130 -0
  79. package/src/v5/point-cloud-tileset.ts +137 -0
  80. package/src/v5/resource-fetcher.ts +4 -1
  81. package/src/v5/resource-manifest.ts +40 -5
  82. package/src/v5/selected-mesh-source.ts +384 -0
  83. package/src/v5/spatial-conversion.ts +88 -17
package/dist/index.js CHANGED
@@ -1,28 +1,17 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __esm = (fn, res, err2) => function __init() {
6
- if (err2) throw err2[0];
3
+ var __esm = (fn, res, err) => function __init() {
4
+ if (err) throw err[0];
7
5
  try {
8
6
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
7
  } catch (e) {
10
- throw err2 = [e], e;
8
+ throw err = [e], e;
11
9
  }
12
10
  };
13
11
  var __export = (target, all) => {
14
12
  for (var name18 in all)
15
13
  __defProp(target, name18, { get: all[name18], enumerable: true });
16
14
  };
17
- var __copyProps = (to, from, except, desc) => {
18
- if (from && typeof from === "object" || typeof from === "function") {
19
- for (let key of __getOwnPropNames(from))
20
- if (!__hasOwnProp.call(to, key) && key !== except)
21
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
22
- }
23
- return to;
24
- };
25
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
26
15
 
27
16
  // ../../modules/loader-utils/src/loader-types.ts
28
17
  async function parseFromContext(data, loaders, options, context) {
@@ -141,6 +130,41 @@ var init_merge_options = __esm({
141
130
  }
142
131
  });
143
132
 
133
+ // ../../modules/loader-utils/src/lib/module-utils/initialize-wasm-module.ts
134
+ function initializeWasmModule(initialize, extractExports) {
135
+ return new Promise((resolve2, reject) => {
136
+ let isSettled = false;
137
+ function rejectInitialization(error) {
138
+ if (!isSettled) {
139
+ isSettled = true;
140
+ reject(error);
141
+ }
142
+ }
143
+ function resolveInitialization(module) {
144
+ if (isSettled) {
145
+ return;
146
+ }
147
+ isSettled = true;
148
+ try {
149
+ resolve2(extractExports(module));
150
+ } catch (error) {
151
+ reject(error);
152
+ }
153
+ }
154
+ try {
155
+ const modulePromise = initialize(resolveInitialization, rejectInitialization);
156
+ modulePromise?.then(resolveInitialization, rejectInitialization);
157
+ } catch (error) {
158
+ rejectInitialization(error);
159
+ }
160
+ });
161
+ }
162
+ var init_initialize_wasm_module = __esm({
163
+ "../../modules/loader-utils/src/lib/module-utils/initialize-wasm-module.ts"() {
164
+ "use strict";
165
+ }
166
+ });
167
+
144
168
  // ../../modules/loader-utils/src/lib/module-utils/js-module-utils.ts
145
169
  function registerJSModules(modules) {
146
170
  globalThis.loaders ||= {};
@@ -300,18 +324,11 @@ var init_worker_job = __esm({
300
324
  });
301
325
 
302
326
  // ../../modules/worker-utils/src/lib/node/worker_threads.ts
303
- var worker_threads_exports = {};
304
- __export(worker_threads_exports, {
305
- NodeWorker: () => NodeWorker,
306
- parentPort: () => parentPort
307
- });
308
327
  import * as WorkerThreads from "worker_threads";
309
- import * as worker_threads_star from "worker_threads";
310
328
  var parentPort, NodeWorker;
311
329
  var init_worker_threads = __esm({
312
330
  "../../modules/worker-utils/src/lib/node/worker_threads.ts"() {
313
331
  "use strict";
314
- __reExport(worker_threads_exports, worker_threads_star);
315
332
  parentPort = WorkerThreads?.parentPort;
316
333
  NodeWorker = WorkerThreads.Worker;
317
334
  }
@@ -1432,6 +1449,9 @@ var init_src = __esm({
1432
1449
 
1433
1450
  // ../../modules/loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
1434
1451
  function canParseWithWorker(loader, options) {
1452
+ const workerUrl = options?.[loader.id]?.workerUrl;
1453
+ if (options?.core?.worker === false || !(loader.worker || loader.loadWorker || workerUrl))
1454
+ return false;
1435
1455
  if (options?.core?.credentials?.some(
1436
1456
  (credential) => credential.type === "request" || "token" in credential && typeof credential.token === "function"
1437
1457
  ))
@@ -1562,12 +1582,14 @@ function resolveWorkerLoaders(loader, loaderIds, loaderIsArray, context, options
1562
1582
  }
1563
1583
  }
1564
1584
  function getWorkerOptions(options = {}, loader) {
1585
+ const optionsToSerialize = {
1586
+ ...options,
1587
+ ...options.core ? { core: { ...options.core, authentications: void 0 } } : {}
1588
+ };
1565
1589
  const serializedOptions = JSON.parse(
1566
- JSON.stringify({
1567
- ...options,
1568
- ...options.core ? { core: { ...options.core, authentications: void 0 } } : {}
1569
- })
1590
+ JSON.stringify(optionsToSerialize, (_key, value) => typeof value === "bigint" ? null : value)
1570
1591
  );
1592
+ restoreBigIntOptions(optionsToSerialize, serializedOptions);
1571
1593
  const workerOptions = {
1572
1594
  ...serializedOptions.core,
1573
1595
  ...serializedOptions
@@ -1580,6 +1602,14 @@ function getWorkerOptions(options = {}, loader) {
1580
1602
  }
1581
1603
  return workerOptions;
1582
1604
  }
1605
+ function restoreBigIntOptions(original, serialized) {
1606
+ if (!serialized || typeof serialized !== "object") return;
1607
+ for (const key of Object.keys(serialized)) {
1608
+ const value = original?.[key];
1609
+ if (typeof value === "bigint") serialized[key] = value;
1610
+ else restoreBigIntOptions(value, serialized[key]);
1611
+ }
1612
+ }
1583
1613
  function getSerializableLoaderContext(context) {
1584
1614
  if (!context) {
1585
1615
  return {};
@@ -3767,6 +3797,7 @@ var init_src2 = __esm({
3767
3797
  init_log();
3768
3798
  init_is_type();
3769
3799
  init_merge_options();
3800
+ init_initialize_wasm_module();
3770
3801
  init_js_module_utils();
3771
3802
  init_js_module_utils();
3772
3803
  init_parse_with_worker();
@@ -6307,6 +6338,7 @@ function convertArrowTableToMesh(table) {
6307
6338
  const schema = serializeArrowSchema(arrowTable.schema);
6308
6339
  const fields = schema.fields;
6309
6340
  const attributes = {};
6341
+ const columns = [];
6310
6342
  for (const field of fields) {
6311
6343
  const { name: name18 } = field;
6312
6344
  if (name18 === "indices") {
@@ -6316,11 +6348,16 @@ function convertArrowTableToMesh(table) {
6316
6348
  const size = getFixedSizeListSize(attributeData);
6317
6349
  const typedArray = getAttributeTypedArray(attributeData, size);
6318
6350
  const metadata = getMeshAttributeMetadata(field.metadata);
6351
+ const value = metadata.componentType === "float16" ? restoreFloat16Array(typedArray) : typedArray;
6352
+ const shared = columns.find(
6353
+ (column) => column.data.length === attributeData.data.length && attributes[column.name].value.constructor === value.constructor && column.data.every((chunk, index) => shareArrowStorage(chunk, attributeData.data[index]))
6354
+ );
6319
6355
  attributes[name18] = {
6320
- value: metadata.componentType === "float16" ? restoreFloat16Array(typedArray) : typedArray,
6356
+ value: shared ? attributes[shared.name].value : value,
6321
6357
  size,
6322
6358
  ...metadata
6323
6359
  };
6360
+ if (!shared) columns.push({ name: name18, data: attributeData.data });
6324
6361
  }
6325
6362
  fixMetadata(schema);
6326
6363
  const topology = schema.metadata.topology;
@@ -6437,6 +6474,15 @@ function getIndices(arrowTable) {
6437
6474
  const values = indicesData.children[0].values.subarray(start, end);
6438
6475
  return { value: values, size: 1 };
6439
6476
  }
6477
+ function shareArrowStorage(left, right) {
6478
+ const rightBuffers = Object.values(right.buffers);
6479
+ return left.type.toString() === right.type.toString() && left.offset === right.offset && left.length === right.length && left.nullCount === right.nullCount && left.dictionary === right.dictionary && Object.values(left.buffers).every((buffer, index) => {
6480
+ const other = rightBuffers[index];
6481
+ return buffer === other || Boolean(
6482
+ buffer && other && buffer.buffer === other.buffer && buffer.byteOffset === other.byteOffset && buffer.byteLength === other.byteLength
6483
+ );
6484
+ }) && left.children.length === right.children.length && left.children.every((child, index) => shareArrowStorage(child, right.children[index]));
6485
+ }
6440
6486
  var init_convert_table_to_mesh = __esm({
6441
6487
  "../../modules/schema-utils/src/lib/mesh/convert-table-to-mesh.ts"() {
6442
6488
  "use strict";
@@ -6589,8 +6635,8 @@ function convertDataToBatch(parsedData, loader) {
6589
6635
  }
6590
6636
  async function applyInputTransforms(inputIterator, transforms = []) {
6591
6637
  let iteratorChain = inputIterator;
6592
- for await (const transformBatches of transforms) {
6593
- iteratorChain = transformBatches(iteratorChain);
6638
+ for await (const transformBatches2 of transforms) {
6639
+ iteratorChain = transformBatches2(iteratorChain);
6594
6640
  }
6595
6641
  return iteratorChain;
6596
6642
  }
@@ -9943,16 +9989,16 @@ function encodeExtMeshFeaturesForPrimitive(scenegraph, primitive) {
9943
9989
  function createAccessorKey(attributes) {
9944
9990
  const prefix = "_FEATURE_ID_";
9945
9991
  const attrs = Object.keys(attributes).filter((item) => item.indexOf(prefix) === 0);
9946
- let max2 = -1;
9992
+ let max = -1;
9947
9993
  for (const a of attrs) {
9948
9994
  const n = Number(a.substring(prefix.length));
9949
- if (n > max2) {
9950
- max2 = n;
9995
+ if (n > max) {
9996
+ max = n;
9951
9997
  }
9952
9998
  }
9953
- max2++;
9954
- const accessorKey = `${prefix}${max2}`;
9955
- return { accessorKey, index: max2 };
9999
+ max++;
10000
+ const accessorKey = `${prefix}${max}`;
10001
+ return { accessorKey, index: max };
9956
10002
  }
9957
10003
  var EXT_MESH_FEATURES_NAME, name;
9958
10004
  var init_EXT_mesh_features = __esm({
@@ -11866,8 +11912,9 @@ function initializeBasisTranscoderModule(BasisModule, wasmBinary) {
11866
11912
  if (wasmBinary) {
11867
11913
  options.wasmBinary = wasmBinary;
11868
11914
  }
11869
- return new Promise((resolve2) => {
11870
- BasisModule(options).then((module) => {
11915
+ return initializeWasmModule(
11916
+ () => BasisModule(options),
11917
+ (module) => {
11871
11918
  const {
11872
11919
  BasisFile,
11873
11920
  KTX2File,
@@ -11877,15 +11924,15 @@ function initializeBasisTranscoderModule(BasisModule, wasmBinary) {
11877
11924
  isFormatSupported
11878
11925
  } = module;
11879
11926
  initializeBasis();
11880
- resolve2({
11927
+ return {
11881
11928
  BasisFile,
11882
11929
  KTX2File,
11883
11930
  getBasisTexFormatBlockHeight,
11884
11931
  getBasisTexFormatBlockWidth,
11885
11932
  isFormatSupported
11886
- });
11887
- });
11888
- });
11933
+ };
11934
+ }
11935
+ );
11889
11936
  }
11890
11937
  var BASIS_EXTERNAL_LIBRARIES, loadBasisTranscoderPromise;
11891
11938
  var init_basis_module_loader = __esm({
@@ -13143,7 +13190,6 @@ var init_src7 = __esm({
13143
13190
  init_version4();
13144
13191
  init_basis_loader();
13145
13192
  init_compressed_texture_loader();
13146
- init_gl_extensions();
13147
13193
  KTX2BasisWriterWorker = {
13148
13194
  name: "Basis Universal Supercompressed GPU Texture",
13149
13195
  id: "ktx2-basis-writer",
@@ -13675,7 +13721,10 @@ async function loadDracoDecoderModuleFromDraco3D(draco3DModule) {
13675
13721
  const typedDraco3DModule = validateDracoDecoderModule(draco3DModule);
13676
13722
  let decoderPromise = injectedDecoderPromises.get(typedDraco3DModule);
13677
13723
  if (!decoderPromise) {
13678
- decoderPromise = typedDraco3DModule.createDecoderModule({}).then((draco) => ({ draco }));
13724
+ decoderPromise = initializeWasmModule(
13725
+ () => typedDraco3DModule.createDecoderModule({}),
13726
+ (draco) => ({ draco })
13727
+ );
13679
13728
  injectedDecoderPromises.set(typedDraco3DModule, decoderPromise);
13680
13729
  }
13681
13730
  return await decoderPromise;
@@ -13686,7 +13735,10 @@ async function loadDracoEncoderModule(options = {}) {
13686
13735
  const typedDraco3DModule = validateDracoEncoderModule(draco3DModule);
13687
13736
  let encoderPromise2 = injectedEncoderPromises.get(typedDraco3DModule);
13688
13737
  if (!encoderPromise2) {
13689
- encoderPromise2 = typedDraco3DModule.createEncoderModule({}).then((draco) => ({ draco }));
13738
+ encoderPromise2 = initializeWasmModule(
13739
+ () => typedDraco3DModule.createEncoderModule({}),
13740
+ (draco) => ({ draco })
13741
+ );
13690
13742
  injectedEncoderPromises.set(typedDraco3DModule, encoderPromise2);
13691
13743
  }
13692
13744
  return await encoderPromise2;
@@ -13816,17 +13868,13 @@ function initializeDracoModule(initializer, wasmBinary) {
13816
13868
  if (typeof initializer !== "function") {
13817
13869
  throw new Error("Draco module initializer could not be loaded");
13818
13870
  }
13819
- return new Promise((resolve2, reject) => {
13820
- try {
13821
- const modulePromise = initializer({
13822
- ...wasmBinary ? { wasmBinary } : {},
13823
- onModuleLoaded: (draco) => resolve2({ draco })
13824
- });
13825
- modulePromise?.then((draco) => resolve2({ draco }), reject);
13826
- } catch (error) {
13827
- reject(error);
13828
- }
13829
- });
13871
+ return initializeWasmModule(
13872
+ (onInitialized) => initializer({
13873
+ ...wasmBinary ? { wasmBinary } : {},
13874
+ onModuleLoaded: onInitialized
13875
+ }),
13876
+ (draco) => ({ draco })
13877
+ );
13830
13878
  }
13831
13879
  function getLibraryExport(library, exportName) {
13832
13880
  if (typeof library === "function") {
@@ -13876,6 +13924,7 @@ var DRACO_VERSION, DRACO_RELEASE_COMMIT, STATIC_DECODER_URL, STATIC_ENCODER_URL,
13876
13924
  var init_draco_module_loader = __esm({
13877
13925
  "../../modules/draco/src/lib/draco-module-loader.ts"() {
13878
13926
  "use strict";
13927
+ init_src2();
13879
13928
  init_draco_library_loader();
13880
13929
  DRACO_VERSION = "1.5.7";
13881
13930
  DRACO_RELEASE_COMMIT = "8786740086a9f4d83f44aa83badfbea4dce7a1b5";
@@ -13972,13 +14021,13 @@ function hasAttributeQuantization(options) {
13972
14021
  options.attributeQuantization && Object.keys(options.attributeQuantization).length
13973
14022
  );
13974
14023
  }
13975
- function validateQuantizationBits(attributeName, bits2, attributeType) {
13976
- if (!Number.isInteger(bits2) || bits2 < 1 || bits2 > 30) {
14024
+ function validateQuantizationBits(attributeName, bits, attributeType) {
14025
+ if (!Number.isInteger(bits) || bits < 1 || bits > 30) {
13977
14026
  throw new Error(
13978
14027
  `DracoWriter: quantization bits for "${attributeName}" must be an integer from 1 to 30`
13979
14028
  );
13980
14029
  }
13981
- if (attributeType === "NORMAL" && (bits2 < 2 || bits2 > 29)) {
14030
+ if (attributeType === "NORMAL" && (bits < 2 || bits > 29)) {
13982
14031
  throw new Error(
13983
14032
  `DracoWriter: quantization bits for NORMAL attribute "${attributeName}" must be an integer from 2 to 29`
13984
14033
  );
@@ -14217,10 +14266,10 @@ var init_draco_builder = __esm({
14217
14266
  if (options.quantization) {
14218
14267
  for (const attribute in options.quantization) {
14219
14268
  const attributeType = attribute;
14220
- const bits2 = options.quantization[attributeType];
14221
- if (bits2 !== void 0) {
14222
- validateQuantizationBits(attributeType, bits2, attributeType);
14223
- this.dracoEncoder.SetAttributeQuantization(this.draco[attributeType], bits2);
14269
+ const bits = options.quantization[attributeType];
14270
+ if (bits !== void 0) {
14271
+ validateQuantizationBits(attributeType, bits, attributeType);
14272
+ this.dracoEncoder.SetAttributeQuantization(this.draco[attributeType], bits);
14224
14273
  }
14225
14274
  }
14226
14275
  }
@@ -14253,17 +14302,17 @@ var init_draco_builder = __esm({
14253
14302
  _getAttributeQuantization(attributes, options) {
14254
14303
  const categoryQuantization = /* @__PURE__ */ new Map();
14255
14304
  for (const attributeType of Object.keys(options.quantization || {})) {
14256
- const bits2 = options.quantization?.[attributeType];
14257
- if (bits2 !== void 0) {
14258
- validateQuantizationBits(attributeType, bits2, attributeType);
14259
- categoryQuantization.set(this.draco[attributeType], bits2);
14305
+ const bits = options.quantization?.[attributeType];
14306
+ if (bits !== void 0) {
14307
+ validateQuantizationBits(attributeType, bits, attributeType);
14308
+ categoryQuantization.set(this.draco[attributeType], bits);
14260
14309
  }
14261
14310
  }
14262
14311
  const quantization = /* @__PURE__ */ new Map();
14263
14312
  for (const [attributeName, attribute] of Object.entries(attributes)) {
14264
- const bits2 = categoryQuantization.get(attribute.attributeType);
14265
- if (bits2 !== void 0) {
14266
- quantization.set(attributeName, bits2);
14313
+ const bits = categoryQuantization.get(attribute.attributeType);
14314
+ if (bits !== void 0) {
14315
+ quantization.set(attributeName, bits);
14267
14316
  }
14268
14317
  }
14269
14318
  for (const [attributeName, setting] of Object.entries(options.attributeQuantization || {})) {
@@ -15045,8 +15094,8 @@ function getTransformedMeshBoundingBox(attributes) {
15045
15094
  if (position?.transform?.type !== "quantization") {
15046
15095
  return boundingBox;
15047
15096
  }
15048
- const { bits: bits2, origin, range } = position.transform;
15049
- const scale = range / (2 ** bits2 - 1);
15097
+ const { bits, origin, range } = position.transform;
15098
+ const scale = range / (2 ** bits - 1);
15050
15099
  return boundingBox.map(
15051
15100
  (bounds) => bounds.map((value, componentIndex) => origin[componentIndex] + value * scale)
15052
15101
  );
@@ -20747,6 +20796,7 @@ var init_spatial_resource_registry = __esm({
20747
20796
  // ../../modules/tiles/src/spatial/spatial-coordinate-transformer.ts
20748
20797
  import { Vector3 as Vector34 } from "@math.gl/core";
20749
20798
  import { Ellipsoid as Ellipsoid2 } from "@math.gl/geospatial";
20799
+ import { ProjectionBuffer } from "@math.gl/projection/bulk";
20750
20800
  function getFiniteDifferenceJacobian(transformer, position, epsilon) {
20751
20801
  const columns = [];
20752
20802
  for (let axis = 0; axis < 3; axis++) {
@@ -20859,6 +20909,8 @@ var init_spatial_coordinate_transformer = __esm({
20859
20909
  spatialReference;
20860
20910
  /** Projection from the source CRS directly to the requested horizontal target CRS. */
20861
20911
  horizontalProjection;
20912
+ /** Reusable packed xyz projection for horizontal-only coordinate batches. */
20913
+ horizontalProjectionBuffer;
20862
20914
  /** Projection from the source CRS to geographic longitude, latitude, and ellipsoidal height. */
20863
20915
  geographicProjection;
20864
20916
  /** Projection from adjusted geographic coordinates to the requested output CRS. */
@@ -20894,6 +20946,12 @@ var init_spatial_coordinate_transformer = __esm({
20894
20946
  to: getHorizontalProjectionDefinition(spatialReference.targetCrs),
20895
20947
  enforceAxis: false
20896
20948
  });
20949
+ if (!requiresHeightTransformation(spatialReference)) {
20950
+ this.horizontalProjectionBuffer = new ProjectionBuffer({
20951
+ projection: this.horizontalProjection,
20952
+ dimension: 3
20953
+ });
20954
+ }
20897
20955
  }
20898
20956
  if (requiresHeightTransformation(spatialReference) || this.sourceIsGeocentric || this.outputIsGeocentric) {
20899
20957
  if (!this.sourceIsGeographic && !this.sourceIsGeocentric) {
@@ -20956,12 +21014,21 @@ var init_spatial_coordinate_transformer = __esm({
20956
21014
  }
20957
21015
  return result;
20958
21016
  }
20959
- /** Transform a packed sequence of xyz positions, preserving the input array type only when safe. */
21017
+ /** Transform packed xyz positions into owned Float64 storage, batching finite horizontal transforms. */
20960
21018
  transformPositions(positions) {
20961
21019
  if (positions.length % 3 !== 0) {
20962
21020
  throw new Error("Packed spatial positions must contain a multiple of three components");
20963
21021
  }
20964
21022
  const transformedPositions = new Float64Array(positions.length);
21023
+ if (this.horizontalProjectionBuffer) {
21024
+ transformedPositions.set(positions);
21025
+ if (transformedPositions.every(Number.isFinite)) {
21026
+ return this.horizontalProjectionBuffer.projectFlatTo(
21027
+ transformedPositions,
21028
+ transformedPositions
21029
+ );
21030
+ }
21031
+ }
20965
21032
  for (let index = 0; index < positions.length; index += 3) {
20966
21033
  const transformed = this.transformPosition([
20967
21034
  Number(positions[index]),
@@ -25799,6 +25866,152 @@ var init_cesium_ion_loader = __esm({
25799
25866
  }
25800
25867
  });
25801
25868
 
25869
+ // ../../modules/compression/src/lib/compression.ts
25870
+ var CompressionTransform, Decompressor;
25871
+ var init_compression = __esm({
25872
+ "../../modules/compression/src/lib/compression.ts"() {
25873
+ "use strict";
25874
+ init_src2();
25875
+ CompressionTransform = class {
25876
+ /** Preloads any dynamic libraries. May enable sync functions */
25877
+ async preload(modules = {}) {
25878
+ registerJSModules(modules);
25879
+ return void 0;
25880
+ }
25881
+ // HELPERS
25882
+ concatenate(asyncIterator) {
25883
+ return concatenateArrayBuffersAsync(asyncIterator);
25884
+ }
25885
+ improveError(error) {
25886
+ if (!error.message.includes(this.name)) {
25887
+ error.message = `${this.name} ${error.message}`;
25888
+ }
25889
+ return error;
25890
+ }
25891
+ };
25892
+ Decompressor = class extends CompressionTransform {
25893
+ constructor(options) {
25894
+ super();
25895
+ this.decompressBatches = this.decompressBatches.bind(this);
25896
+ }
25897
+ /** Asynchronously decompresses data. */
25898
+ async decompress(input, size) {
25899
+ await this.preload();
25900
+ return this.decompressSync(input, size);
25901
+ }
25902
+ /** Synchronously decompresses data. */
25903
+ decompressSync(input, size) {
25904
+ throw new Error(`${this.name}: sync decompression not supported`);
25905
+ }
25906
+ /** Decompresses batches. */
25907
+ async *decompressBatches(asyncIterator) {
25908
+ const input = await this.concatenate(asyncIterator);
25909
+ yield this.decompress(input);
25910
+ }
25911
+ };
25912
+ }
25913
+ });
25914
+
25915
+ // ../../modules/compression/src/lib/compress-utils-compression.ts
25916
+ async function* transformBatches(stream, inputBatches) {
25917
+ try {
25918
+ for await (const input of inputBatches) {
25919
+ const output2 = stream.write(new Uint8Array(input));
25920
+ if (output2.byteLength > 0) yield copyArrayBuffer2(output2);
25921
+ }
25922
+ const output = stream.finish();
25923
+ if (output.byteLength > 0) yield copyArrayBuffer2(output);
25924
+ } finally {
25925
+ stream.destroy();
25926
+ }
25927
+ }
25928
+ function copyArrayBuffer2(bytes) {
25929
+ return bytes.slice().buffer;
25930
+ }
25931
+ function getDecompressOptions(options, size) {
25932
+ const decodeOptions = {
25933
+ ...options.compressUtils,
25934
+ ...size === void 0 ? {} : { expectedSize: size }
25935
+ };
25936
+ const capacity = decodeOptions.expectedSize;
25937
+ const maximum = options.maxOutputByteLength ?? 512 * 1024 * 1024;
25938
+ if (!Number.isSafeInteger(maximum) || maximum < 0 || maximum > 2147483647)
25939
+ throw new RangeError("Invalid maxOutputByteLength");
25940
+ if (capacity !== void 0 && (!Number.isSafeInteger(capacity) || capacity < 0 || capacity > maximum)) {
25941
+ throw new RangeError("expectedSize exceeds the configured output capacity limit");
25942
+ }
25943
+ return decodeOptions;
25944
+ }
25945
+ var CompressUtilsDecompressor;
25946
+ var init_compress_utils_compression = __esm({
25947
+ "../../modules/compression/src/lib/compress-utils-compression.ts"() {
25948
+ "use strict";
25949
+ init_compression();
25950
+ CompressUtilsDecompressor = class extends Decompressor {
25951
+ name;
25952
+ extensions;
25953
+ contentEncodings;
25954
+ isSupported = true;
25955
+ options;
25956
+ loadModule;
25957
+ /** Module initialized for synchronous operations. */
25958
+ module = null;
25959
+ /** Shared import and WASM initialization for concurrent callers. */
25960
+ modulePromise = null;
25961
+ /** Creates a format-specific compress-utils decoder. */
25962
+ constructor(metadata, loadModule, options = {}) {
25963
+ super(options);
25964
+ this.name = metadata.name;
25965
+ this.extensions = metadata.extensions || [];
25966
+ this.contentEncodings = metadata.contentEncodings || [];
25967
+ this.loadModule = loadModule;
25968
+ this.options = options;
25969
+ }
25970
+ /** Imports and initializes the codec without loading the opposite direction. */
25971
+ async preload(modules = {}) {
25972
+ await super.preload(modules);
25973
+ this.modulePromise ||= this.loadModule().then(async (module) => {
25974
+ await module.preload?.();
25975
+ this.module = module;
25976
+ });
25977
+ try {
25978
+ await this.modulePromise;
25979
+ } catch (error) {
25980
+ this.modulePromise = null;
25981
+ throw error;
25982
+ }
25983
+ }
25984
+ /** Runs synchronously after preload has initialized the WASM codec. */
25985
+ decompressSync(input, size) {
25986
+ if (!this.module?.decompressSync)
25987
+ throw new Error(`${this.name}: call preload() before decompressSync()`);
25988
+ return copyArrayBuffer2(
25989
+ this.module.decompressSync(new Uint8Array(input), getDecompressOptions(this.options, size))
25990
+ );
25991
+ }
25992
+ /** Decompresses one buffer with the selected compress-utils decoder. */
25993
+ async decompress(input, size) {
25994
+ const decodeOptions = getDecompressOptions(this.options, size);
25995
+ await this.preload();
25996
+ const module = this.module;
25997
+ const output = await module.decompress(new Uint8Array(input), decodeOptions);
25998
+ return copyArrayBuffer2(output);
25999
+ }
26000
+ /** Incrementally decompresses input batches with compress-utils. */
26001
+ async *decompressBatches(inputBatches) {
26002
+ await this.preload();
26003
+ const module = this.module;
26004
+ if (!module.createDecompressStream) {
26005
+ yield await this.decompress(await this.concatenate(inputBatches));
26006
+ return;
26007
+ }
26008
+ const stream = await module.createDecompressStream();
26009
+ yield* transformBatches(stream, inputBatches);
26010
+ }
26011
+ };
26012
+ }
26013
+ });
26014
+
25802
26015
  // ../../modules/crypto/src/lib/hash.ts
25803
26016
  var Hash;
25804
26017
  var init_hash = __esm({
@@ -26255,65 +26468,25 @@ var init_crc32_hash = __esm({
26255
26468
  });
26256
26469
 
26257
26470
  // ../../modules/crypto/src/lib/algorithms/md5-wasm.ts
26258
- function md5WASM(data) {
26259
- var mem, memView, importObj, imports, len, buff, thenFun, catchFun, result, endTime;
26260
- const md5JS = makeMD5JS(), md5WA = makeMD5WA(), returnObj = {}, startTime = (/* @__PURE__ */ new Date()).getTime();
26261
- returnObj["then"] = function(fun) {
26262
- thenFun = fun;
26263
- getThen();
26264
- return returnObj;
26265
- };
26266
- returnObj["catch"] = function(fun) {
26267
- catchFun = fun;
26268
- return returnObj;
26269
- };
26270
- buff = normalizeInput(data);
26271
- if (!buff) {
26272
- getCatch(new TypeError(parmTypeErrStr));
26273
- }
26274
- if (buff) {
26275
- len = buff.length;
26276
- if (wasm && len > bounder) {
26277
- if (len > upperLimit) {
26278
- getCatch(new Error(tooBigErrStr));
26279
- } else {
26280
- mem = new WebAssembly.Memory({
26281
- initial: len > 32e6 ? len > 64e6 ? len > 128e6 ? 4096 : 2048 : 1024 : 512
26282
- });
26283
- memView = new Uint32Array(mem.buffer);
26284
- imports = { mem, log: console.log };
26285
- importObj = { imports };
26286
- WebAssembly.instantiate(wasm, importObj).then(giterdone);
26287
- }
26288
- } else {
26289
- getThen(md5JS(buff));
26290
- }
26471
+ async function md5WASM(data) {
26472
+ const input = normalizeInput(data);
26473
+ if (!input) {
26474
+ throw new TypeError(parmTypeErrStr);
26291
26475
  }
26292
- return returnObj;
26293
- function giterdone(obj) {
26294
- getThen(md5WA(buff, obj.instance.exports, memView));
26476
+ if (!wasm || input.length <= bounder) {
26477
+ return makeMD5JS()(input);
26295
26478
  }
26296
- function getThen(r) {
26297
- var res = Boolean(r) ? r : result;
26298
- if (Boolean(r)) {
26299
- endTime = (/* @__PURE__ */ new Date()).getTime();
26300
- }
26301
- if (typeof thenFun === "function") {
26302
- if (Boolean(res)) {
26303
- thenFun(res, endTime - startTime);
26304
- thenFun = catchFun = null;
26305
- }
26306
- } else {
26307
- if (Boolean(r)) {
26308
- result = r;
26309
- }
26310
- }
26311
- }
26312
- function getCatch(err2) {
26313
- if (typeof catchFun === "function") {
26314
- catchFun(err2);
26315
- }
26479
+ if (input.length > upperLimit) {
26480
+ throw new Error(tooBigErrStr);
26316
26481
  }
26482
+ const memory = new WebAssembly.Memory({
26483
+ initial: input.length > 32e6 ? input.length > 64e6 ? input.length > 128e6 ? 4096 : 2048 : 1024 : 512
26484
+ });
26485
+ const memoryView = new Uint32Array(memory.buffer);
26486
+ const { instance } = await WebAssembly.instantiate(wasm, {
26487
+ imports: { mem: memory, log: console.log }
26488
+ });
26489
+ return makeMD5WA()(input, instance.exports, memoryView);
26317
26490
  }
26318
26491
  function makeMD5WA() {
26319
26492
  var _loop, loops;
@@ -26714,13 +26887,7 @@ var init_md5_hash = __esm({
26714
26887
  * @returns base64 encoded hash
26715
26888
  */
26716
26889
  async hash(input, encoding) {
26717
- const md5Promise = new Promise(
26718
- (resolve2, reject) => (
26719
- // @ts-expect-error
26720
- md5WASM(input).then(resolve2).catch(reject)
26721
- )
26722
- );
26723
- const hex = await md5Promise;
26890
+ const hex = await md5WASM(input);
26724
26891
  return encodeHex(hex, encoding);
26725
26892
  }
26726
26893
  };
@@ -26736,442 +26903,7 @@ var init_src11 = __esm({
26736
26903
  }
26737
26904
  });
26738
26905
 
26739
- // ../../modules/zip/src/parse-zip/readable-file-utils.ts
26740
- function toBigInt(value) {
26741
- return typeof value === "bigint" ? value : BigInt(value);
26742
- }
26743
- function toNumber(value) {
26744
- const numberValue = Number(value);
26745
- if (!Number.isFinite(numberValue)) {
26746
- throw new Error("Offset is out of bounds");
26747
- }
26748
- return numberValue;
26749
- }
26750
- function normalizeOffset2(offset, size) {
26751
- if (offset < 0) {
26752
- return Math.max(size + offset, 0);
26753
- }
26754
- return Math.min(offset, size);
26755
- }
26756
- async function readRange(file, start, end) {
26757
- const startOffset = toBigInt(start);
26758
- const endOffset = toBigInt(end);
26759
- const length = endOffset - startOffset;
26760
- if (length < 0) {
26761
- throw new Error("Invalid range requested");
26762
- }
26763
- return await file.read(startOffset, toNumber(length));
26764
- }
26765
- async function readDataView(file, start, end) {
26766
- const arrayBuffer = await readRange(file, start, end);
26767
- return new DataView(arrayBuffer);
26768
- }
26769
- async function readUint16(file, offset) {
26770
- const dataView = await readDataView(file, offset, toBigInt(offset) + 2n);
26771
- return dataView.getUint16(0, true);
26772
- }
26773
- async function readUint32(file, offset) {
26774
- const dataView = await readDataView(file, offset, toBigInt(offset) + 4n);
26775
- return dataView.getUint32(0, true);
26776
- }
26777
- async function readBigUint64(file, offset) {
26778
- const dataView = await readDataView(file, offset, toBigInt(offset) + 8n);
26779
- return dataView.getBigUint64(0, true);
26780
- }
26781
- async function getReadableFileSize(file) {
26782
- if (file.bigsize > 0n) {
26783
- return file.bigsize;
26784
- }
26785
- if (file.size > 0) {
26786
- return BigInt(file.size);
26787
- }
26788
- if (file.stat) {
26789
- const stats = await file.stat();
26790
- if (stats?.bigsize !== void 0) {
26791
- return stats.bigsize;
26792
- }
26793
- if (stats?.size !== void 0) {
26794
- return BigInt(stats.size);
26795
- }
26796
- }
26797
- return 0n;
26798
- }
26799
- var DataViewReadableFile;
26800
- var init_readable_file_utils = __esm({
26801
- "../../modules/zip/src/parse-zip/readable-file-utils.ts"() {
26802
- "use strict";
26803
- init_src2();
26804
- DataViewReadableFile = class {
26805
- handle;
26806
- size;
26807
- bigsize;
26808
- url;
26809
- constructor(dataView, url = "") {
26810
- this.handle = dataView;
26811
- this.size = dataView.byteLength;
26812
- this.bigsize = BigInt(dataView.byteLength);
26813
- this.url = url;
26814
- }
26815
- async close() {
26816
- }
26817
- async stat() {
26818
- return { size: this.size, bigsize: this.bigsize, isDirectory: false };
26819
- }
26820
- async read(start = 0, length) {
26821
- const offset = toNumber(start);
26822
- const end = length ? offset + length : this.size;
26823
- const normalizedStart = normalizeOffset2(offset, this.size);
26824
- const normalizedEnd = normalizeOffset2(end, this.size);
26825
- const clampedEnd = Math.max(normalizedEnd, normalizedStart);
26826
- const lengthToRead = clampedEnd - normalizedStart;
26827
- if (lengthToRead <= 0) {
26828
- return new ArrayBuffer(0);
26829
- }
26830
- return copyToArrayBuffer2(this.handle.buffer, normalizedStart, lengthToRead);
26831
- }
26832
- };
26833
- }
26834
- });
26835
-
26836
- // ../../modules/zip/src/parse-zip/search-from-the-end.ts
26837
- var buffLength, searchFromTheEnd;
26838
- var init_search_from_the_end = __esm({
26839
- "../../modules/zip/src/parse-zip/search-from-the-end.ts"() {
26840
- "use strict";
26841
- init_readable_file_utils();
26842
- buffLength = 1024;
26843
- searchFromTheEnd = async (file, target) => {
26844
- const fileLength = await getReadableFileSize(file);
26845
- if (fileLength < BigInt(target.length)) {
26846
- return -1n;
26847
- }
26848
- const lastBytes = new Uint8Array(await readRange(file, fileLength - 3n, fileLength));
26849
- const searchWindow = [lastBytes[0], lastBytes[1], lastBytes[2], void 0];
26850
- let targetOffset = -1;
26851
- let point = fileLength - 3n;
26852
- do {
26853
- const prevPoint = point;
26854
- point -= BigInt(buffLength);
26855
- point = point >= 0n ? point : 0n;
26856
- const buff = new Uint8Array(await readRange(file, point, prevPoint));
26857
- for (let i = buff.length - 1; i > -1; i--) {
26858
- searchWindow[3] = searchWindow[2];
26859
- searchWindow[2] = searchWindow[1];
26860
- searchWindow[1] = searchWindow[0];
26861
- searchWindow[0] = buff[i];
26862
- if (searchWindow.every((val, index) => val === target[index])) {
26863
- targetOffset = i;
26864
- break;
26865
- }
26866
- }
26867
- } while (targetOffset === -1 && point > 0n);
26868
- return point + BigInt(targetOffset);
26869
- };
26870
- }
26871
- });
26872
-
26873
- // ../../modules/zip/src/parse-zip/zip64-info-generation.ts
26874
- function createZip64Info(options) {
26875
- const optionsToUse = {
26876
- ...options,
26877
- zip64Length: (options.offset ? 1 : 0) * 8 + (options.size ? 1 : 0) * 16
26878
- };
26879
- const arraysToConcat = [];
26880
- for (const field of ZIP64_FIELDS) {
26881
- if (!optionsToUse[field.name ?? ""] && !field.default) {
26882
- continue;
26883
- }
26884
- const newValue = new DataView(new ArrayBuffer(field.size));
26885
- NUMBER_SETTERS[field.size](newValue, 0, optionsToUse[field.name ?? ""] ?? field.default);
26886
- arraysToConcat.push(newValue.buffer);
26887
- }
26888
- return concatenateArrayBuffers(...arraysToConcat);
26889
- }
26890
- function setFieldToNumber(header, fieldSize, fieldOffset, value) {
26891
- NUMBER_SETTERS[fieldSize](header, Number(fieldOffset), value);
26892
- }
26893
- var signature, NUMBER_SETTERS, ZIP64_FIELDS;
26894
- var init_zip64_info_generation = __esm({
26895
- "../../modules/zip/src/parse-zip/zip64-info-generation.ts"() {
26896
- "use strict";
26897
- init_src2();
26898
- signature = new Uint8Array([1, 0]);
26899
- NUMBER_SETTERS = {
26900
- 2: (header, offset, value) => {
26901
- header.setUint16(offset, Number(value > 65535 ? 65535 : value), true);
26902
- },
26903
- 4: (header, offset, value) => {
26904
- header.setUint32(offset, Number(value > 4294967295 ? 4294967295 : value), true);
26905
- },
26906
- 8: (header, offset, value) => {
26907
- header.setBigUint64(offset, BigInt(value), true);
26908
- }
26909
- };
26910
- ZIP64_FIELDS = [
26911
- // Header ID 0x0001
26912
- {
26913
- size: 2,
26914
- default: new DataView(signature.buffer).getUint16(0, true)
26915
- },
26916
- // Size of the extra field chunk (8, 16, 24 or 28)
26917
- {
26918
- size: 2,
26919
- name: "zip64Length"
26920
- },
26921
- // Original uncompressed file size
26922
- {
26923
- size: 8,
26924
- name: "size"
26925
- },
26926
- // Size of compressed data
26927
- {
26928
- size: 8,
26929
- name: "size"
26930
- },
26931
- // Offset of local header record
26932
- {
26933
- size: 8,
26934
- name: "offset"
26935
- }
26936
- ];
26937
- }
26938
- });
26939
-
26940
- // ../../modules/zip/src/parse-zip/end-of-central-directory.ts
26941
- function generateEoCD(options) {
26942
- const header = new DataView(new ArrayBuffer(Number(CD_COMMENT_OFFSET)));
26943
- for (const field of EOCD_FIELDS) {
26944
- setFieldToNumber(
26945
- header,
26946
- field.size,
26947
- field.offset,
26948
- options[field.name ?? ""] ?? field.default ?? 0
26949
- );
26950
- }
26951
- const locator = generateZip64InfoLocator(options);
26952
- const zip64Record = generateZip64Info(options);
26953
- return concatenateArrayBuffers(zip64Record, locator, header.buffer);
26954
- }
26955
- function generateZip64Info(options) {
26956
- const record = new DataView(new ArrayBuffer(Number(ZIP64_COMMENT_OFFSET)));
26957
- for (const field of ZIP64_EOCD_FIELDS) {
26958
- setFieldToNumber(
26959
- record,
26960
- field.size,
26961
- field.offset,
26962
- options[field.name ?? ""] ?? field.default ?? 0
26963
- );
26964
- }
26965
- return record.buffer;
26966
- }
26967
- function generateZip64InfoLocator(options) {
26968
- const locator = new DataView(new ArrayBuffer(Number(20)));
26969
- for (const field of ZIP64_EOCD_LOCATOR_FIELDS) {
26970
- setFieldToNumber(
26971
- locator,
26972
- field.size,
26973
- field.offset,
26974
- options[field.name ?? ""] ?? field.default ?? 0
26975
- );
26976
- }
26977
- return locator.buffer;
26978
- }
26979
- var eoCDSignature, zip64EoCDLocatorSignature, zip64EoCDSignature, CD_RECORDS_NUMBER_OFFSET, CD_CD_BYTE_SIZE_OFFSET, CD_START_OFFSET_OFFSET, CD_COMMENT_OFFSET, ZIP64_EOCD_START_OFFSET_OFFSET, ZIP64_CD_RECORDS_NUMBER_OFFSET, ZIP64_CD_CD_BYTE_SIZE_OFFSET, ZIP64_CD_START_OFFSET_OFFSET, ZIP64_COMMENT_OFFSET, parseEoCDRecord, EOCD_FIELDS, ZIP64_EOCD_LOCATOR_FIELDS, ZIP64_EOCD_FIELDS;
26980
- var init_end_of_central_directory = __esm({
26981
- "../../modules/zip/src/parse-zip/end-of-central-directory.ts"() {
26982
- "use strict";
26983
- init_src2();
26984
- init_search_from_the_end();
26985
- init_readable_file_utils();
26986
- init_zip64_info_generation();
26987
- eoCDSignature = new Uint8Array([80, 75, 5, 6]);
26988
- zip64EoCDLocatorSignature = new Uint8Array([80, 75, 6, 7]);
26989
- zip64EoCDSignature = new Uint8Array([80, 75, 6, 6]);
26990
- CD_RECORDS_NUMBER_OFFSET = 8n;
26991
- CD_CD_BYTE_SIZE_OFFSET = 12n;
26992
- CD_START_OFFSET_OFFSET = 16n;
26993
- CD_COMMENT_OFFSET = 22n;
26994
- ZIP64_EOCD_START_OFFSET_OFFSET = 8n;
26995
- ZIP64_CD_RECORDS_NUMBER_OFFSET = 24n;
26996
- ZIP64_CD_CD_BYTE_SIZE_OFFSET = 40n;
26997
- ZIP64_CD_START_OFFSET_OFFSET = 48n;
26998
- ZIP64_COMMENT_OFFSET = 56n;
26999
- parseEoCDRecord = async (file) => {
27000
- const zipEoCDOffset = await searchFromTheEnd(file, eoCDSignature);
27001
- let cdRecordsNumber = BigInt(await readUint16(file, zipEoCDOffset + CD_RECORDS_NUMBER_OFFSET));
27002
- let cdByteSize = BigInt(await readUint32(file, zipEoCDOffset + CD_CD_BYTE_SIZE_OFFSET));
27003
- let cdStartOffset = BigInt(await readUint32(file, zipEoCDOffset + CD_START_OFFSET_OFFSET));
27004
- let zip64EoCDLocatorOffset = zipEoCDOffset - 20n;
27005
- let zip64EoCDOffset = 0n;
27006
- const magicBytes = await readRange(file, zip64EoCDLocatorOffset, zip64EoCDLocatorOffset + 4n);
27007
- if (compareArrayBuffers(magicBytes, zip64EoCDLocatorSignature.buffer)) {
27008
- zip64EoCDOffset = await readBigUint64(
27009
- file,
27010
- zip64EoCDLocatorOffset + ZIP64_EOCD_START_OFFSET_OFFSET
27011
- );
27012
- const endOfCDMagicBytes = await readRange(file, zip64EoCDOffset, zip64EoCDOffset + 4n);
27013
- if (!compareArrayBuffers(endOfCDMagicBytes, zip64EoCDSignature.buffer)) {
27014
- throw new Error("zip64 EoCD not found");
27015
- }
27016
- cdRecordsNumber = await readBigUint64(file, zip64EoCDOffset + ZIP64_CD_RECORDS_NUMBER_OFFSET);
27017
- cdByteSize = await readBigUint64(file, zip64EoCDOffset + ZIP64_CD_CD_BYTE_SIZE_OFFSET);
27018
- cdStartOffset = await readBigUint64(file, zip64EoCDOffset + ZIP64_CD_START_OFFSET_OFFSET);
27019
- } else {
27020
- zip64EoCDLocatorOffset = 0n;
27021
- }
27022
- return {
27023
- cdRecordsNumber,
27024
- cdStartOffset,
27025
- cdByteSize,
27026
- offsets: {
27027
- zip64EoCDOffset,
27028
- zip64EoCDLocatorOffset,
27029
- zipEoCDOffset
27030
- }
27031
- };
27032
- };
27033
- EOCD_FIELDS = [
27034
- // End of central directory signature = 0x06054b50
27035
- {
27036
- offset: 0,
27037
- size: 4,
27038
- default: new DataView(eoCDSignature.buffer).getUint32(0, true)
27039
- },
27040
- // Number of this disk (or 0xffff for ZIP64)
27041
- {
27042
- offset: 4,
27043
- size: 2,
27044
- default: 0
27045
- },
27046
- // Disk where central directory starts (or 0xffff for ZIP64)
27047
- {
27048
- offset: 6,
27049
- size: 2,
27050
- default: 0
27051
- },
27052
- // Number of central directory records on this disk (or 0xffff for ZIP64)
27053
- {
27054
- offset: 8,
27055
- size: 2,
27056
- name: "recordsNumber"
27057
- },
27058
- // Total number of central directory records (or 0xffff for ZIP64)
27059
- {
27060
- offset: 10,
27061
- size: 2,
27062
- name: "recordsNumber"
27063
- },
27064
- // Size of central directory (bytes) (or 0xffffffff for ZIP64)
27065
- {
27066
- offset: 12,
27067
- size: 4,
27068
- name: "cdSize"
27069
- },
27070
- // Offset of start of central directory, relative to start of archive (or 0xffffffff for ZIP64)
27071
- {
27072
- offset: 16,
27073
- size: 4,
27074
- name: "cdOffset"
27075
- },
27076
- // Comment length (n)
27077
- {
27078
- offset: 20,
27079
- size: 2,
27080
- default: 0
27081
- }
27082
- ];
27083
- ZIP64_EOCD_LOCATOR_FIELDS = [
27084
- // zip64 end of central dir locator signature
27085
- {
27086
- offset: 0,
27087
- size: 4,
27088
- default: new DataView(zip64EoCDLocatorSignature.buffer).getUint32(0, true)
27089
- },
27090
- // number of the disk with the start of the zip64 end of
27091
- {
27092
- offset: 4,
27093
- size: 4,
27094
- default: 0
27095
- },
27096
- // start of the zip64 end of central directory
27097
- {
27098
- offset: 8,
27099
- size: 8,
27100
- name: "eoCDStart"
27101
- },
27102
- // total number of disks
27103
- {
27104
- offset: 16,
27105
- size: 4,
27106
- default: 1
27107
- }
27108
- ];
27109
- ZIP64_EOCD_FIELDS = [
27110
- // End of central directory signature = 0x06064b50
27111
- {
27112
- offset: 0,
27113
- size: 4,
27114
- default: new DataView(zip64EoCDSignature.buffer).getUint32(0, true)
27115
- },
27116
- // Size of the EOCD64 minus 12
27117
- {
27118
- offset: 4,
27119
- size: 8,
27120
- default: 44
27121
- },
27122
- // Version made by
27123
- {
27124
- offset: 12,
27125
- size: 2,
27126
- default: 45
27127
- },
27128
- // Version needed to extract (minimum)
27129
- {
27130
- offset: 14,
27131
- size: 2,
27132
- default: 45
27133
- },
27134
- // Number of this disk
27135
- {
27136
- offset: 16,
27137
- size: 4,
27138
- default: 0
27139
- },
27140
- // Disk where central directory starts
27141
- {
27142
- offset: 20,
27143
- size: 4,
27144
- default: 0
27145
- },
27146
- // Number of central directory records on this disk
27147
- {
27148
- offset: 24,
27149
- size: 8,
27150
- name: "recordsNumber"
27151
- },
27152
- // Total number of central directory records
27153
- {
27154
- offset: 32,
27155
- size: 8,
27156
- name: "recordsNumber"
27157
- },
27158
- // Size of central directory (bytes)
27159
- {
27160
- offset: 40,
27161
- size: 8,
27162
- name: "cdSize"
27163
- },
27164
- // Offset of start of central directory, relative to start of archive
27165
- {
27166
- offset: 48,
27167
- size: 8,
27168
- name: "cdOffset"
27169
- }
27170
- ];
27171
- }
27172
- });
27173
-
27174
- // ../../modules/zip/src/parse-zip/zip64-extra-field.ts
26906
+ // ../../modules/zip/src/lib/zip64-extra-field.ts
27175
26907
  function parseZip64ExtraField(extraField, expectedFields) {
27176
26908
  const values = {};
27177
26909
  if (expectedFields.length === 0) {
@@ -27214,537 +26946,264 @@ function parseZip64ExtraField(extraField, expectedFields) {
27214
26946
  }
27215
26947
  throw new Error("Invalid ZIP archive: required ZIP64 extended information is missing");
27216
26948
  }
27217
- var ZIP64_EXTRA_FIELD_ID, ZIP64_UINT16_SENTINEL, ZIP64_UINT32_SENTINEL;
26949
+ var ZIP64_EXTRA_FIELD_ID;
27218
26950
  var init_zip64_extra_field = __esm({
27219
- "../../modules/zip/src/parse-zip/zip64-extra-field.ts"() {
26951
+ "../../modules/zip/src/lib/zip64-extra-field.ts"() {
27220
26952
  "use strict";
27221
26953
  ZIP64_EXTRA_FIELD_ID = 1;
27222
- ZIP64_UINT16_SENTINEL = 0xffffn;
27223
- ZIP64_UINT32_SENTINEL = 0xffffffffn;
27224
26954
  }
27225
26955
  });
27226
26956
 
27227
- // ../../modules/zip/src/parse-zip/cd-file-header.ts
27228
- async function* makeZipCDHeaderIterator(fileProvider) {
27229
- const { cdStartOffset, cdByteSize } = await parseEoCDRecord(fileProvider);
27230
- const centralDirectory = new DataViewReadableFile(
27231
- new DataView(await readRange(fileProvider, cdStartOffset, cdStartOffset + cdByteSize))
27232
- );
27233
- let cdHeader = await parseZipCDFileHeader(0n, centralDirectory);
27234
- while (cdHeader) {
27235
- yield cdHeader;
27236
- cdHeader = await parseZipCDFileHeader(
27237
- cdHeader.extraOffset + BigInt(cdHeader.extraFieldLength),
27238
- centralDirectory
27239
- );
27240
- }
27241
- }
27242
- function generateCDHeader(options) {
27243
- const optionsToUse = {
27244
- ...options,
27245
- fnlength: options.fileName.length,
27246
- extraLength: 0
26957
+ // ../../modules/zip/src/lib/zip-entry-metadata.ts
26958
+ function decodeZipHeader(bytes, central) {
26959
+ const header = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
26960
+ const fixedBytes = central ? 46 : 30;
26961
+ if (bytes.byteLength < fixedBytes || header.getUint32(0, true) !== (central ? 33639248 : 67324752))
26962
+ throw new Error("Invalid ZIP archive: missing entry header");
26963
+ const nameLength = header.getUint16(central ? 28 : 26, true);
26964
+ const extraLength = header.getUint16(central ? 30 : 28, true);
26965
+ const commentLength = central ? header.getUint16(32, true) : 0;
26966
+ if (bytes.byteLength !== fixedBytes + nameLength + extraLength + commentLength)
26967
+ throw new Error("Invalid ZIP archive: truncated entry metadata");
26968
+ const flags = header.getUint16(central ? 8 : 6, true);
26969
+ const method = header.getUint16(central ? 10 : 8, true);
26970
+ if (flags & (1 | 64 | 8192)) throw new Error("Unsupported ZIP encryption");
26971
+ if (flags & ~(8 | 2048 | (method === 8 ? 6 : 0))) throw new Error("Unsupported ZIP flags");
26972
+ if (method !== 0 && method !== 8)
26973
+ throw new Error(`Unsupported ZIP compression method: ${method}`);
26974
+ let compressedSize = BigInt(header.getUint32(central ? 20 : 18, true));
26975
+ let size = BigInt(header.getUint32(central ? 24 : 22, true));
26976
+ let localHeaderOffset = central ? BigInt(header.getUint32(42, true)) : 0n;
26977
+ let disk = central ? BigInt(header.getUint16(34, true)) : 0n;
26978
+ let zip64 = compressedSize === 0xffffffffn || size === 0xffffffffn;
26979
+ const fields = [];
26980
+ if (central) {
26981
+ if (size === 0xffffffffn) fields.push({ name: "size", byteLength: 8 });
26982
+ if (compressedSize === 0xffffffffn) fields.push({ name: "compressedSize", byteLength: 8 });
26983
+ if (localHeaderOffset === 0xffffffffn) fields.push({ name: "localHeaderOffset", byteLength: 8 });
26984
+ if (disk === 0xffffn) fields.push({ name: "disk", byteLength: 4 });
26985
+ } else if (zip64)
26986
+ fields.push({ name: "size", byteLength: 8 }, { name: "compressedSize", byteLength: 8 });
26987
+ const extraBytes = bytes.subarray(fixedBytes + nameLength, fixedBytes + nameLength + extraLength);
26988
+ const extra = new DataView(extraBytes.buffer, extraBytes.byteOffset, extraBytes.byteLength);
26989
+ const extraValues = parseZip64ExtraField(extra, fields);
26990
+ if (size === 0xffffffffn) size = extraValues.size;
26991
+ if (compressedSize === 0xffffffffn) compressedSize = extraValues.compressedSize;
26992
+ if (localHeaderOffset === 0xffffffffn) localHeaderOffset = extraValues.localHeaderOffset;
26993
+ if (disk === 0xffffn) disk = extraValues.disk;
26994
+ if (disk !== 0n) throw new Error("Unsupported split ZIP archive");
26995
+ const nameBytes = bytes.subarray(fixedBytes, fixedBytes + nameLength);
26996
+ let path = decodeZipText(nameBytes, Boolean(flags & 2048));
26997
+ const commentBytes = bytes.subarray(fixedBytes + nameLength + extraLength);
26998
+ let comment = decodeZipText(commentBytes, Boolean(flags & 2048));
26999
+ for (let offset = 0; offset < extra.byteLength; ) {
27000
+ if (offset + 4 > extra.byteLength)
27001
+ throw new Error("Invalid ZIP archive: truncated extra field");
27002
+ const identifier = extra.getUint16(offset, true);
27003
+ const length = extra.getUint16(offset + 2, true);
27004
+ if (offset + 4 + length > extra.byteLength)
27005
+ throw new Error("Invalid ZIP archive: truncated extra field");
27006
+ if (!central && flags & 8 && identifier === 1) {
27007
+ if (length >= 16) zip64 = true;
27008
+ }
27009
+ if (identifier === 28789 || identifier === 25461) {
27010
+ const original = identifier === 28789 ? nameBytes : commentBytes;
27011
+ if (length < 5) throw new Error("Invalid ZIP archive: truncated Unicode extra field");
27012
+ if (extra.getUint8(offset + 4) === 1 && extra.getUint32(offset + 5, true) === calculateZipChecksum(original)) {
27013
+ const text = decodeZipText(extraBytes.subarray(offset + 9, offset + 4 + length), true);
27014
+ if (identifier === 28789) path = text;
27015
+ else comment = text;
27016
+ }
27017
+ }
27018
+ offset += 4 + length;
27019
+ }
27020
+ validateZipPath(path);
27021
+ return {
27022
+ path,
27023
+ nameBytes,
27024
+ flags,
27025
+ method,
27026
+ crc32: header.getUint32(central ? 16 : 14, true),
27027
+ compressedSize,
27028
+ size,
27029
+ localHeaderOffset,
27030
+ comment,
27031
+ zip64
27247
27032
  };
27248
- let zip64header = new ArrayBuffer(0);
27249
- const optionsToZip64 = {};
27250
- if (optionsToUse.offset >= 4294967295) {
27251
- optionsToZip64.offset = optionsToUse.offset;
27252
- optionsToUse.offset = BigInt(4294967295);
27253
- }
27254
- if (optionsToUse.length >= 4294967295) {
27255
- optionsToZip64.size = optionsToUse.length;
27256
- optionsToUse.length = 4294967295;
27257
- }
27258
- if (Object.keys(optionsToZip64).length) {
27259
- zip64header = createZip64Info(optionsToZip64);
27260
- optionsToUse.extraLength = zip64header.byteLength;
27261
- }
27262
- const header = new DataView(new ArrayBuffer(Number(CD_FILE_NAME_OFFSET)));
27263
- for (const field of ZIP_HEADER_FIELDS) {
27264
- setFieldToNumber(
27265
- header,
27266
- field.size,
27267
- field.offset,
27268
- optionsToUse[field.name ?? ""] ?? field.default ?? 0
27269
- );
27270
- }
27271
- const encodedName = new TextEncoder().encode(optionsToUse.fileName);
27272
- const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
27273
- return resHeader;
27274
27033
  }
27275
- var CD_COMPRESSED_SIZE_OFFSET, CD_UNCOMPRESSED_SIZE_OFFSET, CD_FILE_NAME_LENGTH_OFFSET, CD_EXTRA_FIELD_LENGTH_OFFSET, CD_START_DISK_OFFSET, CD_LOCAL_HEADER_OFFSET_OFFSET, CD_FILE_NAME_OFFSET, signature2, parseZipCDFileHeader, ZIP_HEADER_FIELDS;
27276
- var init_cd_file_header = __esm({
27277
- "../../modules/zip/src/parse-zip/cd-file-header.ts"() {
27278
- "use strict";
27279
- init_src2();
27280
- init_end_of_central_directory();
27281
- init_zip64_info_generation();
27282
- init_zip64_extra_field();
27283
- init_readable_file_utils();
27284
- CD_COMPRESSED_SIZE_OFFSET = 20;
27285
- CD_UNCOMPRESSED_SIZE_OFFSET = 24;
27286
- CD_FILE_NAME_LENGTH_OFFSET = 28;
27287
- CD_EXTRA_FIELD_LENGTH_OFFSET = 30;
27288
- CD_START_DISK_OFFSET = 34;
27289
- CD_LOCAL_HEADER_OFFSET_OFFSET = 42;
27290
- CD_FILE_NAME_OFFSET = 46n;
27291
- signature2 = new Uint8Array([80, 75, 1, 2]);
27292
- parseZipCDFileHeader = async (headerOffset, file) => {
27293
- const fileLength = await getReadableFileSize(file);
27294
- if (headerOffset >= fileLength) {
27295
- return null;
27296
- }
27297
- const mainHeader = await readDataView(file, headerOffset, headerOffset + CD_FILE_NAME_OFFSET);
27298
- const magicBytes = mainHeader.buffer.slice(0, 4);
27299
- if (!compareArrayBuffers(magicBytes, signature2.buffer)) {
27300
- return null;
27301
- }
27302
- const compressedSize = BigInt(mainHeader.getUint32(CD_COMPRESSED_SIZE_OFFSET, true));
27303
- const uncompressedSize = BigInt(mainHeader.getUint32(CD_UNCOMPRESSED_SIZE_OFFSET, true));
27304
- const extraFieldLength = mainHeader.getUint16(CD_EXTRA_FIELD_LENGTH_OFFSET, true);
27305
- const startDisk = BigInt(mainHeader.getUint16(CD_START_DISK_OFFSET, true));
27306
- const fileNameLength = mainHeader.getUint16(CD_FILE_NAME_LENGTH_OFFSET, true);
27307
- const additionalHeader = await readRange(
27308
- file,
27309
- headerOffset + CD_FILE_NAME_OFFSET,
27310
- headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength)
27311
- );
27312
- const filenameBytes = additionalHeader.slice(0, fileNameLength);
27313
- const fileName = new TextDecoder().decode(filenameBytes);
27314
- const extraOffset = headerOffset + CD_FILE_NAME_OFFSET + BigInt(fileNameLength);
27315
- const oldFormatOffset = mainHeader.getUint32(CD_LOCAL_HEADER_OFFSET_OFFSET, true);
27316
- const localHeaderOffset = BigInt(oldFormatOffset);
27317
- const extraField = new DataView(
27318
- additionalHeader.slice(fileNameLength, additionalHeader.byteLength)
27319
- );
27320
- const zip64Data = {
27321
- uncompressedSize,
27322
- compressedSize,
27323
- localHeaderOffset,
27324
- startDisk
27325
- };
27326
- const expectedZip64Fields = [];
27327
- if (zip64Data.uncompressedSize === ZIP64_UINT32_SENTINEL) {
27328
- expectedZip64Fields.push({ name: "uncompressedSize", byteLength: 8 });
27329
- }
27330
- if (zip64Data.compressedSize === ZIP64_UINT32_SENTINEL) {
27331
- expectedZip64Fields.push({ name: "compressedSize", byteLength: 8 });
27332
- }
27333
- if (zip64Data.localHeaderOffset === ZIP64_UINT32_SENTINEL) {
27334
- expectedZip64Fields.push({ name: "localHeaderOffset", byteLength: 8 });
27335
- }
27336
- if (zip64Data.startDisk === ZIP64_UINT16_SENTINEL) {
27337
- expectedZip64Fields.push({ name: "startDisk", byteLength: 4 });
27338
- }
27339
- const zip64Values = parseZip64ExtraField(extraField, expectedZip64Fields);
27340
- return {
27341
- ...zip64Data,
27342
- ...zip64Values,
27343
- extraFieldLength,
27344
- fileNameLength,
27345
- fileName,
27346
- extraOffset
27347
- };
27348
- };
27349
- ZIP_HEADER_FIELDS = [
27350
- // Central directory file header signature = 0x02014b50
27351
- {
27352
- offset: 0,
27353
- size: 4,
27354
- default: new DataView(signature2.buffer).getUint32(0, true)
27355
- },
27356
- // Version made by
27357
- {
27358
- offset: 4,
27359
- size: 2,
27360
- default: 45
27361
- },
27362
- // Version needed to extract (minimum)
27363
- {
27364
- offset: 6,
27365
- size: 2,
27366
- default: 45
27367
- },
27368
- // General purpose bit flag
27369
- {
27370
- offset: 8,
27371
- size: 2,
27372
- default: 0
27373
- },
27374
- // Compression method
27375
- {
27376
- offset: 10,
27377
- size: 2,
27378
- default: 0
27379
- },
27380
- // File last modification time
27381
- {
27382
- offset: 12,
27383
- size: 2,
27384
- default: 0
27385
- },
27386
- // File last modification date
27387
- {
27388
- offset: 14,
27389
- size: 2,
27390
- default: 0
27391
- },
27392
- // CRC-32 of uncompressed data
27393
- {
27394
- offset: 16,
27395
- size: 4,
27396
- name: "crc32"
27397
- },
27398
- // Compressed size (or 0xffffffff for ZIP64)
27399
- {
27400
- offset: 20,
27401
- size: 4,
27402
- name: "length"
27403
- },
27404
- // Uncompressed size (or 0xffffffff for ZIP64)
27405
- {
27406
- offset: 24,
27407
- size: 4,
27408
- name: "length"
27409
- },
27410
- // File name length (n)
27411
- {
27412
- offset: 28,
27413
- size: 2,
27414
- name: "fnlength"
27415
- },
27416
- // Extra field length (m)
27417
- {
27418
- offset: 30,
27419
- size: 2,
27420
- default: 0,
27421
- name: "extraLength"
27422
- },
27423
- // File comment length (k)
27424
- {
27425
- offset: 32,
27426
- size: 2,
27427
- default: 0
27428
- },
27429
- // Disk number where file starts (or 0xffff for ZIP64)
27430
- {
27431
- offset: 34,
27432
- size: 2,
27433
- default: 0
27434
- },
27435
- // Internal file attributes
27436
- {
27437
- offset: 36,
27438
- size: 2,
27439
- default: 0
27440
- },
27441
- // External file attributes
27442
- {
27443
- offset: 38,
27444
- size: 4,
27445
- default: 0
27446
- },
27447
- // Relative offset of local file header
27448
- {
27449
- offset: 42,
27450
- size: 4,
27451
- name: "offset"
27452
- }
27453
- ];
27454
- }
27455
- });
27456
-
27457
- // ../../modules/zip/src/parse-zip/local-file-header.ts
27458
- function generateLocalHeader(options) {
27459
- const optionsToUse = {
27460
- ...options,
27461
- extraLength: 0,
27462
- fnlength: options.fileName.length
27463
- };
27464
- let zip64header = new ArrayBuffer(0);
27465
- const optionsToZip64 = {};
27466
- if (optionsToUse.length >= 4294967295) {
27467
- optionsToZip64.size = optionsToUse.length;
27468
- optionsToUse.length = 4294967295;
27469
- }
27470
- if (Object.keys(optionsToZip64).length) {
27471
- zip64header = createZip64Info(optionsToZip64);
27472
- optionsToUse.extraLength = zip64header.byteLength;
27473
- }
27474
- const header = new DataView(new ArrayBuffer(Number(FILE_NAME_OFFSET)));
27475
- for (const field of ZIP_HEADER_FIELDS2) {
27476
- setFieldToNumber(
27477
- header,
27478
- field.size,
27479
- field.offset,
27480
- optionsToUse[field.name ?? ""] ?? field.default ?? 0
27481
- );
27482
- }
27483
- const encodedName = new TextEncoder().encode(optionsToUse.fileName);
27484
- const resHeader = concatenateArrayBuffers(header.buffer, encodedName, zip64header);
27485
- return resHeader;
27034
+ function decodeZipText(bytes, utf8) {
27035
+ if (utf8) return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
27036
+ return Array.from(
27037
+ bytes,
27038
+ (value) => value < 128 ? String.fromCharCode(value) : CP437_HIGH[value - 128]
27039
+ ).join("");
27040
+ }
27041
+ function validateZipPath(path) {
27042
+ const segments = path.endsWith("/") ? path.slice(0, -1).split("/") : path.split("/");
27043
+ if (!path || path.includes("\\") || path.includes("\0") || /^[A-Za-z]:/.test(path) || segments.some((segment) => !segment || segment === "." || segment === ".."))
27044
+ throw new Error("Invalid ZIP archive: noncanonical relative path");
27045
+ }
27046
+ function calculateZipChecksum(bytes) {
27047
+ return Number.parseInt(new CRC32Hash().hashSync(bytes.slice().buffer, "hex"), 16);
27048
+ }
27049
+ function encodeUtf8Text(value) {
27050
+ const bytes = new TextEncoder().encode(value);
27051
+ if (new TextDecoder("utf-8", { ignoreBOM: true }).decode(bytes) !== value)
27052
+ throw new TypeError("ZIP names and entry comments must be well-formed Unicode");
27053
+ return bytes;
27486
27054
  }
27487
- var COMPRESSION_METHOD_OFFSET, COMPRESSED_SIZE_OFFSET, UNCOMPRESSED_SIZE_OFFSET, FILE_NAME_LENGTH_OFFSET, EXTRA_FIELD_LENGTH_OFFSET, FILE_NAME_OFFSET, signature3, parseZipLocalFileHeader, ZIP_HEADER_FIELDS2;
27488
- var init_local_file_header = __esm({
27489
- "../../modules/zip/src/parse-zip/local-file-header.ts"() {
27055
+ var CP437_HIGH;
27056
+ var init_zip_entry_metadata = __esm({
27057
+ "../../modules/zip/src/lib/zip-entry-metadata.ts"() {
27490
27058
  "use strict";
27491
- init_src2();
27492
- init_zip64_info_generation();
27059
+ init_src11();
27493
27060
  init_zip64_extra_field();
27494
- init_readable_file_utils();
27495
- COMPRESSION_METHOD_OFFSET = 8;
27496
- COMPRESSED_SIZE_OFFSET = 18;
27497
- UNCOMPRESSED_SIZE_OFFSET = 22;
27498
- FILE_NAME_LENGTH_OFFSET = 26;
27499
- EXTRA_FIELD_LENGTH_OFFSET = 28;
27500
- FILE_NAME_OFFSET = 30n;
27501
- signature3 = new Uint8Array([80, 75, 3, 4]);
27502
- parseZipLocalFileHeader = async (headerOffset, file) => {
27503
- const mainHeader = await readDataView(file, headerOffset, headerOffset + FILE_NAME_OFFSET);
27504
- const magicBytes = mainHeader.buffer.slice(0, 4);
27505
- if (!compareArrayBuffers(magicBytes, signature3.buffer)) {
27506
- return null;
27507
- }
27508
- const fileNameLength = mainHeader.getUint16(FILE_NAME_LENGTH_OFFSET, true);
27509
- const extraFieldLength = mainHeader.getUint16(EXTRA_FIELD_LENGTH_OFFSET, true);
27510
- const additionalHeader = await readRange(
27511
- file,
27512
- headerOffset + FILE_NAME_OFFSET,
27513
- headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength)
27514
- );
27515
- const fileNameBuffer = additionalHeader.slice(0, fileNameLength);
27516
- const extraDataBuffer = new DataView(
27517
- additionalHeader.slice(fileNameLength, additionalHeader.byteLength)
27518
- );
27519
- const fileName = new TextDecoder().decode(fileNameBuffer).split("\\").join("/");
27520
- const fileDataOffset = headerOffset + FILE_NAME_OFFSET + BigInt(fileNameLength + extraFieldLength);
27521
- const compressionMethod = mainHeader.getUint16(COMPRESSION_METHOD_OFFSET, true);
27522
- let compressedSize = BigInt(mainHeader.getUint32(COMPRESSED_SIZE_OFFSET, true));
27523
- const uncompressedSize = BigInt(mainHeader.getUint32(UNCOMPRESSED_SIZE_OFFSET, true));
27524
- const expectedZip64Fields = [];
27525
- if (uncompressedSize === ZIP64_UINT32_SENTINEL || compressedSize === ZIP64_UINT32_SENTINEL) {
27526
- expectedZip64Fields.push(
27527
- { name: "uncompressedSize", byteLength: 8 },
27528
- { name: "compressedSize", byteLength: 8 }
27529
- );
27530
- }
27531
- const zip64Sizes = parseZip64ExtraField(extraDataBuffer, expectedZip64Fields);
27532
- if (compressedSize === ZIP64_UINT32_SENTINEL && zip64Sizes.compressedSize !== void 0) {
27533
- compressedSize = zip64Sizes.compressedSize;
27534
- }
27535
- return {
27536
- fileNameLength,
27537
- fileName,
27538
- extraFieldLength,
27539
- fileDataOffset,
27540
- compressedSize,
27541
- compressionMethod
27542
- };
27543
- };
27544
- ZIP_HEADER_FIELDS2 = [
27545
- // Local file header signature = 0x04034b50
27546
- {
27547
- offset: 0,
27548
- size: 4,
27549
- default: new DataView(signature3.buffer).getUint32(0, true)
27550
- },
27551
- // Version needed to extract (minimum)
27552
- {
27553
- offset: 4,
27554
- size: 2,
27555
- default: 45
27556
- },
27557
- // General purpose bit flag
27558
- {
27559
- offset: 6,
27560
- size: 2,
27561
- default: 0
27562
- },
27563
- // Compression method
27564
- {
27565
- offset: 8,
27566
- size: 2,
27567
- default: 0
27568
- },
27569
- // File last modification time
27570
- {
27571
- offset: 10,
27572
- size: 2,
27573
- default: 0
27574
- },
27575
- // File last modification date
27576
- {
27577
- offset: 12,
27578
- size: 2,
27579
- default: 0
27580
- },
27581
- // CRC-32 of uncompressed data
27582
- {
27583
- offset: 14,
27584
- size: 4,
27585
- name: "crc32"
27586
- },
27587
- // Compressed size (or 0xffffffff for ZIP64)
27588
- {
27589
- offset: 18,
27590
- size: 4,
27591
- name: "length"
27592
- },
27593
- // Uncompressed size (or 0xffffffff for ZIP64)
27594
- {
27595
- offset: 22,
27596
- size: 4,
27597
- name: "length"
27598
- },
27599
- // File name length (n)
27600
- {
27601
- offset: 26,
27602
- size: 2,
27603
- name: "fnlength"
27604
- },
27605
- // Extra field length (m)
27606
- {
27607
- offset: 28,
27608
- size: 2,
27609
- default: 0,
27610
- name: "extraLength"
27611
- }
27612
- ];
27613
- }
27614
- });
27615
-
27616
- // ../../modules/zip/src/parse-zip/zip-composition.ts
27617
- async function generateFileHeaders(fileName, fileToAdd, localFileHeaderOffset) {
27618
- const newFileCRC322 = parseInt(await new CRC32Hash().hash(fileToAdd, "hex"), 16);
27619
- const newFileLocalHeader = generateLocalHeader({
27620
- crc32: newFileCRC322,
27621
- fileName,
27622
- length: fileToAdd.byteLength
27623
- });
27624
- const newFileCDHeader = generateCDHeader({
27625
- crc32: newFileCRC322,
27626
- fileName,
27627
- offset: localFileHeaderOffset,
27628
- length: fileToAdd.byteLength
27629
- });
27630
- return [
27631
- new Uint8Array(concatenateArrayBuffers(newFileLocalHeader, fileToAdd)),
27632
- new Uint8Array(newFileCDHeader)
27633
- ];
27634
- }
27635
- async function createZip(inputPath, outputPath, createAdditionalData) {
27636
- const fileIterator = getFileIterator(inputPath);
27637
- const resFile = new NodeFileFacade(outputPath, "w");
27638
- const fileList = [];
27639
- const cdArray = [];
27640
- for await (const file of fileIterator) {
27641
- await addFile(file, resFile, cdArray, fileList);
27642
- }
27643
- if (createAdditionalData) {
27644
- const additionaldata = await createAdditionalData(fileList);
27645
- await addFile(additionaldata, resFile, cdArray);
27646
- }
27647
- const cdOffset = (await resFile.stat()).bigsize;
27648
- const cd = concatenateArrayBuffers(...cdArray);
27649
- await resFile.append(new Uint8Array(cd));
27650
- const eoCDStart = (await resFile.stat()).bigsize;
27651
- await resFile.append(
27652
- new Uint8Array(
27653
- generateEoCD({ recordsNumber: cdArray.length, cdSize: cd.byteLength, cdOffset, eoCDStart })
27654
- )
27061
+ CP437_HIGH = "\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
27062
+ }
27063
+ });
27064
+
27065
+ // ../../modules/zip/src/lib/zip-serialization.ts
27066
+ function encodeZipLocalHeader(entry) {
27067
+ validateHeaderEntry(entry);
27068
+ const bytes = new Uint8Array(30 + entry.nameBytes.length + (entry.zip64 ? 20 : 0));
27069
+ const view = new DataView(bytes.buffer);
27070
+ view.setUint32(0, 67324752, true);
27071
+ view.setUint16(4, getZipVersion(entry), true);
27072
+ view.setUint16(6, entry.flags, true);
27073
+ view.setUint16(8, entry.method, true);
27074
+ view.setUint32(10, encodeZipTimestamp(entry.date), true);
27075
+ const descriptor = Boolean(entry.flags & 8);
27076
+ view.setUint32(14, descriptor ? 0 : entry.crc32, true);
27077
+ view.setUint32(
27078
+ 18,
27079
+ entry.zip64 ? Number(ZIP32_SENTINEL) : descriptor ? 0 : Number(entry.compressedSize),
27080
+ true
27655
27081
  );
27082
+ view.setUint32(
27083
+ 22,
27084
+ entry.zip64 ? Number(ZIP32_SENTINEL) : descriptor ? 0 : Number(entry.size),
27085
+ true
27086
+ );
27087
+ view.setUint16(26, entry.nameBytes.length, true);
27088
+ view.setUint16(28, entry.zip64 ? 20 : 0, true);
27089
+ bytes.set(entry.nameBytes, 30);
27090
+ if (entry.zip64) {
27091
+ const extraOffset = 30 + entry.nameBytes.length;
27092
+ view.setUint16(extraOffset, 1, true);
27093
+ view.setUint16(extraOffset + 2, 16, true);
27094
+ view.setBigUint64(extraOffset + 4, descriptor ? 0n : entry.size, true);
27095
+ view.setBigUint64(extraOffset + 12, descriptor ? 0n : entry.compressedSize, true);
27096
+ }
27097
+ return bytes;
27656
27098
  }
27657
- async function addFile(file, resFile, cdArray, fileList) {
27658
- const size = (await resFile.stat()).bigsize;
27659
- fileList?.push({ fileName: file.path, localHeaderOffset: size });
27660
- const [localPart, cdHeaderPart] = await generateFileHeaders(file.path, file.file, size);
27661
- await resFile.append(localPart);
27662
- cdArray.push(toArrayBuffer2(cdHeaderPart));
27099
+ function encodeZipCentralHeader(entry) {
27100
+ validateHeaderEntry(entry);
27101
+ const comment = entry.commentBytes ?? new Uint8Array();
27102
+ const extraBytes = entry.zip64 ? 28 : 0;
27103
+ const bytes = new Uint8Array(46 + entry.nameBytes.length + extraBytes + comment.length);
27104
+ const view = new DataView(bytes.buffer);
27105
+ view.setUint32(0, 33639248, true);
27106
+ view.setUint16(4, entry.zip64 ? 45 : 20, true);
27107
+ view.setUint16(6, getZipVersion(entry), true);
27108
+ view.setUint16(8, entry.flags, true);
27109
+ view.setUint16(10, entry.method, true);
27110
+ view.setUint32(12, encodeZipTimestamp(entry.date), true);
27111
+ view.setUint32(16, entry.crc32, true);
27112
+ view.setUint32(20, entry.zip64 ? Number(ZIP32_SENTINEL) : Number(entry.compressedSize), true);
27113
+ view.setUint32(24, entry.zip64 ? Number(ZIP32_SENTINEL) : Number(entry.size), true);
27114
+ view.setUint16(28, entry.nameBytes.length, true);
27115
+ view.setUint16(30, extraBytes, true);
27116
+ view.setUint16(32, comment.length, true);
27117
+ view.setUint32(38, entry.directory ? 16 : 0, true);
27118
+ view.setUint32(42, entry.zip64 ? Number(ZIP32_SENTINEL) : Number(entry.localHeaderOffset), true);
27119
+ bytes.set(entry.nameBytes, 46);
27120
+ if (entry.zip64) {
27121
+ const extraOffset = 46 + entry.nameBytes.length;
27122
+ view.setUint16(extraOffset, 1, true);
27123
+ view.setUint16(extraOffset + 2, 24, true);
27124
+ view.setBigUint64(extraOffset + 4, entry.size, true);
27125
+ view.setBigUint64(extraOffset + 12, entry.compressedSize, true);
27126
+ view.setBigUint64(extraOffset + 20, entry.localHeaderOffset, true);
27127
+ }
27128
+ bytes.set(comment, 46 + entry.nameBytes.length + extraBytes);
27129
+ return bytes;
27663
27130
  }
27664
- function getFileIterator(inputPath) {
27665
- async function* iterable() {
27666
- const fileList = await getAllFiles(inputPath);
27667
- for (const filePath of fileList) {
27668
- const provider = new NodeFileFacade(path_exports.join(inputPath, filePath), "r");
27669
- const { bigsize } = await provider.stat();
27670
- const file = await provider.read(0, Number(bigsize));
27671
- await provider.close();
27672
- yield { path: filePath, file };
27673
- }
27674
- }
27675
- return iterable();
27131
+ function encodeZipEndRecords(count, directorySize, directoryOffset, zip64, comment = new Uint8Array()) {
27132
+ for (const value of [count, directorySize, directoryOffset, directoryOffset + directorySize])
27133
+ validateUint64(value);
27134
+ if (comment.length > 65535) throw new RangeError("ZIP archive comment exceeds 65535 bytes");
27135
+ if (!zip64 && (count > 0xffffn || directorySize >= ZIP32_SENTINEL || directoryOffset >= ZIP32_SENTINEL))
27136
+ throw new RangeError("ZIP32 end record capacity exceeded");
27137
+ const bytes = new Uint8Array((zip64 ? 98 : 22) + comment.length);
27138
+ const view = new DataView(bytes.buffer);
27139
+ if (zip64) {
27140
+ view.setUint32(0, 101075792, true);
27141
+ view.setBigUint64(4, 44n, true);
27142
+ view.setUint16(12, 45, true);
27143
+ view.setUint16(14, 45, true);
27144
+ view.setBigUint64(24, count, true);
27145
+ view.setBigUint64(32, count, true);
27146
+ view.setBigUint64(40, directorySize, true);
27147
+ view.setBigUint64(48, directoryOffset, true);
27148
+ view.setUint32(56, 117853008, true);
27149
+ view.setBigUint64(64, directoryOffset + directorySize, true);
27150
+ view.setUint32(72, 1, true);
27151
+ }
27152
+ const endOffset = zip64 ? 76 : 0;
27153
+ view.setUint32(endOffset, 101010256, true);
27154
+ view.setUint16(endOffset + 8, zip64 ? 65535 : Number(count), true);
27155
+ view.setUint16(endOffset + 10, zip64 ? 65535 : Number(count), true);
27156
+ view.setUint32(endOffset + 12, zip64 ? Number(ZIP32_SENTINEL) : Number(directorySize), true);
27157
+ view.setUint32(endOffset + 16, zip64 ? Number(ZIP32_SENTINEL) : Number(directoryOffset), true);
27158
+ view.setUint16(endOffset + 20, comment.length, true);
27159
+ bytes.set(comment, endOffset + 22);
27160
+ return bytes;
27676
27161
  }
27677
- async function getAllFiles(basePath, subfolder = "", fsPassed) {
27678
- const fs3 = fsPassed ? fsPassed : new NodeFileSystemFacade({});
27679
- const files = await fs3.readdir(pathJoin(basePath, subfolder));
27680
- const arrayOfFiles = [];
27681
- for (const file of files) {
27682
- const fullPath = pathJoin(basePath, subfolder, file);
27683
- if ((await fs3.stat(fullPath)).isDirectory) {
27684
- const files2 = await getAllFiles(basePath, pathJoin(subfolder, file));
27685
- arrayOfFiles.push(...files2);
27686
- } else {
27687
- arrayOfFiles.push(pathJoin(subfolder, file));
27688
- }
27689
- }
27690
- return arrayOfFiles;
27162
+ function encodeZipTimestamp(date) {
27163
+ if (!(date instanceof Date) || !Number.isFinite(date.getTime()) || date.getUTCFullYear() < 1980 || date.getUTCFullYear() > 2107)
27164
+ throw new RangeError("ZIP timestamp must be a valid UTC date in 1980\u20132107");
27165
+ const time = date.getUTCHours() << 11 | date.getUTCMinutes() << 5 | Math.floor(date.getUTCSeconds() / 2);
27166
+ const day = date.getUTCFullYear() - 1980 << 9 | date.getUTCMonth() + 1 << 5 | date.getUTCDate();
27167
+ return (day << 16 | time) >>> 0;
27168
+ }
27169
+ function getZipVersion(entry) {
27170
+ return entry.zip64 ? 45 : entry.method === 8 || entry.flags & 8 ? 20 : 10;
27171
+ }
27172
+ function validateHeaderEntry(entry) {
27173
+ if (!entry.nameBytes.length || entry.nameBytes.length > 65535 || (entry.commentBytes?.length ?? 0) > 65535)
27174
+ throw new RangeError("ZIP name/comment exceeds header capacity");
27175
+ for (const value of [entry.size, entry.compressedSize, entry.localHeaderOffset])
27176
+ validateUint64(value);
27177
+ if (!entry.zip64 && [entry.size, entry.compressedSize, entry.localHeaderOffset].some(
27178
+ (value) => value >= ZIP32_SENTINEL
27179
+ ))
27180
+ throw new RangeError("ZIP32 entry capacity exceeded");
27691
27181
  }
27692
- function pathJoin(...paths) {
27693
- const resPaths = paths.filter((val) => val.length);
27694
- return path_exports.join(...resPaths);
27182
+ function validateUint64(value) {
27183
+ if (typeof value !== "bigint" || value < 0n || value > 0xffffffffffffffffn)
27184
+ throw new RangeError("ZIP64 unsigned integer capacity exceeded");
27695
27185
  }
27696
- var init_zip_composition = __esm({
27697
- "../../modules/zip/src/parse-zip/zip-composition.ts"() {
27186
+ var ZIP32_SENTINEL;
27187
+ var init_zip_serialization = __esm({
27188
+ "../../modules/zip/src/lib/zip-serialization.ts"() {
27698
27189
  "use strict";
27699
- init_src2();
27700
- init_end_of_central_directory();
27701
- init_src11();
27702
- init_local_file_header();
27703
- init_cd_file_header();
27190
+ ZIP32_SENTINEL = 0xffffffffn;
27704
27191
  }
27705
27192
  });
27706
27193
 
27707
- // ../../modules/compression/src/lib/compression.ts
27708
- var CompressionTransform, Decompressor;
27709
- var init_compression = __esm({
27710
- "../../modules/compression/src/lib/compression.ts"() {
27194
+ // ../../modules/compression/src/deflate-decompressor-compress-utils.ts
27195
+ var DeflateCompressUtilsDecompressor;
27196
+ var init_deflate_decompressor_compress_utils = __esm({
27197
+ "../../modules/compression/src/deflate-decompressor-compress-utils.ts"() {
27711
27198
  "use strict";
27712
- init_src2();
27713
- CompressionTransform = class {
27714
- /** Preloads any dynamic libraries. May enable sync functions */
27715
- async preload(modules = {}) {
27716
- registerJSModules(modules);
27717
- return void 0;
27718
- }
27719
- // HELPERS
27720
- concatenate(asyncIterator) {
27721
- return concatenateArrayBuffersAsync(asyncIterator);
27722
- }
27723
- improveError(error) {
27724
- if (!error.message.includes(this.name)) {
27725
- error.message = `${this.name} ${error.message}`;
27726
- }
27727
- return error;
27728
- }
27729
- };
27730
- Decompressor = class extends CompressionTransform {
27731
- constructor(options) {
27732
- super();
27733
- this.decompressBatches = this.decompressBatches.bind(this);
27734
- }
27735
- /** Asynchronously decompresses data. */
27736
- async decompress(input, size) {
27737
- await this.preload();
27738
- return this.decompressSync(input, size);
27739
- }
27740
- /** Synchronously decompresses data. */
27741
- decompressSync(input, size) {
27742
- throw new Error(`${this.name}: sync decompression not supported`);
27743
- }
27744
- /** Decompresses batches. */
27745
- async *decompressBatches(asyncIterator) {
27746
- const input = await this.concatenate(asyncIterator);
27747
- yield this.decompress(input);
27199
+ init_compress_utils_compression();
27200
+ DeflateCompressUtilsDecompressor = class extends CompressUtilsDecompressor {
27201
+ constructor(options = {}) {
27202
+ super(
27203
+ { name: "deflate", contentEncodings: ["deflate"] },
27204
+ () => options.raw ? import("compress-utils/deflate/decompress") : import("compress-utils/zlib/decompress"),
27205
+ options
27206
+ );
27748
27207
  }
27749
27208
  };
27750
27209
  }
@@ -27845,680 +27304,32 @@ var init_decompression_stream = __esm({
27845
27304
  }
27846
27305
  });
27847
27306
 
27848
- // ../../modules/compression/src/lib/native-decompressor.ts
27849
- var native_decompressor_exports = {};
27850
- __export(native_decompressor_exports, {
27851
- NativeDecompressor: () => NativeDecompressor
27852
- });
27853
- var NativeDecompressor;
27854
- var init_native_decompressor = __esm({
27855
- "../../modules/compression/src/lib/native-decompressor.ts"() {
27856
- "use strict";
27857
- init_compression();
27858
- init_decompression_stream();
27859
- NativeDecompressor = class extends Decompressor {
27860
- name;
27861
- extensions;
27862
- contentEncodings;
27863
- isSupported = true;
27864
- /** Runtime stream format used for every operation. */
27865
- format;
27866
- constructor(metadata, format, options = {}) {
27867
- super(options);
27868
- this.name = metadata.name;
27869
- this.extensions = [...metadata.extensions];
27870
- this.contentEncodings = [...metadata.contentEncodings];
27871
- this.format = format;
27872
- }
27873
- /** Decompresses one buffer with the runtime-provided stream. */
27874
- async decompress(input) {
27875
- const output = await decompressWithNativeDecompressionStream(input, this.format);
27876
- if (!output) throw new Error(`${this.name}: built-in decompression is no longer available`);
27877
- return output;
27878
- }
27879
- /** Decompresses batches incrementally with the runtime-provided stream. */
27880
- async *decompressBatches(inputBatches) {
27881
- const output = decompressBatchesWithNativeDecompressionStream(inputBatches, this.format);
27882
- if (!output) throw new Error(`${this.name}: built-in decompression is no longer available`);
27883
- yield* output;
27884
- }
27885
- };
27886
- }
27887
- });
27888
-
27889
- // ../../modules/compression/src/lib/lazy-compression.ts
27890
- function mergeModules(options, modules) {
27891
- return { ...options, modules: { ...options.modules, ...modules } };
27892
- }
27893
- var LazyDecompressor;
27894
- var init_lazy_compression = __esm({
27895
- "../../modules/compression/src/lib/lazy-compression.ts"() {
27896
- "use strict";
27897
- init_compression();
27898
- init_decompression_stream();
27899
- LazyDecompressor = class extends Decompressor {
27900
- name;
27901
- extensions;
27902
- contentEncodings;
27903
- isSupported = true;
27904
- /** Constructor options retained until a concrete implementation is selected. */
27905
- options;
27906
- /** Built-in stream format to probe, or null when the format has no built-in path. */
27907
- nativeFormat;
27908
- /** Returns whether built-in selection remains eligible for the merged preload options. */
27909
- shouldUseNative;
27910
- /** Dynamically imports the balanced fallback constructor. */
27911
- loadFallback;
27912
- /** Selected concrete implementation after preload completes. */
27913
- implementation = null;
27914
- /** Shared in-flight selection used by concurrent asynchronous calls. */
27915
- implementationPromise = null;
27916
- constructor(metadata, loadFallback, options = {}, nativeFormat = null, shouldUseNative = () => true) {
27917
- super(options);
27918
- this.name = metadata.name;
27919
- this.extensions = [...metadata.extensions];
27920
- this.contentEncodings = [...metadata.contentEncodings];
27921
- this.options = options;
27922
- this.nativeFormat = nativeFormat;
27923
- this.shouldUseNative = shouldUseNative;
27924
- this.loadFallback = loadFallback;
27925
- }
27926
- /** Selects and returns the built-in or dynamically imported fallback decompressor. */
27927
- async preload(modules = {}) {
27928
- if (this.implementation) return this.implementation;
27929
- const options = mergeModules(this.options, modules);
27930
- this.implementationPromise ||= this.loadImplementation(options);
27931
- try {
27932
- this.implementation = await this.implementationPromise;
27933
- return this.implementation;
27934
- } catch (error) {
27935
- this.implementationPromise = null;
27936
- throw error;
27937
- }
27938
- }
27939
- /** Loads the selected concrete decompressor. */
27940
- async loadImplementation(options) {
27941
- if (options.useNative !== false && this.nativeFormat && this.shouldUseNative(options) && isNativeDecompressionSupported(this.nativeFormat)) {
27942
- const { NativeDecompressor: NativeDecompressor2 } = await Promise.resolve().then(() => (init_native_decompressor(), native_decompressor_exports));
27943
- return new NativeDecompressor2(this, this.nativeFormat, options);
27944
- }
27945
- const Decompressor2 = await this.loadFallback();
27946
- const implementation = new Decompressor2({ ...options, useNative: false });
27947
- await implementation.preload(options.modules);
27948
- return implementation;
27949
- }
27950
- /** Decompresses after lazily selecting the default implementation. */
27951
- async decompress(input, size) {
27952
- return (await this.preload()).decompress(input, size);
27953
- }
27954
- /** Decompresses synchronously after an implementation has been preloaded. */
27955
- decompressSync(input, size) {
27956
- if (!this.implementation) {
27957
- throw new Error(`${this.name}: call preload() before decompressSync()`);
27958
- }
27959
- return this.implementation.decompressSync(input, size);
27960
- }
27961
- /** Decompresses batches after lazily selecting the default implementation. */
27962
- async *decompressBatches(inputBatches) {
27963
- yield* (await this.preload()).decompressBatches(inputBatches);
27964
- }
27965
- };
27966
- }
27967
- });
27968
-
27969
- // ../../modules/compression/src/no-decompressor.ts
27970
- var no_decompressor_exports = {};
27971
- __export(no_decompressor_exports, {
27972
- NoDecompressor: () => NoDecompressor
27973
- });
27974
- var NoDecompressor;
27975
- var init_no_decompressor = __esm({
27976
- "../../modules/compression/src/no-decompressor.ts"() {
27977
- "use strict";
27978
- init_compression();
27979
- NoDecompressor = class extends Decompressor {
27980
- name = "uncompressed";
27981
- extensions = [];
27982
- contentEncodings = [];
27983
- isSupported = true;
27984
- constructor(options = {}) {
27985
- super(options);
27986
- }
27987
- /** Returns the input without modification. */
27988
- decompressSync(input) {
27989
- return input;
27990
- }
27991
- };
27992
- }
27993
- });
27994
-
27995
- // ../../modules/compression/src/lib/fflate/index.ts
27996
- function inflateSync(data, out) {
27997
- return inflt(data, out);
27998
- }
27999
- function gunzipSync(data, out) {
28000
- return inflt(data.subarray(gzs(data), -8), out || new u8(gzl(data)));
28001
- }
28002
- function unzlibSync(data, out) {
28003
- return inflt((zlv(data), data.subarray(2, -4)), out);
28004
- }
28005
- var u8, u16, u32, fleb, fdeb, clim, freb, fl, revfl, fd, revfd, rev, hMap, flt, fdt, flrm, fdrm, max, bits, bits16, shft, slc, ec, err, inflt, gzs, gzl, zlv, Inflate, Gunzip, Unzlib;
28006
- var init_fflate = __esm({
28007
- "../../modules/compression/src/lib/fflate/index.ts"() {
28008
- "use strict";
28009
- u8 = Uint8Array;
28010
- u16 = Uint16Array;
28011
- u32 = Uint32Array;
28012
- fleb = new u8([
28013
- 0,
28014
- 0,
28015
- 0,
28016
- 0,
28017
- 0,
28018
- 0,
28019
- 0,
28020
- 0,
28021
- 1,
28022
- 1,
28023
- 1,
28024
- 1,
28025
- 2,
28026
- 2,
28027
- 2,
28028
- 2,
28029
- 3,
28030
- 3,
28031
- 3,
28032
- 3,
28033
- 4,
28034
- 4,
28035
- 4,
28036
- 4,
28037
- 5,
28038
- 5,
28039
- 5,
28040
- 5,
28041
- 0,
28042
- /* unused */
28043
- 0,
28044
- 0,
28045
- /* impossible */
28046
- 0
28047
- ]);
28048
- fdeb = new u8([
28049
- 0,
28050
- 0,
28051
- 0,
28052
- 0,
28053
- 1,
28054
- 1,
28055
- 2,
28056
- 2,
28057
- 3,
28058
- 3,
28059
- 4,
28060
- 4,
28061
- 5,
28062
- 5,
28063
- 6,
28064
- 6,
28065
- 7,
28066
- 7,
28067
- 8,
28068
- 8,
28069
- 9,
28070
- 9,
28071
- 10,
28072
- 10,
28073
- 11,
28074
- 11,
28075
- 12,
28076
- 12,
28077
- 13,
28078
- 13,
28079
- /* unused */
28080
- 0,
28081
- 0
28082
- ]);
28083
- clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
28084
- freb = (eb, start) => {
28085
- const b = new u16(31);
28086
- for (let i = 0; i < 31; ++i) {
28087
- b[i] = start += 1 << eb[i - 1];
28088
- }
28089
- const r = new u32(b[30]);
28090
- for (let i = 1; i < 30; ++i) {
28091
- for (let j = b[i]; j < b[i + 1]; ++j) {
28092
- r[j] = j - b[i] << 5 | i;
28093
- }
28094
- }
28095
- return [b, r];
28096
- };
28097
- [fl, revfl] = freb(fleb, 2);
28098
- fl[28] = 258, revfl[258] = 28;
28099
- [fd, revfd] = freb(fdeb, 0);
28100
- rev = new u16(32768);
28101
- for (let i = 0; i < 32768; ++i) {
28102
- let x = (i & 43690) >>> 1 | (i & 21845) << 1;
28103
- x = (x & 52428) >>> 2 | (x & 13107) << 2;
28104
- x = (x & 61680) >>> 4 | (x & 3855) << 4;
28105
- rev[i] = ((x & 65280) >>> 8 | (x & 255) << 8) >>> 1;
28106
- }
28107
- hMap = (cd, mb, r) => {
28108
- const s = cd.length;
28109
- let i = 0;
28110
- const l = new u16(mb);
28111
- for (; i < s; ++i) {
28112
- if (cd[i]) ++l[cd[i] - 1];
28113
- }
28114
- const le = new u16(mb);
28115
- for (i = 0; i < mb; ++i) {
28116
- le[i] = le[i - 1] + l[i - 1] << 1;
28117
- }
28118
- let co;
28119
- if (r) {
28120
- co = new u16(1 << mb);
28121
- const rvb = 15 - mb;
28122
- for (i = 0; i < s; ++i) {
28123
- if (cd[i]) {
28124
- const sv = i << 4 | cd[i];
28125
- const r2 = mb - cd[i];
28126
- let v = le[cd[i] - 1]++ << r2;
28127
- for (const m = v | (1 << r2) - 1; v <= m; ++v) {
28128
- co[rev[v] >>> rvb] = sv;
28129
- }
28130
- }
28131
- }
28132
- } else {
28133
- co = new u16(s);
28134
- for (i = 0; i < s; ++i) {
28135
- if (cd[i]) {
28136
- co[i] = rev[le[cd[i] - 1]++] >>> 15 - cd[i];
28137
- }
28138
- }
28139
- }
28140
- return co;
28141
- };
28142
- flt = new u8(288);
28143
- for (let i = 0; i < 144; ++i) flt[i] = 8;
28144
- for (let i = 144; i < 256; ++i) flt[i] = 9;
28145
- for (let i = 256; i < 280; ++i) flt[i] = 7;
28146
- for (let i = 280; i < 288; ++i) flt[i] = 8;
28147
- fdt = new u8(32);
28148
- for (let i = 0; i < 32; ++i) fdt[i] = 5;
28149
- flrm = /* @__PURE__ */ hMap(flt, 9, 1);
28150
- fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
28151
- max = (a) => {
28152
- let m = a[0];
28153
- for (let i = 1; i < a.length; ++i) {
28154
- if (a[i] > m) m = a[i];
28155
- }
28156
- return m;
28157
- };
28158
- bits = (d, p, m) => {
28159
- const o = p / 8 | 0;
28160
- return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
28161
- };
28162
- bits16 = (d, p) => {
28163
- const o = p / 8 | 0;
28164
- return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
28165
- };
28166
- shft = (p) => (p + 7) / 8 | 0;
28167
- slc = (v, s, e) => {
28168
- if (s == null || s < 0) s = 0;
28169
- if (e == null || e > v.length) e = v.length;
28170
- const n = new (v.BYTES_PER_ELEMENT == 2 ? u16 : v.BYTES_PER_ELEMENT == 4 ? u32 : u8)(e - s);
28171
- n.set(v.subarray(s, e));
28172
- return n;
28173
- };
28174
- ec = [
28175
- "unexpected EOF",
28176
- "invalid block type",
28177
- "invalid length/literal",
28178
- "invalid distance",
28179
- "stream finished",
28180
- "no stream handler",
28181
- ,
28182
- // determined by compression function
28183
- "no callback",
28184
- "invalid UTF-8 data",
28185
- "extra field too long",
28186
- "date not in range 1980-2099",
28187
- "filename too long",
28188
- "stream finishing",
28189
- "invalid zip data"
28190
- // determined by unknown compression method
28191
- ];
28192
- err = (ind, msg, nt) => {
28193
- const e = new Error(msg || ec[ind]);
28194
- e.code = ind;
28195
- if (Error.captureStackTrace) Error.captureStackTrace(e, err);
28196
- if (!nt) throw e;
28197
- return e;
28198
- };
28199
- inflt = (dat, buf, st) => {
28200
- const sl = dat.length;
28201
- if (!sl || st && st.f && !st.l) return buf || new u8(0);
28202
- const noBuf = !buf || st;
28203
- const noSt = !st || st.i;
28204
- if (!st) st = {};
28205
- if (!buf) buf = new u8(sl * 3);
28206
- const cbuf = (l) => {
28207
- let bl = buf.length;
28208
- if (l > bl) {
28209
- const nbuf = new u8(Math.max(bl * 2, l));
28210
- nbuf.set(buf);
28211
- buf = nbuf;
28212
- }
28213
- };
28214
- let final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
28215
- const tbts = sl * 8;
28216
- do {
28217
- if (!lm) {
28218
- final = bits(dat, pos, 1);
28219
- const type = bits(dat, pos + 1, 3);
28220
- pos += 3;
28221
- if (!type) {
28222
- const s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
28223
- if (t > sl) {
28224
- if (noSt) err(0);
28225
- break;
28226
- }
28227
- if (noBuf) cbuf(bt + l);
28228
- buf.set(dat.subarray(s, t), bt);
28229
- st.b = bt += l, st.p = pos = t * 8, st.f = final;
28230
- continue;
28231
- } else if (type == 1) lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
28232
- else if (type == 2) {
28233
- const hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
28234
- const tl = hLit + bits(dat, pos + 5, 31) + 1;
28235
- pos += 14;
28236
- const ldt = new u8(tl);
28237
- const clt = new u8(19);
28238
- for (let i = 0; i < hcLen; ++i) {
28239
- clt[clim[i]] = bits(dat, pos + i * 3, 7);
28240
- }
28241
- pos += hcLen * 3;
28242
- const clb = max(clt), clbmsk = (1 << clb) - 1;
28243
- const clm = hMap(clt, clb, 1);
28244
- for (let i = 0; i < tl; ) {
28245
- const r = clm[bits(dat, pos, clbmsk)];
28246
- pos += r & 15;
28247
- const s = r >>> 4;
28248
- if (s < 16) {
28249
- ldt[i++] = s;
28250
- } else {
28251
- let c = 0, n = 0;
28252
- if (s == 16) n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
28253
- else if (s == 17) n = 3 + bits(dat, pos, 7), pos += 3;
28254
- else if (s == 18) n = 11 + bits(dat, pos, 127), pos += 7;
28255
- while (n--) ldt[i++] = c;
28256
- }
28257
- }
28258
- const lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
28259
- lbt = max(lt);
28260
- dbt = max(dt);
28261
- lm = hMap(lt, lbt, 1);
28262
- dm = hMap(dt, dbt, 1);
28263
- } else err(1);
28264
- if (pos > tbts) {
28265
- if (noSt) err(0);
28266
- break;
28267
- }
28268
- }
28269
- if (noBuf) cbuf(bt + 131072);
28270
- const lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
28271
- let lpos = pos;
28272
- for (; ; lpos = pos) {
28273
- const c = lm[bits16(dat, pos) & lms], sym = c >>> 4;
28274
- pos += c & 15;
28275
- if (pos > tbts) {
28276
- if (noSt) err(0);
28277
- break;
28278
- }
28279
- if (!c) err(2);
28280
- if (sym < 256) buf[bt++] = sym;
28281
- else if (sym == 256) {
28282
- lpos = pos, lm = void 0;
28283
- break;
28284
- } else {
28285
- let add = sym - 254;
28286
- if (sym > 264) {
28287
- const i = sym - 257, b = fleb[i];
28288
- add = bits(dat, pos, (1 << b) - 1) + fl[i];
28289
- pos += b;
28290
- }
28291
- const d = dm[bits16(dat, pos) & dms], dsym = d >>> 4;
28292
- if (!d) err(3);
28293
- pos += d & 15;
28294
- let dt = fd[dsym];
28295
- if (dsym > 3) {
28296
- const b = fdeb[dsym];
28297
- dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
28298
- }
28299
- if (pos > tbts) {
28300
- if (noSt) err(0);
28301
- break;
28302
- }
28303
- if (noBuf) cbuf(bt + 131072);
28304
- const end = bt + add;
28305
- for (; bt < end; bt += 4) {
28306
- buf[bt] = buf[bt - dt];
28307
- buf[bt + 1] = buf[bt + 1 - dt];
28308
- buf[bt + 2] = buf[bt + 2 - dt];
28309
- buf[bt + 3] = buf[bt + 3 - dt];
28310
- }
28311
- bt = end;
28312
- }
28313
- }
28314
- st.l = lm, st.p = lpos, st.b = bt, st.f = final;
28315
- if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt;
28316
- } while (!final);
28317
- return bt == buf.length ? buf : slc(buf, 0, bt);
28318
- };
28319
- gzs = (d) => {
28320
- if (d[0] != 31 || d[1] != 139 || d[2] != 8) err(6, "invalid gzip data");
28321
- const flg = d[3];
28322
- let st = 10;
28323
- if (flg & 4) st += d[10] | (d[11] << 8) + 2;
28324
- for (let zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]) ;
28325
- return st + (flg & 2);
28326
- };
28327
- gzl = (d) => {
28328
- const l = d.length;
28329
- return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;
28330
- };
28331
- zlv = (d) => {
28332
- if ((d[0] & 15) != 8 || d[0] >>> 4 > 7 || (d[0] << 8 | d[1]) % 31) err(6, "invalid zlib data");
28333
- if (d[1] & 32) err(6, "invalid zlib data: preset dictionaries not supported");
28334
- };
28335
- Inflate = class {
28336
- /**
28337
- * Creates an inflation stream
28338
- * @param cb The callback to call whenever data is inflated
28339
- */
28340
- constructor(cb) {
28341
- this.ondata = cb;
28342
- }
28343
- /** Persistent bit-reader and Huffman decoding state. */
28344
- s = {};
28345
- /** Compression options or retained output window for this stream. */
28346
- o;
28347
- /** Compressed bytes pending decoding. */
28348
- p = new u8(0);
28349
- /** Whether the stream has received its final chunk. */
28350
- d;
28351
- /**
28352
- * The handler to call whenever data is available
28353
- */
28354
- ondata;
28355
- /** Appends pending input after checking stream lifecycle. */
28356
- e(c) {
28357
- if (!this.ondata) err(5);
28358
- if (this.d) err(4);
28359
- const l = this.p.length;
28360
- const n = new u8(l + c.length);
28361
- n.set(this.p), n.set(c, l), this.p = n;
28362
- }
28363
- /** Decodes pending input and retains the sliding window. */
28364
- c(final) {
28365
- this.d = this.s.i = final || false;
28366
- const bts = this.s.b;
28367
- const dt = inflt(this.p, this.o, this.s);
28368
- this.ondata(slc(dt, bts, this.s.b), this.d);
28369
- this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;
28370
- this.p = slc(this.p, this.s.p / 8 | 0), this.s.p &= 7;
28371
- }
28372
- /**
28373
- * Pushes a chunk to be inflated
28374
- * @param chunk The chunk to push
28375
- * @param final Whether this is the final chunk
28376
- */
28377
- push(chunk, final) {
28378
- this.e(chunk), this.c(final);
28379
- }
28380
- };
28381
- Gunzip = class extends Inflate {
28382
- /** Whether the stream header still needs to be emitted or consumed. */
28383
- v = 1;
28384
- /**
28385
- * Creates a GUNZIP stream
28386
- * @param cb The callback to call whenever data is inflated
28387
- */
28388
- constructor(cb) {
28389
- super(cb);
28390
- }
28391
- /**
28392
- * Pushes a chunk to be GUNZIPped
28393
- * @param chunk The chunk to push
28394
- * @param final Whether this is the last chunk
28395
- */
28396
- push(chunk, final) {
28397
- Inflate.prototype.e.call(this, chunk);
28398
- if (this.v) {
28399
- const s = this.p.length > 3 ? gzs(this.p) : 4;
28400
- if (s >= this.p.length && !final) return;
28401
- this.p = this.p.subarray(s), this.v = 0;
28402
- }
28403
- if (final) {
28404
- if (this.p.length < 8) err(6, "invalid gzip data");
28405
- this.p = this.p.subarray(0, -8);
28406
- }
28407
- Inflate.prototype.c.call(this, final);
28408
- }
28409
- };
28410
- Unzlib = class extends Inflate {
28411
- /** Whether the stream header still needs to be emitted or consumed. */
28412
- v = 1;
28413
- /**
28414
- * Creates a Zlib decompression stream
28415
- * @param cb The callback to call whenever data is inflated
28416
- */
28417
- constructor(cb) {
28418
- super(cb);
28419
- }
28420
- /**
28421
- * Pushes a chunk to be unzlibbed
28422
- * @param chunk The chunk to push
28423
- * @param final Whether this is the last chunk
28424
- */
28425
- push(chunk, final) {
28426
- Inflate.prototype.e.call(this, chunk);
28427
- if (this.v) {
28428
- if (this.p.length < 2 && !final) return;
28429
- this.p = this.p.subarray(2), this.v = 0;
28430
- }
28431
- if (final) {
28432
- if (this.p.length < 4) err(6, "invalid zlib data");
28433
- this.p = this.p.subarray(0, -4);
28434
- }
28435
- Inflate.prototype.c.call(this, final);
28436
- }
28437
- };
28438
- }
28439
- });
28440
-
28441
- // ../../modules/compression/src/lib/fflate-stream.ts
28442
- async function* transformFflateBatches(processor, inputBatches) {
28443
- const chunks = [];
28444
- processor.ondata = (data) => {
28445
- chunks.push(data.slice().buffer);
28446
- };
28447
- for await (const batch of inputBatches) {
28448
- processor.push(new Uint8Array(batch), false);
28449
- yield* chunks.splice(0);
28450
- }
28451
- processor.push(new Uint8Array(0), true);
28452
- yield* chunks;
28453
- }
28454
- var init_fflate_stream = __esm({
28455
- "../../modules/compression/src/lib/fflate-stream.ts"() {
28456
- "use strict";
28457
- }
28458
- });
28459
-
28460
- // ../../modules/compression/src/deflate-decompressor-fflate.ts
28461
- var DeflateFflateDecompressor;
28462
- var init_deflate_decompressor_fflate = __esm({
28463
- "../../modules/compression/src/deflate-decompressor-fflate.ts"() {
28464
- "use strict";
28465
- init_fflate();
28466
- init_compression();
28467
- init_fflate_stream();
28468
- DeflateFflateDecompressor = class extends Decompressor {
28469
- name = "deflate";
28470
- extensions = [];
28471
- contentEncodings = ["deflate"];
28472
- isSupported = true;
28473
- options;
28474
- constructor(options = {}) {
28475
- super(options);
28476
- this.options = options;
28477
- }
28478
- /** Decompresses one zlib-wrapped DEFLATE payload synchronously. */
28479
- decompressSync(input) {
28480
- const bytes = new Uint8Array(input);
28481
- const output = this.options.raw ? inflateSync(bytes) : unzlibSync(bytes);
28482
- return output.slice().buffer;
28483
- }
28484
- /** Decompresses DEFLATE batches incrementally. */
28485
- async *decompressBatches(inputBatches) {
28486
- const processor = this.options.raw ? new Inflate() : new Unzlib();
28487
- yield* transformFflateBatches(processor, inputBatches);
28488
- }
28489
- };
28490
- }
28491
- });
28492
-
28493
27307
  // ../../modules/compression/src/deflate-decompressor.ts
28494
- var deflate_decompressor_exports = {};
28495
- __export(deflate_decompressor_exports, {
28496
- DeflateDecompressor: () => DeflateDecompressor
28497
- });
28498
27308
  var DeflateDecompressor;
28499
27309
  var init_deflate_decompressor = __esm({
28500
27310
  "../../modules/compression/src/deflate-decompressor.ts"() {
28501
27311
  "use strict";
28502
- init_deflate_decompressor_fflate();
27312
+ init_deflate_decompressor_compress_utils();
28503
27313
  init_decompression_stream();
28504
- DeflateDecompressor = class extends DeflateFflateDecompressor {
28505
- constructor(options = {}) {
28506
- super(options);
28507
- }
28508
- /** Decompresses with the built-in stream when available, then falls back to fflate. */
28509
- async decompress(input) {
27314
+ DeflateDecompressor = class extends DeflateCompressUtilsDecompressor {
27315
+ /** Decompresses with native streams when available, otherwise lazily initializes WASM. */
27316
+ async decompress(input, size) {
28510
27317
  if (this.options.useNative !== false) {
28511
- const format = this.options.raw ? "deflate-raw" : "deflate";
28512
- const output = await decompressWithNativeDecompressionStream(input, format);
27318
+ const output = await decompressWithNativeDecompressionStream(
27319
+ input,
27320
+ this.options.raw ? "deflate-raw" : "deflate"
27321
+ );
28513
27322
  if (output) return output;
28514
27323
  }
28515
- return this.decompressSync(input);
27324
+ return super.decompress(input, size);
28516
27325
  }
28517
- /** Decompresses batches with a built-in or fflate stream. */
27326
+ /** Streams native batches when available, otherwise uses the WASM stream. */
28518
27327
  async *decompressBatches(inputBatches) {
28519
27328
  if (this.options.useNative !== false) {
28520
- const format = this.options.raw ? "deflate-raw" : "deflate";
28521
- const output = decompressBatchesWithNativeDecompressionStream(inputBatches, format);
27329
+ const output = decompressBatchesWithNativeDecompressionStream(
27330
+ inputBatches,
27331
+ this.options.raw ? "deflate-raw" : "deflate"
27332
+ );
28522
27333
  if (output) {
28523
27334
  yield* output;
28524
27335
  return;
@@ -28530,303 +27341,679 @@ var init_deflate_decompressor = __esm({
28530
27341
  }
28531
27342
  });
28532
27343
 
28533
- // ../../modules/compression/src/gzip-decompressor-fflate.ts
28534
- var GZipFflateDecompressor;
28535
- var init_gzip_decompressor_fflate = __esm({
28536
- "../../modules/compression/src/gzip-decompressor-fflate.ts"() {
28537
- "use strict";
28538
- init_fflate();
28539
- init_compression();
28540
- init_fflate_stream();
28541
- GZipFflateDecompressor = class extends Decompressor {
28542
- name = "gzip";
28543
- extensions = ["gz", "gzip"];
28544
- contentEncodings = ["gzip", "x-gzip"];
28545
- isSupported = true;
28546
- constructor(options = {}) {
28547
- super(options);
28548
- }
28549
- /** Decompresses one GZIP payload synchronously. */
28550
- decompressSync(input) {
28551
- return gunzipSync(new Uint8Array(input)).slice().buffer;
28552
- }
28553
- /** Decompresses GZIP batches incrementally. */
28554
- async *decompressBatches(inputBatches) {
28555
- yield* transformFflateBatches(new Gunzip(), inputBatches);
28556
- }
28557
- };
28558
- }
28559
- });
28560
-
28561
- // ../../modules/compression/src/gzip-decompressor.ts
28562
- var gzip_decompressor_exports = {};
28563
- __export(gzip_decompressor_exports, {
28564
- GZipDecompressor: () => GZipDecompressor
28565
- });
28566
- var GZipDecompressor;
28567
- var init_gzip_decompressor = __esm({
28568
- "../../modules/compression/src/gzip-decompressor.ts"() {
27344
+ // ../../modules/zip/src/zip-archive.ts
27345
+ async function openZipArchive(input, options = {}) {
27346
+ return await ZipArchive.open(input, options);
27347
+ }
27348
+ function normalizeZipInput(input) {
27349
+ if (input instanceof ArrayBuffer) return new BlobFile(input);
27350
+ if (ArrayBuffer.isView(input))
27351
+ return new BlobFile(
27352
+ new Blob([new Uint8Array(input.buffer, input.byteOffset, input.byteLength).slice()])
27353
+ );
27354
+ if (input instanceof Blob) return new BlobFile(input);
27355
+ return input;
27356
+ }
27357
+ function minimumBigInt(left, right) {
27358
+ return left < right ? left : right;
27359
+ }
27360
+ var DEFAULT_OPTIONS, ZipArchive;
27361
+ var init_zip_archive = __esm({
27362
+ "../../modules/zip/src/zip-archive.ts"() {
28569
27363
  "use strict";
28570
- init_gzip_decompressor_fflate();
28571
- init_decompression_stream();
28572
- GZipDecompressor = class extends GZipFflateDecompressor {
28573
- options;
28574
- constructor(options = {}) {
28575
- super(options);
28576
- this.options = options;
28577
- }
28578
- /** Decompresses with the built-in stream when available, then falls back to fflate. */
28579
- async decompress(input) {
28580
- if (this.options.useNative !== false) {
28581
- const output = await decompressWithNativeDecompressionStream(input, "gzip");
28582
- if (output) return output;
27364
+ init_src2();
27365
+ init_deflate_decompressor();
27366
+ init_src11();
27367
+ init_zip_entry_metadata();
27368
+ init_zip_serialization();
27369
+ DEFAULT_OPTIONS = {
27370
+ maxArchiveBytes: 1024n ** 4n,
27371
+ maxDirectoryBytes: 32 * 1024 * 1024,
27372
+ maxEntries: 1e5,
27373
+ maxReadBytes: 1024 * 1024,
27374
+ maxCompressedBytes: 64n * 1024n * 1024n,
27375
+ maxDecodedBytes: 64n * 1024n * 1024n,
27376
+ chunkBytes: 64 * 1024
27377
+ };
27378
+ ZipArchive = class _ZipArchive {
27379
+ /** Archive byte length, without losing ZIP64 precision. */
27380
+ size;
27381
+ /** Archive comment, decoded using legacy ZIP CP437. */
27382
+ comment;
27383
+ /** Shared file limits captured at open time. */
27384
+ limits;
27385
+ /** Owned random-access transport. */
27386
+ file;
27387
+ /** File lifetime, including in-flight operations. */
27388
+ controller = new AbortController();
27389
+ /** Initialization/caller cancellation combined with close. */
27390
+ signal;
27391
+ /** Validated directory boundary. */
27392
+ directory;
27393
+ /** A single directory-index promise shared by concurrent lookups. */
27394
+ directoryPromise;
27395
+ /** Local-header validation shared by repeated path reads. */
27396
+ entriesByOffset = /* @__PURE__ */ new Map();
27397
+ /** Central-validated named lookups share their local-header work. */
27398
+ entriesByPath = /* @__PURE__ */ new Map();
27399
+ /** Next local-header boundary for central-validated, nonoverlapping payloads. */
27400
+ nextOffsets = /* @__PURE__ */ new Map();
27401
+ /** Only entries issued by this archive can be used for reads. */
27402
+ issuedEntries = /* @__PURE__ */ new WeakSet();
27403
+ /** Idempotent file cleanup, including open failure. */
27404
+ closePromise;
27405
+ /** Captures the owned transport and validates independent limits. */
27406
+ constructor(file, size, options) {
27407
+ this.file = file;
27408
+ this.size = size;
27409
+ this.comment = "";
27410
+ this.limits = {
27411
+ maxArchiveBytes: options.maxArchiveBytes ?? DEFAULT_OPTIONS.maxArchiveBytes,
27412
+ maxDirectoryBytes: options.maxDirectoryBytes ?? DEFAULT_OPTIONS.maxDirectoryBytes,
27413
+ maxEntries: options.maxEntries ?? DEFAULT_OPTIONS.maxEntries,
27414
+ maxReadBytes: options.maxReadBytes ?? DEFAULT_OPTIONS.maxReadBytes,
27415
+ maxCompressedBytes: options.maxCompressedBytes ?? DEFAULT_OPTIONS.maxCompressedBytes,
27416
+ maxDecodedBytes: options.maxDecodedBytes ?? DEFAULT_OPTIONS.maxDecodedBytes,
27417
+ chunkBytes: options.chunkBytes ?? DEFAULT_OPTIONS.chunkBytes
27418
+ };
27419
+ for (const [name18, value] of Object.entries(this.limits)) {
27420
+ const bigintLimit = ["maxArchiveBytes", "maxCompressedBytes", "maxDecodedBytes"].includes(
27421
+ name18
27422
+ );
27423
+ if (bigintLimit ? typeof value !== "bigint" || value < 0n : typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
27424
+ throw new RangeError(`Invalid ZIP ${name18} limit`);
28583
27425
  }
28584
- return this.decompressSync(input);
27426
+ this.signal = options.signal ? AbortSignal.any([this.controller.signal, options.signal]) : this.controller.signal;
28585
27427
  }
28586
- /** Decompresses batches with a built-in or fflate stream. */
28587
- async *decompressBatches(inputBatches) {
28588
- if (this.options.useNative !== false) {
28589
- const output = decompressBatchesWithNativeDecompressionStream(inputBatches, "gzip");
28590
- if (output) {
28591
- yield* output;
28592
- return;
28593
- }
27428
+ /** Initializes directory bounds without scanning entries or reading their payloads. */
27429
+ static async open(input, options = {}) {
27430
+ const file = normalizeZipInput(input);
27431
+ let archive;
27432
+ try {
27433
+ const advertisedSize = file.bigsize;
27434
+ const status = advertisedSize === void 0 || advertisedSize === 0n ? await file.stat?.() : void 0;
27435
+ const reportedBigsize = status?.bigsize ?? file.bigsize;
27436
+ const size = reportedBigsize !== void 0 && reportedBigsize !== 0n ? reportedBigsize : BigInt(status?.size || file.size);
27437
+ archive = new _ZipArchive(file, size, options);
27438
+ archive.signal.throwIfAborted();
27439
+ if (size < 22n || size > archive.limits.maxArchiveBytes)
27440
+ throw new RangeError("ZIP archive size limit or minimum header size");
27441
+ archive.directory = await archive.readDirectoryLocation();
27442
+ Object.defineProperty(archive, "comment", { value: archive.directory.comment });
27443
+ return archive;
27444
+ } catch (error) {
27445
+ if (archive) await archive.close();
27446
+ else await file.close();
27447
+ throw error;
28594
27448
  }
28595
- yield* super.decompressBatches(inputBatches);
28596
- }
28597
- };
28598
- }
28599
- });
28600
-
28601
- // ../../modules/compression/src/default-codecs.ts
28602
- var UNCOMPRESSED, DEFLATE, GZIP, NoDecompressor2, DeflateDecompressor2, GZipDecompressor2;
28603
- var init_default_codecs = __esm({
28604
- "../../modules/compression/src/default-codecs.ts"() {
28605
- "use strict";
28606
- init_lazy_compression();
28607
- UNCOMPRESSED = { name: "uncompressed", extensions: [], contentEncodings: [] };
28608
- DEFLATE = { name: "deflate", extensions: [], contentEncodings: ["deflate"] };
28609
- GZIP = { name: "gzip", extensions: ["gz"], contentEncodings: ["gzip"] };
28610
- NoDecompressor2 = class extends LazyDecompressor {
28611
- constructor(options = {}) {
28612
- super(UNCOMPRESSED, async () => (await Promise.resolve().then(() => (init_no_decompressor(), no_decompressor_exports))).NoDecompressor, options);
28613
27449
  }
28614
- };
28615
- DeflateDecompressor2 = class extends LazyDecompressor {
28616
- constructor(options = {}) {
28617
- super(
28618
- DEFLATE,
28619
- async () => (await Promise.resolve().then(() => (init_deflate_decompressor(), deflate_decompressor_exports))).DeflateDecompressor,
28620
- options,
28621
- options.raw ? "deflate-raw" : "deflate"
28622
- );
28623
- }
28624
- };
28625
- GZipDecompressor2 = class extends LazyDecompressor {
28626
- constructor(options = {}) {
28627
- super(
28628
- GZIP,
28629
- async () => (await Promise.resolve().then(() => (init_gzip_decompressor(), gzip_decompressor_exports))).GZipDecompressor,
28630
- options,
28631
- "gzip"
28632
- );
28633
- }
28634
- };
28635
- }
28636
- });
28637
-
28638
- // ../../modules/compression/src/index.ts
28639
- var init_src12 = __esm({
28640
- "../../modules/compression/src/index.ts"() {
28641
- "use strict";
28642
- init_default_codecs();
28643
- }
28644
- });
28645
-
28646
- // ../../modules/zip/src/filesystems/zip-filesystem.ts
28647
- var ZIP_COMPRESSION_HANDLERS, ZipFileSystem;
28648
- var init_zip_filesystem = __esm({
28649
- "../../modules/zip/src/filesystems/zip-filesystem.ts"() {
28650
- "use strict";
28651
- init_src2();
28652
- init_cd_file_header();
28653
- init_local_file_header();
28654
- init_src12();
28655
- init_IndexedArchive();
28656
- init_readable_file_utils();
28657
- ZIP_COMPRESSION_HANDLERS = {
28658
- /** No compression */
28659
- 0: async (compressedFile) => compressedFile,
28660
- /** Deflation */
28661
- 8: async (compressedFile) => {
28662
- const compression = new DeflateDecompressor2({ raw: true });
28663
- const decompressedData = await compression.decompress(compressedFile);
28664
- return decompressedData;
28665
- }
28666
- };
28667
- ZipFileSystem = class {
28668
- /** File instance */
28669
- file = null;
28670
- fileName;
28671
- archive = null;
28672
27450
  /**
28673
- * Constructor
28674
- * @param file - instance of ReadableFile or file path string
27451
+ * Appends one STORE entry through validated container metadata and the native serializer.
27452
+ * Internal composition operation: callers own the writable file and discard it on write failure.
27453
+ * Existing payload offsets, central metadata and archive comments are retained.
28675
27454
  */
28676
- constructor(file) {
28677
- if (typeof file === "string") {
28678
- this.fileName = file;
28679
- if (isBrowser) {
28680
- throw new Error("ZipFileSystem cannot open file paths in browser environments");
27455
+ static async appendEntry(file, path, data, options = {}) {
27456
+ const archive = await _ZipArchive.open(file, options);
27457
+ try {
27458
+ validateZipPath(path);
27459
+ if (archive.directory.offset > BigInt(Number.MAX_SAFE_INTEGER))
27460
+ throw new RangeError("ZIP append transport offset exceeds safe integer range");
27461
+ if (await archive.getEntry(path)) throw new Error("ZIP entry already exists");
27462
+ for await (const _entry of archive.entries()) {
28681
27463
  }
28682
- this.file = new NodeFileFacade(file);
28683
- } else if (file instanceof Blob || file instanceof ArrayBuffer) {
28684
- this.file = new BlobFile(file);
28685
- } else if (file instanceof IndexedArchive) {
28686
- this.file = file.file;
28687
- this.archive = file;
28688
- this.fileName = file.fileName;
28689
- } else {
28690
- this.file = file;
27464
+ const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
27465
+ if (path.endsWith("/") && bytes.length)
27466
+ throw new Error("ZIP directory payload must be empty");
27467
+ const entry = {
27468
+ nameBytes: encodeUtf8Text(path),
27469
+ date: /* @__PURE__ */ new Date("1980-01-01T00:00:00Z"),
27470
+ flags: 2048,
27471
+ method: 0,
27472
+ crc32: 0,
27473
+ size: BigInt(bytes.length),
27474
+ compressedSize: BigInt(bytes.length),
27475
+ localHeaderOffset: archive.directory.offset,
27476
+ zip64: archive.directory.offset >= 0xffffffffn || bytes.length >= 4294967295
27477
+ };
27478
+ let local = encodeZipLocalHeader(entry);
27479
+ let central = encodeZipCentralHeader(entry);
27480
+ const directoryBytes = archive.directory.size + BigInt(central.length);
27481
+ const directoryOffset = archive.directory.offset + BigInt(local.length + bytes.length);
27482
+ const count = archive.directory.count + 1n;
27483
+ const comment = new Uint8Array(
27484
+ await archive.readExact(
27485
+ archive.size - BigInt(archive.comment.length),
27486
+ archive.comment.length
27487
+ )
27488
+ );
27489
+ const footer = encodeZipEndRecords(
27490
+ count,
27491
+ directoryBytes,
27492
+ directoryOffset,
27493
+ directoryOffset + directoryBytes > 0x7fffffffn || count >= 0xffffn,
27494
+ comment
27495
+ );
27496
+ if (count > BigInt(archive.limits.maxEntries) || directoryBytes > BigInt(archive.limits.maxDirectoryBytes) || directoryOffset + directoryBytes + BigInt(footer.length) > archive.limits.maxArchiveBytes)
27497
+ throw new RangeError("ZIP append metadata/archive limit exceeded");
27498
+ entry.crc32 = calculateZipChecksum(bytes);
27499
+ local = encodeZipLocalHeader(entry);
27500
+ central = encodeZipCentralHeader(entry);
27501
+ const directory = new Uint8Array(
27502
+ await archive.readExact(archive.directory.offset, Number(archive.directory.size))
27503
+ );
27504
+ archive.signal.throwIfAborted();
27505
+ await file.truncate(Number(archive.directory.offset));
27506
+ for (const chunk of [local, bytes, directory, central, footer]) {
27507
+ archive.signal.throwIfAborted();
27508
+ await file.append(chunk);
27509
+ }
27510
+ archive.signal.throwIfAborted();
27511
+ } finally {
27512
+ await archive.close();
28691
27513
  }
28692
27514
  }
28693
- /** Clean up resources */
28694
- async destroy() {
28695
- if (this.file) {
28696
- await this.file.close();
28697
- }
27515
+ /** Enumerates validated entries in central-directory order; metadata is indexed once. */
27516
+ async *entries() {
27517
+ for (const path of (await this.getDirectory()).keys()) yield await this.getEntry(path);
28698
27518
  }
28699
27519
  /**
28700
- * Get file names list from zip archive
28701
- * @returns array of file names
27520
+ * Reads the final central entry using at most one maximum-sized header from the directory tail.
27521
+ * Ambiguous header signatures in comments fall back to the cached directory. This supports
27522
+ * final-index discovery without scanning a large directory in the normal indexed profile.
28702
27523
  */
28703
- async readdir() {
28704
- if (!this.file) {
28705
- throw new Error("No data detected in the zip archive");
28706
- }
28707
- const fileNames = [];
28708
- const zipCDIterator = makeZipCDHeaderIterator(this.file);
28709
- for await (const cdHeader of zipCDIterator) {
28710
- fileNames.push(cdHeader.fileName);
27524
+ async getLastEntry() {
27525
+ this.signal.throwIfAborted();
27526
+ if (!this.directory.count) return void 0;
27527
+ const length = Number(minimumBigInt(this.directory.size, 46n + 3n * 65535n));
27528
+ const bytes = new Uint8Array(
27529
+ await this.readExact(this.directory.offset + this.directory.size - BigInt(length), length)
27530
+ );
27531
+ const view = new DataView(bytes.buffer);
27532
+ const positions = [];
27533
+ for (let position = 0; position + 46 <= length; position++) {
27534
+ if (view.getUint32(position, true) !== 33639248) continue;
27535
+ const end = position + 46 + view.getUint16(position + 28, true) + view.getUint16(position + 30, true) + view.getUint16(position + 32, true);
27536
+ if (end === length) positions.push(position);
27537
+ }
27538
+ if (positions.length !== 1) {
27539
+ const headers = [...(await this.getDirectory()).values()];
27540
+ return await this.getEntry(headers[headers.length - 1].path);
27541
+ }
27542
+ const metadata = decodeZipHeader(bytes.subarray(positions[0]), true);
27543
+ return await this.getValidatedEntry(metadata.localHeaderOffset, metadata);
27544
+ }
27545
+ /** Looks up a canonical path; returns undefined when the entry is absent. */
27546
+ async getEntry(path) {
27547
+ this.signal.throwIfAborted();
27548
+ const metadata = (await this.getDirectory()).get(path);
27549
+ if (!metadata) return void 0;
27550
+ let promise = this.entriesByPath.get(path);
27551
+ if (!promise) {
27552
+ promise = this.getValidatedEntry(metadata.localHeaderOffset, metadata).catch((error) => {
27553
+ this.entriesByPath.delete(path);
27554
+ throw error;
27555
+ });
27556
+ this.entriesByPath.set(path, promise);
28711
27557
  }
28712
- return fileNames;
27558
+ return await promise;
28713
27559
  }
28714
27560
  /**
28715
- * Get file metadata
28716
- * @param filename - name of a file
28717
- * @returns central directory data
27561
+ * Validates a populated local header at an index-provided offset without a directory scan.
27562
+ * Descriptor entries fall back to the shared directory because their local sizes may be zero.
27563
+ * Direct access validates local layout/bounds; central consistency requires named lookup.
28718
27564
  */
28719
- async stat(filename2) {
28720
- const cdFileHeader = await this.getCDFileHeader(filename2);
28721
- return { ...cdFileHeader, size: Number(cdFileHeader.uncompressedSize) };
28722
- }
28723
- /**
28724
- * Implementation of fetch against this file system
28725
- * @param filename - name of a file
28726
- * @returns - Response with file data
28727
- */
28728
- async fetch(filename2) {
28729
- if (this.fileName && filename2.indexOf(this.fileName) === 0) {
28730
- filename2 = filename2.substring(this.fileName.length + 1);
28731
- }
28732
- let uncompressedFile;
28733
- if (this.archive) {
28734
- uncompressedFile = await this.archive.getFile(filename2, "http");
28735
- } else {
28736
- if (!this.file) {
28737
- throw new Error("No data detected in the zip archive");
28738
- }
28739
- const cdFileHeader = await this.getCDFileHeader(filename2);
28740
- const localFileHeader = await parseZipLocalFileHeader(
28741
- cdFileHeader.localHeaderOffset,
28742
- this.file
28743
- );
28744
- if (!localFileHeader) {
28745
- throw new Error("Local file header has not been found in the zip archive`");
28746
- }
28747
- const compressionHandler = ZIP_COMPRESSION_HANDLERS[localFileHeader.compressionMethod.toString()];
28748
- if (!compressionHandler) {
28749
- throw Error("Only Deflation compression is supported");
27565
+ async getEntryAt(localHeaderOffset) {
27566
+ this.signal.throwIfAborted();
27567
+ const existing = this.entriesByOffset.get(localHeaderOffset);
27568
+ if (existing) return await existing;
27569
+ const metadata = await this.readLocalHeader(localHeaderOffset);
27570
+ if (metadata.header.flags & 8) {
27571
+ for (const header of (await this.getDirectory()).values())
27572
+ if (header.localHeaderOffset === localHeaderOffset)
27573
+ return await this.getEntry(header.path);
27574
+ throw new Error("Invalid ZIP archive: indexed offset missing from directory");
27575
+ }
27576
+ return await this.getValidatedEntry(localHeaderOffset, void 0, metadata);
27577
+ }
27578
+ /** Reads one complete entry and verifies its decoded size and CRC-32. */
27579
+ async read(entryOrPath, options = {}) {
27580
+ const signal = this.getReadSignal(options);
27581
+ signal.throwIfAborted();
27582
+ const entry = await this.resolveEntry(entryOrPath);
27583
+ signal.throwIfAborted();
27584
+ this.checkEntryBudget(entry);
27585
+ if (entry.size > BigInt(Number.MAX_SAFE_INTEGER))
27586
+ throw new RangeError("ZIP allocation is not safely representable");
27587
+ const output = new Uint8Array(Number(entry.size));
27588
+ let offset = 0;
27589
+ for await (const chunk of this.readInBatches(entry, options)) {
27590
+ output.set(chunk, offset);
27591
+ offset += chunk.byteLength;
27592
+ }
27593
+ return output.buffer;
27594
+ }
27595
+ /** Streams decoded chunks with backpressure; consuming through completion verifies CRC-32. */
27596
+ async *readInBatches(entryOrPath, options = {}) {
27597
+ const signal = this.getReadSignal(options);
27598
+ signal.throwIfAborted();
27599
+ const entry = await this.resolveEntry(entryOrPath);
27600
+ signal.throwIfAborted();
27601
+ this.checkEntryBudget(entry);
27602
+ let decodedBytes = 0n;
27603
+ let checksum = 0;
27604
+ const hash = new CRC32Hash({
27605
+ crypto: {
27606
+ onEnd: (result) => {
27607
+ checksum = Number.parseInt(result.hash, 16);
27608
+ }
28750
27609
  }
28751
- const compressedFile = await readRange(
28752
- this.file,
28753
- localFileHeader.fileDataOffset,
28754
- localFileHeader.fileDataOffset + cdFileHeader.compressedSize
28755
- );
28756
- uncompressedFile = await compressionHandler(compressedFile);
28757
- }
28758
- const response = new Response(uncompressedFile);
28759
- Object.defineProperty(response, "url", {
28760
- value: filename2 ? `${this.fileName || ""}/${filename2}` : this.fileName || ""
28761
27610
  });
28762
- return response;
27611
+ const compressed = this.readPayloadChunks(entry, signal);
27612
+ const decoded = entry.compression === "store" ? compressed : new DeflateDecompressor({ raw: true }).decompressBatches(compressed);
27613
+ for await (const chunk of hash.hashBatches(decoded, "hex")) {
27614
+ signal.throwIfAborted();
27615
+ decodedBytes += BigInt(chunk.byteLength);
27616
+ if (decodedBytes > entry.size || decodedBytes > this.limits.maxDecodedBytes)
27617
+ throw new RangeError("ZIP decoded entry size limit exceeded");
27618
+ yield new Uint8Array(chunk);
27619
+ }
27620
+ signal.throwIfAborted();
27621
+ if (decodedBytes !== entry.size) throw new Error("Invalid ZIP archive: decoded size mismatch");
27622
+ if (checksum !== entry.crc32) throw new Error("Invalid ZIP archive: CRC-32 mismatch");
27623
+ }
27624
+ /** Reads only a STORE byte range. Partial reads cannot verify a whole-entry CRC. */
27625
+ async readRange(entryOrPath, options) {
27626
+ const signal = this.getReadSignal(options);
27627
+ signal.throwIfAborted();
27628
+ const entry = await this.resolveEntry(entryOrPath);
27629
+ if (entry.compression !== "store") throw new Error("ZIP ranges require STORE entries");
27630
+ if (options.start < 0n || options.end < options.start || options.end > entry.size || options.end - options.start > BigInt(this.limits.maxReadBytes))
27631
+ throw new RangeError("ZIP byte-range limit exceeded");
27632
+ return await this.readExact(
27633
+ entry.dataOffset + options.start,
27634
+ Number(options.end - options.start),
27635
+ signal
27636
+ );
28763
27637
  }
28764
- /**
28765
- * Get central directory file header
28766
- * @param filename - name of a file
28767
- * @returns central directory file header
28768
- */
28769
- async getCDFileHeader(filename2) {
28770
- if (!this.file) {
28771
- throw new Error("No data detected in the zip archive");
28772
- }
28773
- const zipCDIterator = makeZipCDHeaderIterator(this.file);
28774
- let result = null;
28775
- for await (const cdHeader of zipCDIterator) {
28776
- if (cdHeader.fileName === filename2) {
28777
- result = cdHeader;
27638
+ /** Cancels reads and closes the owned transport exactly once; all subsequent reads reject. */
27639
+ close() {
27640
+ this.controller.abort(new Error("ZIP archive is closed"));
27641
+ this.closePromise ||= this.file.close();
27642
+ return this.closePromise;
27643
+ }
27644
+ /** Resolves a named entry or rejects metadata not issued by this archive. */
27645
+ async resolveEntry(entryOrPath) {
27646
+ this.signal.throwIfAborted();
27647
+ const entry = typeof entryOrPath === "string" ? await this.getEntry(entryOrPath) : entryOrPath;
27648
+ if (!entry || !this.issuedEntries.has(entry))
27649
+ throw new Error("ZIP entry not found or belongs to another archive");
27650
+ return entry;
27651
+ }
27652
+ /** Combines per-read cancellation with the owned lifetime. */
27653
+ getReadSignal(options) {
27654
+ return options.signal ? AbortSignal.any([this.signal, options.signal]) : this.signal;
27655
+ }
27656
+ /** Checks whole-entry consumption before allocation or decompression. */
27657
+ checkEntryBudget(entry) {
27658
+ if (entry.size > this.limits.maxDecodedBytes || entry.compressedSize > this.limits.maxCompressedBytes)
27659
+ throw new RangeError("ZIP entry compressed/decoded byte limit exceeded");
27660
+ }
27661
+ /** Yields compressed bytes without retaining a complete entry. */
27662
+ async *readPayloadChunks(entry, signal) {
27663
+ const chunkBytes = Math.min(this.limits.chunkBytes, this.limits.maxReadBytes);
27664
+ for (let offset = 0n; offset < entry.compressedSize; offset += BigInt(chunkBytes)) {
27665
+ const length = Number(minimumBigInt(BigInt(chunkBytes), entry.compressedSize - offset));
27666
+ yield await this.readExact(entry.dataOffset + offset, length, signal);
27667
+ }
27668
+ }
27669
+ /** Performs exact, bounded physical reads and rejects truncated transports. */
27670
+ async readExact(offset, length, signal = this.signal) {
27671
+ signal.throwIfAborted();
27672
+ if (offset < 0n || !Number.isSafeInteger(length) || length < 0 || offset + BigInt(length) > this.size)
27673
+ throw new Error("Invalid ZIP archive: read outside file");
27674
+ const output = new Uint8Array(length);
27675
+ for (let copied = 0; copied < length; ) {
27676
+ const readBytes = Math.min(length - copied, this.limits.maxReadBytes);
27677
+ const bytes = await this.file.read(offset + BigInt(copied), readBytes, signal);
27678
+ signal.throwIfAborted();
27679
+ if (bytes.byteLength !== readBytes)
27680
+ throw new Error("Invalid ZIP archive: truncated file read");
27681
+ output.set(new Uint8Array(bytes), copied);
27682
+ copied += readBytes;
27683
+ }
27684
+ return output.buffer;
27685
+ }
27686
+ /** Finds an EOCD whose complete comment ends at EOF, not a signature embedded in the comment. */
27687
+ async readDirectoryLocation() {
27688
+ const magic = new DataView(await this.readExact(0n, 4)).getUint32(0, true);
27689
+ if (magic !== 67324752 && magic !== 101010256 && magic !== 101075792)
27690
+ throw new Error("Unsupported ZIP prefix or archive format");
27691
+ const tailLength = Number(minimumBigInt(this.size, 65557n));
27692
+ const tailStart = this.size - BigInt(tailLength);
27693
+ const tail = new DataView(await this.readExact(tailStart, tailLength));
27694
+ let position = -1;
27695
+ for (let candidate = tailLength - 22; candidate >= 0; candidate--) {
27696
+ if (tail.getUint32(candidate, true) !== 101010256 || candidate + 22 + tail.getUint16(candidate + 20, true) !== tailLength)
27697
+ continue;
27698
+ if (position < 0) position = candidate;
27699
+ const emptyDirectoryAtEnd = tail.getUint32(candidate + 12, true) === 0 && BigInt(tail.getUint32(candidate + 16, true)) === tailStart + BigInt(candidate);
27700
+ if (tail.getUint16(candidate + 10, true) !== 0 || emptyDirectoryAtEnd || magic === 101075792) {
27701
+ position = candidate;
28778
27702
  break;
28779
27703
  }
28780
27704
  }
28781
- if (!result) {
28782
- throw new Error("File has not been found in the zip archive");
27705
+ if (position < 0) throw new Error("Invalid ZIP archive: end record not found");
27706
+ const disk = tail.getUint16(position + 4, true);
27707
+ const directoryDisk = tail.getUint16(position + 6, true);
27708
+ if (disk !== 0 && disk !== 65535 || directoryDisk !== 0 && directoryDisk !== 65535)
27709
+ throw new Error("Unsupported split ZIP archive");
27710
+ const onDisk = BigInt(tail.getUint16(position + 8, true));
27711
+ let count = BigInt(tail.getUint16(position + 10, true));
27712
+ let size = BigInt(tail.getUint32(position + 12, true));
27713
+ let offset = BigInt(tail.getUint32(position + 16, true));
27714
+ let footerOffset = tailStart + BigInt(position);
27715
+ let zip64 = false;
27716
+ if (footerOffset >= 20n) {
27717
+ const locator = new DataView(await this.readExact(footerOffset - 20n, 20));
27718
+ const locatorInsideDirectory = size !== 0xffffffffn && offset !== 0xffffffffn && offset + size > footerOffset - 20n;
27719
+ if (locator.getUint32(0, true) === 117853008 && !locatorInsideDirectory) {
27720
+ zip64 = true;
27721
+ if (locator.getUint32(4, true) || locator.getUint32(16, true) !== 1)
27722
+ throw new Error("Unsupported split ZIP64 archive");
27723
+ const zip64Offset = locator.getBigUint64(8, true);
27724
+ const record = new DataView(await this.readExact(zip64Offset, 56));
27725
+ if (record.getUint32(0, true) !== 101075792 || record.getBigUint64(4, true) < 44n || zip64Offset + 12n + record.getBigUint64(4, true) !== footerOffset - 20n || record.getUint32(16, true) || record.getUint32(20, true) || record.getBigUint64(24, true) !== record.getBigUint64(32, true))
27726
+ throw new Error("Invalid ZIP64 end record");
27727
+ const zip64Count = record.getBigUint64(32, true);
27728
+ const zip64Size = record.getBigUint64(40, true);
27729
+ const zip64DirectoryOffset = record.getBigUint64(48, true);
27730
+ if (onDisk !== 0xffffn && onDisk !== zip64Count || count !== 0xffffn && count !== zip64Count || size !== 0xffffffffn && size !== zip64Size || offset !== 0xffffffffn && offset !== zip64DirectoryOffset)
27731
+ throw new Error("Invalid ZIP64 legacy end values");
27732
+ count = zip64Count;
27733
+ size = zip64Size;
27734
+ offset = zip64DirectoryOffset;
27735
+ footerOffset = zip64Offset;
27736
+ } else if (size === 0xffffffffn || offset === 0xffffffffn)
27737
+ throw new Error("Invalid ZIP archive: ZIP64 locator missing");
27738
+ } else if (size === 0xffffffffn || offset === 0xffffffffn)
27739
+ throw new Error("Invalid ZIP archive: ZIP64 locator missing");
27740
+ if (!zip64) {
27741
+ if (disk === 65535 || directoryDisk === 65535)
27742
+ throw new Error("Invalid ZIP archive: ZIP64 locator missing");
27743
+ if (onDisk !== count) throw new Error("Invalid ZIP archive: inconsistent entry counts");
27744
+ }
27745
+ if (count > BigInt(this.limits.maxEntries) || size > BigInt(this.limits.maxDirectoryBytes))
27746
+ throw new RangeError("ZIP directory entry/byte limit exceeded");
27747
+ if (offset + size > footerOffset || size < count * 46n || count === 0n !== (size === 0n))
27748
+ throw new Error("Invalid ZIP archive: directory outside bounds");
27749
+ if (count && new DataView(await this.readExact(offset, 4)).getUint32(0, true) !== 33639248)
27750
+ throw new Error("Invalid ZIP archive: directory signature missing");
27751
+ const comment = decodeZipText(new Uint8Array(tail.buffer, position + 22), false);
27752
+ return { count, size, offset, comment };
27753
+ }
27754
+ /** Indexes central metadata once, without eagerly reading every local header. */
27755
+ getDirectory() {
27756
+ this.signal.throwIfAborted();
27757
+ this.directoryPromise ||= this.readDirectory().catch((error) => {
27758
+ this.directoryPromise = void 0;
27759
+ this.nextOffsets.clear();
27760
+ throw error;
27761
+ });
27762
+ return this.directoryPromise;
27763
+ }
27764
+ /** Parses exact directory records, including comments and Unicode/ZIP64 extras. */
27765
+ async readDirectory() {
27766
+ const bytes = new Uint8Array(
27767
+ await this.readExact(this.directory.offset, Number(this.directory.size))
27768
+ );
27769
+ const view = new DataView(bytes.buffer);
27770
+ const entries = /* @__PURE__ */ new Map();
27771
+ const offsets = /* @__PURE__ */ new Set();
27772
+ let position = 0;
27773
+ for (let index = 0n; index < this.directory.count; index++) {
27774
+ if (position + 46 > bytes.byteLength)
27775
+ throw new Error("Invalid ZIP archive: truncated directory");
27776
+ const length = 46 + view.getUint16(position + 28, true) + view.getUint16(position + 30, true) + view.getUint16(position + 32, true);
27777
+ const header = decodeZipHeader(bytes.subarray(position, position + length), true);
27778
+ if (header.localHeaderOffset + 30n > this.directory.offset)
27779
+ throw new Error("Invalid ZIP archive: local header outside data region");
27780
+ if (entries.has(header.path) || offsets.has(header.localHeaderOffset))
27781
+ throw new Error("Invalid ZIP archive: duplicate path or local-header offset");
27782
+ entries.set(header.path, header);
27783
+ offsets.add(header.localHeaderOffset);
27784
+ position += length;
27785
+ }
27786
+ const sortedOffsets = [...offsets].sort(
27787
+ (left, right) => left < right ? -1 : left > right ? 1 : 0
27788
+ );
27789
+ sortedOffsets.forEach(
27790
+ (offset, index) => this.nextOffsets.set(offset, sortedOffsets[index + 1] ?? this.directory.offset)
27791
+ );
27792
+ if (position !== bytes.byteLength)
27793
+ throw new Error("Invalid ZIP archive: directory length mismatch");
27794
+ return entries;
27795
+ }
27796
+ /** Reads local metadata without inspecting unrelated payloads. */
27797
+ async readLocalHeader(offset) {
27798
+ if (offset < 0n || offset + 30n > this.directory.offset)
27799
+ throw new Error("Invalid ZIP archive: local header outside data region");
27800
+ const fixed = new DataView(await this.readExact(offset, 30));
27801
+ const length = 30 + fixed.getUint16(26, true) + fixed.getUint16(28, true);
27802
+ if (offset + BigInt(length) > this.directory.offset)
27803
+ throw new Error("Invalid ZIP archive: local metadata overlaps directory");
27804
+ const bytes = new Uint8Array(length);
27805
+ bytes.set(new Uint8Array(fixed.buffer));
27806
+ bytes.set(new Uint8Array(await this.readExact(offset + 30n, length - 30)), 30);
27807
+ const header = decodeZipHeader(bytes, false);
27808
+ return { header, dataOffset: offset + BigInt(length) };
27809
+ }
27810
+ /** Shares local validation; a later named lookup additionally verifies central metadata. */
27811
+ async getValidatedEntry(offset, central, localMetadata) {
27812
+ if (central) return await this.validateEntry(offset, central);
27813
+ let entry = this.entriesByOffset.get(offset);
27814
+ if (!entry) {
27815
+ entry = this.validateEntry(offset, void 0, localMetadata).catch((error) => {
27816
+ this.entriesByOffset.delete(offset);
27817
+ throw error;
27818
+ });
27819
+ this.entriesByOffset.set(offset, entry);
27820
+ }
27821
+ return await entry;
27822
+ }
27823
+ /** Validates local/central identity, payload bounds and signed or unsigned descriptors. */
27824
+ async validateEntry(offset, central, localMetadata) {
27825
+ const { header: local, dataOffset } = localMetadata ?? await this.readLocalHeader(offset);
27826
+ const metadata = central || local;
27827
+ const descriptor = Boolean(local.flags & 8);
27828
+ if (central && (central.flags !== local.flags || central.method !== local.method || central.nameBytes.length !== local.nameBytes.length || central.nameBytes.some((value, index) => value !== local.nameBytes[index]) || !descriptor && (central.crc32 !== local.crc32 || central.size !== local.size || central.compressedSize !== local.compressedSize)))
27829
+ throw new Error("Invalid ZIP archive: local/central metadata mismatch");
27830
+ if (metadata.method === 0 && metadata.size !== metadata.compressedSize)
27831
+ throw new Error("Invalid ZIP archive: STORE sizes mismatch");
27832
+ if (central && descriptor && (local.crc32 !== 0 && local.crc32 !== central.crc32 || local.size !== 0n && local.size !== central.size || local.compressedSize !== 0n && local.compressedSize !== central.compressedSize))
27833
+ throw new Error("Invalid ZIP archive: descriptor local/central metadata mismatch");
27834
+ const payloadEnd = dataOffset + metadata.compressedSize;
27835
+ const entryEnd = central ? this.nextOffsets.get(offset) ?? this.directory.offset : this.directory.offset;
27836
+ if (payloadEnd > entryEnd) throw new Error("Invalid ZIP archive: payload overlaps directory");
27837
+ if (descriptor)
27838
+ await this.validateDescriptor(
27839
+ payloadEnd,
27840
+ metadata,
27841
+ local.zip64 || Boolean(central?.zip64),
27842
+ entryEnd
27843
+ );
27844
+ const entry = Object.freeze({
27845
+ path: metadata.path,
27846
+ directory: metadata.path.endsWith("/"),
27847
+ compression: metadata.method === 0 ? "store" : "deflate",
27848
+ size: metadata.size,
27849
+ compressedSize: metadata.compressedSize,
27850
+ crc32: metadata.crc32,
27851
+ localHeaderOffset: offset,
27852
+ dataOffset,
27853
+ comment: central?.comment || ""
27854
+ });
27855
+ this.issuedEntries.add(entry);
27856
+ return entry;
27857
+ }
27858
+ /** Resolves the optional descriptor signature using the expected CRC and sizes. */
27859
+ async validateDescriptor(offset, metadata, zip64, entryEnd) {
27860
+ const length = Number(minimumBigInt(24n, entryEnd - offset));
27861
+ const bytes = new DataView(await this.readExact(offset, length));
27862
+ for (const wide of zip64 ? [true, false] : [false, true]) {
27863
+ if (!wide && (metadata.size > 0xffffffffn || metadata.compressedSize > 0xffffffffn)) continue;
27864
+ const descriptorLength = wide ? 20 : 12;
27865
+ for (const prefix of [4, 0]) {
27866
+ if (length < prefix + descriptorLength || prefix && bytes.getUint32(0, true) !== 134695760)
27867
+ continue;
27868
+ const compressed = wide ? bytes.getBigUint64(prefix + 4, true) : BigInt(bytes.getUint32(prefix + 4, true));
27869
+ const decoded = wide ? bytes.getBigUint64(prefix + 12, true) : BigInt(bytes.getUint32(prefix + 8, true));
27870
+ if (bytes.getUint32(prefix, true) === metadata.crc32 && compressed === metadata.compressedSize && decoded === metadata.size)
27871
+ return;
27872
+ }
28783
27873
  }
28784
- return result;
27874
+ throw new Error("Invalid ZIP archive: data descriptor mismatch");
28785
27875
  }
28786
27876
  };
28787
27877
  }
28788
27878
  });
28789
27879
 
28790
- // ../../modules/zip/src/filesystems/IndexedArchive.ts
28791
- var IndexedArchive;
28792
- var init_IndexedArchive = __esm({
28793
- "../../modules/zip/src/filesystems/IndexedArchive.ts"() {
28794
- "use strict";
28795
- init_zip_filesystem();
28796
- IndexedArchive = class {
28797
- file;
28798
- fileName;
28799
- /**
28800
- * Constructor
28801
- * @param fileProvider - readable file instance for random access
28802
- * @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
28803
- * @param fileName - name of the archive. It is used to add to an URL of a loader context
28804
- */
28805
- constructor(file, hashTable, fileName) {
28806
- this.file = file;
28807
- this.fileName = fileName;
28808
- }
28809
- /**
28810
- * Get file as from order ZIP arhive without using the hash file
28811
- * @param filename - path to the internal file
28812
- * @returns
28813
- */
28814
- async getFileWithoutHash(filename2) {
28815
- const zipFS = new ZipFileSystem(this.file);
28816
- const response = await zipFS.fetch(filename2);
28817
- return await response.arrayBuffer();
27880
+ // ../../modules/zip/src/lib/zip-composition.ts
27881
+ async function generateFileHeaders(fileName, file, offset) {
27882
+ validateZipPath(fileName);
27883
+ const header = {
27884
+ nameBytes: encodeUtf8Text(fileName),
27885
+ date: /* @__PURE__ */ new Date("1980-01-01T00:00:00Z"),
27886
+ flags: 2048,
27887
+ method: 0,
27888
+ crc32: Number.parseInt(await new CRC32Hash().hash(file, "hex"), 16),
27889
+ size: BigInt(file.byteLength),
27890
+ compressedSize: BigInt(file.byteLength),
27891
+ localHeaderOffset: offset,
27892
+ zip64: offset >= 0xffffffffn || file.byteLength >= 4294967295
27893
+ };
27894
+ return [
27895
+ new Uint8Array(concatenateArrayBuffers(encodeZipLocalHeader(header), file)),
27896
+ encodeZipCentralHeader(header)
27897
+ ];
27898
+ }
27899
+ async function createZip(inputPath, outputPath, createAdditionalData, options = {}) {
27900
+ const state = {
27901
+ maxArchiveBytes: options.maxArchiveBytes ?? 1024n ** 4n,
27902
+ maxEntries: options.maxEntries ?? 1e5,
27903
+ maxDirectoryBytes: options.maxDirectoryBytes ?? 32 * 1024 * 1024,
27904
+ signal: options.signal,
27905
+ directoryBytes: 0
27906
+ };
27907
+ if (typeof state.maxArchiveBytes !== "bigint" || state.maxArchiveBytes < 0n || !Number.isSafeInteger(state.maxEntries) || state.maxEntries < 1 || !Number.isSafeInteger(state.maxDirectoryBytes) || state.maxDirectoryBytes < 1)
27908
+ throw new RangeError("Invalid ZIP composition limits");
27909
+ if (state.maxArchiveBytes < 22n) throw new RangeError("ZIP composition archive limit exceeded");
27910
+ state.signal?.throwIfAborted();
27911
+ const fileIterator = getFileIterator(inputPath);
27912
+ const resFile = new NodeFileFacade(outputPath, "w");
27913
+ const fileList = [];
27914
+ const cdArray = [];
27915
+ try {
27916
+ for await (const file of fileIterator) {
27917
+ await addFile(file, resFile, cdArray, state, fileList);
27918
+ }
27919
+ if (createAdditionalData) {
27920
+ const additionaldata = await createAdditionalData(fileList);
27921
+ await addFile(additionaldata, resFile, cdArray, state);
27922
+ }
27923
+ state.signal?.throwIfAborted();
27924
+ const cdOffset = (await resFile.stat()).bigsize;
27925
+ const cd = concatenateArrayBuffers(...cdArray);
27926
+ await resFile.append(new Uint8Array(cd));
27927
+ const eoCDStart = (await resFile.stat()).bigsize;
27928
+ await resFile.append(
27929
+ new Uint8Array(
27930
+ encodeZipEndRecords(
27931
+ BigInt(cdArray.length),
27932
+ BigInt(cd.byteLength),
27933
+ cdOffset,
27934
+ eoCDStart > 0x7fffffffn || cdArray.length >= 65535
27935
+ )
27936
+ )
27937
+ );
27938
+ } finally {
27939
+ await resFile.close();
27940
+ }
27941
+ }
27942
+ async function addFile(file, resFile, cdArray, state, fileList) {
27943
+ state.signal?.throwIfAborted();
27944
+ const size = (await resFile.stat()).bigsize;
27945
+ fileList?.push({ fileName: file.path, localHeaderOffset: size });
27946
+ const [localPart, cdHeaderPart] = await generateFileHeaders(file.path, file.file, size);
27947
+ const directoryBytes = state.directoryBytes + cdHeaderPart.byteLength;
27948
+ const directoryOffset = size + BigInt(localPart.byteLength);
27949
+ const count = cdArray.length + 1;
27950
+ const footer = encodeZipEndRecords(
27951
+ BigInt(count),
27952
+ BigInt(directoryBytes),
27953
+ directoryOffset,
27954
+ directoryOffset + BigInt(directoryBytes) > 0x7fffffffn || count >= 65535
27955
+ );
27956
+ if (count > state.maxEntries || directoryBytes > state.maxDirectoryBytes || directoryOffset + BigInt(directoryBytes + footer.length) > state.maxArchiveBytes)
27957
+ throw new RangeError("ZIP composition metadata/archive limit exceeded");
27958
+ state.signal?.throwIfAborted();
27959
+ await resFile.append(localPart);
27960
+ state.directoryBytes = directoryBytes;
27961
+ cdArray.push(toArrayBuffer2(cdHeaderPart));
27962
+ }
27963
+ function getFileIterator(inputPath) {
27964
+ async function* iterable() {
27965
+ const fileList = await getAllFiles(inputPath);
27966
+ for (const filePath of fileList) {
27967
+ const provider = new NodeFileFacade(path_exports.join(inputPath, filePath), "r");
27968
+ try {
27969
+ const { bigsize } = await provider.stat();
27970
+ const file = await provider.read(0, Number(bigsize));
27971
+ yield { path: filePath, file };
27972
+ } finally {
27973
+ await provider.close();
28818
27974
  }
28819
- };
27975
+ }
27976
+ }
27977
+ return iterable();
27978
+ }
27979
+ async function getAllFiles(basePath, subfolder = "", fsPassed) {
27980
+ const fs3 = fsPassed ? fsPassed : new NodeFileSystemFacade({});
27981
+ const files = await fs3.readdir(pathJoin(basePath, subfolder));
27982
+ const arrayOfFiles = [];
27983
+ for (const file of files) {
27984
+ const fullPath = pathJoin(basePath, subfolder, file);
27985
+ if ((await fs3.stat(fullPath)).isDirectory) {
27986
+ const files2 = await getAllFiles(basePath, pathJoin(subfolder, file));
27987
+ arrayOfFiles.push(...files2);
27988
+ } else {
27989
+ arrayOfFiles.push(pathJoin(subfolder, file));
27990
+ }
27991
+ }
27992
+ return arrayOfFiles;
27993
+ }
27994
+ function pathJoin(...paths) {
27995
+ const resPaths = paths.filter((val) => val.length);
27996
+ return path_exports.join(...resPaths);
27997
+ }
27998
+ var init_zip_composition = __esm({
27999
+ "../../modules/zip/src/lib/zip-composition.ts"() {
28000
+ "use strict";
28001
+ init_src2();
28002
+ init_zip_entry_metadata();
28003
+ init_src11();
28004
+ init_zip_serialization();
28820
28005
  }
28821
28006
  });
28822
28007
 
28823
28008
  // ../../modules/zip/src/hash-file-utility.ts
28824
28009
  function parseHashTable(arrayBuffer) {
28010
+ if (arrayBuffer.byteLength % 24) throw new Error("Invalid ZIP index length");
28825
28011
  const dataView = new DataView(arrayBuffer);
28826
28012
  const hashMap = {};
28827
28013
  for (let i = 0; i < arrayBuffer.byteLength; i = i + 24) {
28828
28014
  const offset = dataView.getBigUint64(i + 16, true);
28829
28015
  const hash = bufferToHex(arrayBuffer, i, 16);
28016
+ if (hash in hashMap) throw new Error("Duplicate ZIP index hash");
28830
28017
  hashMap[hash] = offset;
28831
28018
  }
28832
28019
  return hashMap;
@@ -28834,30 +28021,14 @@ function parseHashTable(arrayBuffer) {
28834
28021
  function bufferToHex(buffer, start, length) {
28835
28022
  return [...new Uint8Array(buffer, start, length)].map((x) => x.toString(16).padStart(2, "0")).join("");
28836
28023
  }
28837
- async function makeHashTableFromZipHeaders(fileProvider) {
28838
- const zipCDIterator = makeZipCDHeaderIterator(fileProvider);
28839
- return getHashTable(zipCDIterator);
28840
- }
28841
- async function getHashTable(zipCDIterator) {
28842
- const md5Hash = new MD5Hash();
28843
- const textEncoder = new TextEncoder();
28844
- const hashTable = {};
28845
- for await (const cdHeader of zipCDIterator) {
28846
- const filename2 = cdHeader.fileName.split("\\").join("/").toLocaleLowerCase();
28847
- const arrayBuffer = textEncoder.encode(filename2).buffer;
28848
- const md53 = await md5Hash.hash(arrayBuffer, "hex");
28849
- hashTable[md53] = cdHeader.localHeaderOffset;
28850
- }
28851
- return hashTable;
28852
- }
28853
28024
  async function composeHashFile(zipCDIterator) {
28854
28025
  const md5Hash = new MD5Hash();
28855
28026
  const textEncoder = new TextEncoder();
28856
28027
  const hashArray = [];
28857
28028
  for await (const cdHeader of zipCDIterator) {
28858
- let filename2 = cdHeader.fileName.split("\\").join("/");
28029
+ let filename2 = ("path" in cdHeader ? cdHeader.path : cdHeader.fileName).split("\\").join("/");
28859
28030
  if (filename2 !== "3dSceneLayer.json.gz") {
28860
- filename2 = filename2.toLocaleLowerCase();
28031
+ filename2 = filename2.toLowerCase();
28861
28032
  }
28862
28033
  const arrayBuffer = textEncoder.encode(filename2).buffer;
28863
28034
  const md53 = await md5Hash.hash(arrayBuffer, "hex");
@@ -28885,18 +28056,313 @@ var init_hash_file_utility = __esm({
28885
28056
  "use strict";
28886
28057
  init_src11();
28887
28058
  init_src2();
28888
- init_cd_file_header();
28059
+ }
28060
+ });
28061
+
28062
+ // ../../modules/zip/src/filesystems/IndexedArchive.ts
28063
+ var IndexedArchive;
28064
+ var init_IndexedArchive = __esm({
28065
+ "../../modules/zip/src/filesystems/IndexedArchive.ts"() {
28066
+ "use strict";
28067
+ init_src11();
28068
+ init_zip_archive();
28069
+ init_hash_file_utility();
28070
+ IndexedArchive = class {
28071
+ /** Captures the source and an optional already-loaded format index. */
28072
+ constructor(file, hashTable, fileName, options = {}) {
28073
+ this.options = options;
28074
+ this.file = file;
28075
+ this.hashTable = hashTable;
28076
+ this.fileName = fileName;
28077
+ }
28078
+ options;
28079
+ /** Owned random-access archive source. */
28080
+ file;
28081
+ /** Optional resource URL prefix. */
28082
+ fileName;
28083
+ /** Format-provided path hashes, or a directory-derived fallback. */
28084
+ hashTable;
28085
+ /** Cancellation for metadata initialization and indexed reads. */
28086
+ controller = new AbortController();
28087
+ /** Shared lazy ZIP reader and directory cache. */
28088
+ readerPromise;
28089
+ /** Idempotent release even when no reader has been opened. */
28090
+ closePromise;
28091
+ /**
28092
+ * Loads a final index when present, otherwise hashes validated directory entries.
28093
+ * The format supplies the reserved name and fallback path-case policy. Returns true for an index.
28094
+ */
28095
+ async initializeIndex(indexPath, lowercasePaths = false) {
28096
+ const reader = await this.getZipArchive();
28097
+ const last = await reader.getLastEntry();
28098
+ if (last?.path === indexPath) {
28099
+ this.hashTable = parseHashTable(await reader.read(last));
28100
+ return true;
28101
+ }
28102
+ const hash = new MD5Hash();
28103
+ const table = /* @__PURE__ */ Object.create(null);
28104
+ for await (const entry of reader.entries()) {
28105
+ const path = lowercasePaths ? entry.path.toLowerCase() : entry.path;
28106
+ const digest = await hash.hash(new TextEncoder().encode(path).buffer, "hex");
28107
+ if (digest in table) throw new Error("Duplicate ZIP index path hash");
28108
+ table[digest] = entry.localHeaderOffset;
28109
+ }
28110
+ this.hashTable = table;
28111
+ return false;
28112
+ }
28113
+ /** Closes the reader/transport exactly once and rejects subsequent resource reads. */
28114
+ async close() {
28115
+ this.controller.abort(new Error("ZIP archive is closed"));
28116
+ this.closePromise ||= this.readerPromise ? this.readerPromise.then(
28117
+ (reader) => reader.close(),
28118
+ () => {
28119
+ }
28120
+ ) : this.file.close();
28121
+ await this.closePromise;
28122
+ }
28123
+ /** Reads and verifies a complete ZIP entry, retaining direct indexed local-header access. */
28124
+ async readZipEntry(path) {
28125
+ const reader = await this.getZipArchive();
28126
+ let entry;
28127
+ if (this.hashTable) {
28128
+ const digest = await new MD5Hash().hash(new TextEncoder().encode(path).buffer, "hex");
28129
+ const offset = this.hashTable[digest];
28130
+ if (offset === void 0) return void 0;
28131
+ entry = await reader.getEntryAt(offset);
28132
+ if (entry.path.toLowerCase() !== path.toLowerCase())
28133
+ throw new Error("ZIP index path mismatch");
28134
+ } else entry = await reader.getEntry(path);
28135
+ return entry ? await reader.read(entry) : void 0;
28136
+ }
28137
+ /** Compatibility helper for adapters with no path index. */
28138
+ async getFileWithoutHash(path) {
28139
+ const data = await this.readZipEntry(path);
28140
+ if (!data) throw new Error(`No such file in the archive: ${path}`);
28141
+ return data;
28142
+ }
28143
+ /** Initializes container metadata once without reading unrelated payloads. */
28144
+ async getZipArchive() {
28145
+ if (this.closePromise) throw new Error("ZIP archive is closed");
28146
+ this.readerPromise ||= openZipArchive(this.file, {
28147
+ ...this.options,
28148
+ signal: this.options.signal ? AbortSignal.any([this.controller.signal, this.options.signal]) : this.controller.signal
28149
+ });
28150
+ return await this.readerPromise;
28151
+ }
28152
+ };
28153
+ }
28154
+ });
28155
+
28156
+ // ../../modules/zip/src/filesystems/zip-filesystem.ts
28157
+ function parseByteRange(value, size) {
28158
+ const match = /^bytes=(\d*)-(\d*)$/i.exec(value.trim());
28159
+ if (!match || !match[1] && !match[2] || size === 0n) return void 0;
28160
+ if (!match[1]) {
28161
+ const suffix = BigInt(match[2]);
28162
+ if (!suffix) return void 0;
28163
+ return { start: suffix < size ? size - suffix : 0n, end: size };
28164
+ }
28165
+ const start = BigInt(match[1]);
28166
+ const last = match[2] ? BigInt(match[2]) : size - 1n;
28167
+ if (start >= size || last < start) return void 0;
28168
+ return { start, end: last < size ? last + 1n : size };
28169
+ }
28170
+ var ZipFileSystem;
28171
+ var init_zip_filesystem = __esm({
28172
+ "../../modules/zip/src/filesystems/zip-filesystem.ts"() {
28173
+ "use strict";
28174
+ init_src2();
28175
+ init_IndexedArchive();
28176
+ init_zip_archive();
28177
+ ZipFileSystem = class {
28178
+ /** Opens portable bytes, a random-access file, a format adapter, or a Node file path lazily. */
28179
+ constructor(file, options = {}) {
28180
+ this.options = options;
28181
+ this.signal = options.signal ? AbortSignal.any([this.controller.signal, options.signal]) : this.controller.signal;
28182
+ this.archive = file instanceof IndexedArchive ? file : null;
28183
+ if (typeof file === "string") {
28184
+ if (isBrowser)
28185
+ throw new Error("ZipFileSystem cannot open file paths in browser environments");
28186
+ this.fileName = file;
28187
+ this.file = new NodeFileFacade(file);
28188
+ } else if (file instanceof IndexedArchive) {
28189
+ this.file = file.file;
28190
+ this.fileName = file.fileName;
28191
+ } else if (file instanceof Blob || file instanceof ArrayBuffer) {
28192
+ this.file = new BlobFile(file);
28193
+ } else if (ArrayBuffer.isView(file)) {
28194
+ this.file = new BlobFile(
28195
+ Uint8Array.from(new Uint8Array(file.buffer, file.byteOffset, file.byteLength)).buffer
28196
+ );
28197
+ } else {
28198
+ this.file = file;
28199
+ }
28200
+ }
28201
+ options;
28202
+ /** Owned random-access transport. */
28203
+ file;
28204
+ /** Optional archive name used in response URLs. */
28205
+ fileName;
28206
+ /** Optional format adapter retaining resource aliases and content-level decoding. */
28207
+ archive;
28208
+ /** Shared reader initialization, performed once when first needed. */
28209
+ readerPromise;
28210
+ /** Cancellation for opening and all reads during the filesystem lifetime. */
28211
+ controller = new AbortController();
28212
+ /** Caller cancellation combined with filesystem destruction. */
28213
+ signal;
28214
+ /** Idempotent transport release. */
28215
+ destroyPromise;
28216
+ /** Cancels pending reads and closes the owned file once; later operations reject. */
28217
+ destroy() {
28218
+ this.controller.abort(new Error("ZIP filesystem is closed"));
28219
+ this.destroyPromise ||= this.archive ? this.archive.close() : this.readerPromise ? this.readerPromise.then(
28220
+ (reader) => reader.close(),
28221
+ () => {
28222
+ }
28223
+ ) : this.file.close();
28224
+ return this.destroyPromise;
28225
+ }
28226
+ /** Lists validated archive paths in central-directory order, including directory entries. */
28227
+ async readdir() {
28228
+ const reader = await this.getReader();
28229
+ const paths = [];
28230
+ for await (const entry of reader.entries()) paths.push(entry.path);
28231
+ return paths;
28232
+ }
28233
+ /** Returns validated metadata; rejects sizes that cannot be represented safely as a number. */
28234
+ async stat(filename2) {
28235
+ const entry = await this.getEntry(filename2);
28236
+ if (entry.size > BigInt(Number.MAX_SAFE_INTEGER))
28237
+ throw new RangeError("ZIP FileSystem size is not safely representable");
28238
+ return { ...entry, size: Number(entry.size), uncompressedSize: entry.size };
28239
+ }
28240
+ /**
28241
+ * Fetches a confined resource. Complete streams verify CRC when consumed through completion.
28242
+ * Single STORE ranges return 206 or 416; compressed and format-decoded ranges reject.
28243
+ */
28244
+ async fetch(filename2, options = {}) {
28245
+ this.signal.throwIfAborted();
28246
+ options.signal?.throwIfAborted();
28247
+ if (options.method && options.method.toUpperCase() !== "GET")
28248
+ throw new Error("ZIP filesystem only supports GET");
28249
+ let path;
28250
+ const range = new Headers(options.headers).get("range");
28251
+ let response;
28252
+ if (this.archive) {
28253
+ path = this.resolveResourcePath(filename2);
28254
+ if (range !== null)
28255
+ throw new Error("ZIP ranges are unavailable through format resource adapters");
28256
+ response = new Response(await this.archive.getFile(path, "http"));
28257
+ this.signal.throwIfAborted();
28258
+ options.signal?.throwIfAborted();
28259
+ } else {
28260
+ const reader = await this.getReader();
28261
+ options.signal?.throwIfAborted();
28262
+ const entry = await this.getEntry(filename2);
28263
+ options.signal?.throwIfAborted();
28264
+ path = entry.path;
28265
+ const headers = new Headers({
28266
+ "Accept-Ranges": entry.compression === "store" ? "bytes" : "none",
28267
+ "Content-Length": String(entry.size)
28268
+ });
28269
+ if (range !== null) {
28270
+ if (entry.compression !== "store") throw new Error("ZIP ranges require STORE entries");
28271
+ const bounds = parseByteRange(range, entry.size);
28272
+ if (!bounds) {
28273
+ headers.set("Content-Range", `bytes */${entry.size}`);
28274
+ headers.set("Content-Length", "0");
28275
+ response = new Response(null, { status: 416, headers });
28276
+ } else {
28277
+ const bytes = await reader.readRange(entry, {
28278
+ ...bounds,
28279
+ signal: options.signal || void 0
28280
+ });
28281
+ headers.set("Content-Range", `bytes ${bounds.start}-${bounds.end - 1n}/${entry.size}`);
28282
+ headers.set("Content-Length", String(bounds.end - bounds.start));
28283
+ response = new Response(bytes, { status: 206, headers });
28284
+ }
28285
+ } else {
28286
+ const iterator = reader.readInBatches(entry, { signal: options.signal || void 0 })[Symbol.asyncIterator]();
28287
+ const stream = new ReadableStream(
28288
+ {
28289
+ async pull(controller) {
28290
+ try {
28291
+ const chunk = await iterator.next();
28292
+ if (chunk.done) controller.close();
28293
+ else controller.enqueue(chunk.value);
28294
+ } catch (error) {
28295
+ controller.error(error);
28296
+ }
28297
+ },
28298
+ async cancel() {
28299
+ await iterator.return?.();
28300
+ }
28301
+ },
28302
+ { highWaterMark: 0 }
28303
+ );
28304
+ response = new Response(stream, { headers });
28305
+ }
28306
+ }
28307
+ Object.defineProperty(response, "url", {
28308
+ value: this.getResourceUrl(path)
28309
+ });
28310
+ return response;
28311
+ }
28312
+ /** Resolves resources once, allowing parents inside the archive but rejecting root escapes. */
28313
+ resolveResourcePath(filename2, decodeUri = false) {
28314
+ const archivePath = filename2.startsWith("./") ? filename2.slice(2) : filename2;
28315
+ const archiveName = this.fileName?.replace(/^\.\//, "");
28316
+ if (archiveName && (archivePath === archiveName || archivePath.startsWith(`${archiveName}/`))) {
28317
+ filename2 = archivePath.slice(archiveName.length).replace(/^\//, "");
28318
+ decodeUri = true;
28319
+ }
28320
+ decodeUri ||= filename2.startsWith("/") || filename2.startsWith("./");
28321
+ if (/^[a-z][a-z\d+.-]*:/i.test(filename2) || filename2.startsWith("//"))
28322
+ throw new Error("ZIP resource must stay inside the archive");
28323
+ const decoded = decodeUri ? decodeURIComponent(filename2.split(/[?#]/, 1)[0]) : filename2;
28324
+ if (decoded.includes("\\") || decoded.includes("\0") || decoded.startsWith("//") || /^[a-z][a-z\d+.-]*:/i.test(decoded))
28325
+ throw new Error("ZIP resource must stay inside the archive");
28326
+ const segments = [];
28327
+ for (const segment of decoded.split("/")) {
28328
+ if (!segment || segment === ".") continue;
28329
+ if (segment === "..") {
28330
+ if (!segments.length) throw new Error("ZIP resource escapes the archive");
28331
+ segments.pop();
28332
+ } else segments.push(segment);
28333
+ }
28334
+ return segments.join("/") + (decoded.endsWith("/") && segments.length ? "/" : "");
28335
+ }
28336
+ /** Creates a qualified URL that cannot be confused with a canonical literal archive path. */
28337
+ getResourceUrl(path) {
28338
+ const prefix = this.fileName && !/^(?:\/|[a-z][a-z\d+.-]*:)/i.test(this.fileName) ? `./${this.fileName.replace(/^\.\//, "")}` : this.fileName || "";
28339
+ return `${prefix}/${path.split("/").map(encodeURIComponent).join("/")}`;
28340
+ }
28341
+ /** Shares the directory cache and lifetime with every filesystem lookup. */
28342
+ async getReader() {
28343
+ this.signal.throwIfAborted();
28344
+ if (this.archive) return await this.archive.getZipArchive();
28345
+ this.readerPromise ||= openZipArchive(this.file, {
28346
+ ...this.options,
28347
+ signal: this.signal
28348
+ });
28349
+ return await this.readerPromise;
28350
+ }
28351
+ /** Resolves one validated entry and reports absent resources explicitly. */
28352
+ async getEntry(path) {
28353
+ const reader = await this.getReader();
28354
+ const entry = await reader.getEntry(path) || await reader.getEntry(this.resolveResourcePath(path, true));
28355
+ if (!entry) throw new Error(`File has not been found in the zip archive: ${path}`);
28356
+ return entry;
28357
+ }
28358
+ };
28889
28359
  }
28890
28360
  });
28891
28361
 
28892
28362
  // ../../modules/zip/src/index.ts
28893
- var init_src13 = __esm({
28363
+ var init_src12 = __esm({
28894
28364
  "../../modules/zip/src/index.ts"() {
28895
28365
  "use strict";
28896
- init_cd_file_header();
28897
- init_local_file_header();
28898
- init_search_from_the_end();
28899
- init_readable_file_utils();
28900
28366
  init_zip_composition();
28901
28367
  init_IndexedArchive();
28902
28368
  init_hash_file_utility();
@@ -28905,30 +28371,19 @@ var init_src13 = __esm({
28905
28371
  });
28906
28372
 
28907
28373
  // ../../modules/3d-tiles/src/3d-tiles-archive/3d-tiles-archive-archive.ts
28908
- var COMPRESSION_METHODS, Tiles3DArchive;
28374
+ var Tiles3DArchive;
28909
28375
  var init_d_tiles_archive_archive = __esm({
28910
28376
  "../../modules/3d-tiles/src/3d-tiles-archive/3d-tiles-archive-archive.ts"() {
28911
28377
  "use strict";
28912
- init_src11();
28913
28378
  init_src12();
28914
- init_src13();
28915
- COMPRESSION_METHODS = {
28916
- /** No compression */
28917
- 0: (data) => new NoDecompressor2().decompress(data),
28918
- /** Deflation */
28919
- 8: (data) => new DeflateDecompressor2({ raw: true }).decompress(data)
28920
- };
28921
28379
  Tiles3DArchive = class extends IndexedArchive {
28922
- /** hash info */
28923
- hashTable;
28924
28380
  /**
28925
28381
  * creates Tiles3DArchive handler
28926
28382
  * @param fileProvider - readable file handle with the whole archive
28927
28383
  * @param hashTable - hash info
28928
28384
  */
28929
- constructor(fileProvider, hashTable, fileName) {
28930
- super(fileProvider, hashTable, fileName);
28931
- this.hashTable = hashTable;
28385
+ constructor(fileProvider, hashTable, fileName, options) {
28386
+ super(fileProvider, hashTable, fileName, options);
28932
28387
  }
28933
28388
  /**
28934
28389
  * Returns file with the given path from 3tz archive
@@ -28951,37 +28406,33 @@ var init_d_tiles_archive_archive = __esm({
28951
28406
  * @returns buffer with the raw file data
28952
28407
  */
28953
28408
  async getFileBytes(path) {
28954
- let uncompressedFile;
28955
- if (this.hashTable) {
28956
- const arrayBuffer = new TextEncoder().encode(path).buffer;
28957
- const nameHash = await new MD5Hash().hash(arrayBuffer, "hex");
28958
- const byteOffset = this.hashTable[nameHash];
28959
- if (byteOffset === void 0) {
28960
- return null;
28961
- }
28962
- const localFileHeader = await parseZipLocalFileHeader(byteOffset, this.file);
28963
- if (!localFileHeader) {
28964
- return null;
28965
- }
28966
- const compressedFile = await readRange(
28967
- this.file,
28968
- localFileHeader.fileDataOffset,
28969
- localFileHeader.fileDataOffset + localFileHeader.compressedSize
28970
- );
28971
- const compressionMethod = COMPRESSION_METHODS[localFileHeader.compressionMethod];
28972
- if (!compressionMethod) {
28973
- throw Error("Only Deflation compression is supported");
28974
- }
28975
- uncompressedFile = await compressionMethod(compressedFile);
28976
- } else {
28977
- uncompressedFile = await this.getFileWithoutHash(path);
28978
- }
28979
- return uncompressedFile;
28409
+ return await this.readZipEntry(path) ?? null;
28980
28410
  }
28981
28411
  };
28982
28412
  }
28983
28413
  });
28984
28414
 
28415
+ // ../../modules/3d-tiles/src/3d-tiles-archive/3d-tiles-archive-parser.ts
28416
+ async function parse3DTilesArchive(fileProvider, callback, fileName, options) {
28417
+ const archive = new Tiles3DArchive(fileProvider, void 0, fileName, options);
28418
+ try {
28419
+ if (!await archive.initializeIndex("@3dtilesIndex1@", false))
28420
+ callback?.(
28421
+ "3tz doesnt contain hash file, hash info has been composed according to zip archive headers"
28422
+ );
28423
+ return archive;
28424
+ } catch (error) {
28425
+ await archive.close();
28426
+ throw error;
28427
+ }
28428
+ }
28429
+ var init_d_tiles_archive_parser = __esm({
28430
+ "../../modules/3d-tiles/src/3d-tiles-archive/3d-tiles-archive-parser.ts"() {
28431
+ "use strict";
28432
+ init_d_tiles_archive_archive();
28433
+ }
28434
+ });
28435
+
28985
28436
  // ../../modules/i3s/src/i3s-zod-schema.ts
28986
28437
  import { z as z3 } from "zod";
28987
28438
  var I3SObbSchema, I3SMeshMaterialSchema, I3SMeshGeometrySchema, I3SNodeInPageSchema, I3SNodePageSchema, I3SPointCloudNodeSchema, I3SPointCloudNodePageSchema, I3SSpatialReferenceSchema, I3SPointCloudStoreSchema, I3SPointCloudSceneLayerBaseSchema, I3SPointCloudNodePagesRequirementSchema, I3SPointCloudSceneLayerSchema, I3SGeometryBufferItemSchema, I3SGeometryBufferSchema, I3SGeometryDefinitionSchema, I3SSceneLayerSchema, I3SPointSceneLayerSchema;
@@ -30885,14 +30336,215 @@ var init_i3s_loader = __esm({
30885
30336
  }
30886
30337
  });
30887
30338
 
30339
+ // ../../modules/compression/src/lib/native-decompressor.ts
30340
+ var native_decompressor_exports = {};
30341
+ __export(native_decompressor_exports, {
30342
+ NativeDecompressor: () => NativeDecompressor
30343
+ });
30344
+ var NativeDecompressor;
30345
+ var init_native_decompressor = __esm({
30346
+ "../../modules/compression/src/lib/native-decompressor.ts"() {
30347
+ "use strict";
30348
+ init_compression();
30349
+ init_decompression_stream();
30350
+ NativeDecompressor = class extends Decompressor {
30351
+ name;
30352
+ extensions;
30353
+ contentEncodings;
30354
+ isSupported = true;
30355
+ /** Runtime stream format used for every operation. */
30356
+ format;
30357
+ constructor(metadata, format, options = {}) {
30358
+ super(options);
30359
+ this.name = metadata.name;
30360
+ this.extensions = [...metadata.extensions];
30361
+ this.contentEncodings = [...metadata.contentEncodings];
30362
+ this.format = format;
30363
+ }
30364
+ /** Decompresses one buffer with the runtime-provided stream. */
30365
+ async decompress(input) {
30366
+ const output = await decompressWithNativeDecompressionStream(input, this.format);
30367
+ if (!output) throw new Error(`${this.name}: built-in decompression is no longer available`);
30368
+ return output;
30369
+ }
30370
+ /** Decompresses batches incrementally with the runtime-provided stream. */
30371
+ async *decompressBatches(inputBatches) {
30372
+ const output = decompressBatchesWithNativeDecompressionStream(inputBatches, this.format);
30373
+ if (!output) throw new Error(`${this.name}: built-in decompression is no longer available`);
30374
+ yield* output;
30375
+ }
30376
+ };
30377
+ }
30378
+ });
30379
+
30380
+ // ../../modules/compression/src/lib/lazy-compression.ts
30381
+ function mergeModules(options, modules) {
30382
+ return { ...options, modules: { ...options.modules, ...modules } };
30383
+ }
30384
+ var LazyDecompressor;
30385
+ var init_lazy_compression = __esm({
30386
+ "../../modules/compression/src/lib/lazy-compression.ts"() {
30387
+ "use strict";
30388
+ init_compression();
30389
+ init_decompression_stream();
30390
+ LazyDecompressor = class extends Decompressor {
30391
+ name;
30392
+ extensions;
30393
+ contentEncodings;
30394
+ isSupported = true;
30395
+ /** Constructor options retained until a concrete implementation is selected. */
30396
+ options;
30397
+ /** Built-in stream format to probe, or null when the format has no built-in path. */
30398
+ nativeFormat;
30399
+ /** Returns whether built-in selection remains eligible for the merged preload options. */
30400
+ shouldUseNative;
30401
+ /** Dynamically imports the balanced fallback constructor. */
30402
+ loadFallback;
30403
+ /** Selected concrete implementation after preload completes. */
30404
+ implementation = null;
30405
+ /** Shared in-flight selection used by concurrent asynchronous calls. */
30406
+ implementationPromise = null;
30407
+ constructor(metadata, loadFallback, options = {}, nativeFormat = null, shouldUseNative = () => true) {
30408
+ super(options);
30409
+ this.name = metadata.name;
30410
+ this.extensions = [...metadata.extensions];
30411
+ this.contentEncodings = [...metadata.contentEncodings];
30412
+ this.options = options;
30413
+ this.nativeFormat = nativeFormat;
30414
+ this.shouldUseNative = shouldUseNative;
30415
+ this.loadFallback = loadFallback;
30416
+ }
30417
+ /** Selects and returns the built-in or dynamically imported fallback decompressor. */
30418
+ async preload(modules = {}) {
30419
+ if (this.implementation) return this.implementation;
30420
+ const options = mergeModules(this.options, modules);
30421
+ this.implementationPromise ||= this.loadImplementation(options);
30422
+ try {
30423
+ this.implementation = await this.implementationPromise;
30424
+ return this.implementation;
30425
+ } catch (error) {
30426
+ this.implementationPromise = null;
30427
+ throw error;
30428
+ }
30429
+ }
30430
+ /** Loads the selected concrete decompressor. */
30431
+ async loadImplementation(options) {
30432
+ if (options.useNative !== false && this.nativeFormat && this.shouldUseNative(options) && isNativeDecompressionSupported(this.nativeFormat)) {
30433
+ const { NativeDecompressor: NativeDecompressor2 } = await Promise.resolve().then(() => (init_native_decompressor(), native_decompressor_exports));
30434
+ return new NativeDecompressor2(this, this.nativeFormat, options);
30435
+ }
30436
+ const Decompressor2 = await this.loadFallback();
30437
+ const implementation = new Decompressor2({ ...options, useNative: false });
30438
+ await implementation.preload(options.modules);
30439
+ return implementation;
30440
+ }
30441
+ /** Decompresses after lazily selecting the default implementation. */
30442
+ async decompress(input, size) {
30443
+ return (await this.preload()).decompress(input, size);
30444
+ }
30445
+ /** Decompresses synchronously after an implementation has been preloaded. */
30446
+ decompressSync(input, size) {
30447
+ if (!this.implementation) {
30448
+ throw new Error(`${this.name}: call preload() before decompressSync()`);
30449
+ }
30450
+ return this.implementation.decompressSync(input, size);
30451
+ }
30452
+ /** Decompresses batches after lazily selecting the default implementation. */
30453
+ async *decompressBatches(inputBatches) {
30454
+ yield* (await this.preload()).decompressBatches(inputBatches);
30455
+ }
30456
+ };
30457
+ }
30458
+ });
30459
+
30460
+ // ../../modules/compression/src/gzip-decompressor-compress-utils.ts
30461
+ var GZipCompressUtilsDecompressor;
30462
+ var init_gzip_decompressor_compress_utils = __esm({
30463
+ "../../modules/compression/src/gzip-decompressor-compress-utils.ts"() {
30464
+ "use strict";
30465
+ init_compress_utils_compression();
30466
+ GZipCompressUtilsDecompressor = class extends CompressUtilsDecompressor {
30467
+ constructor(options = {}) {
30468
+ super(
30469
+ { name: "gzip", extensions: ["gz", "gzip"], contentEncodings: ["gzip", "x-gzip"] },
30470
+ () => import("compress-utils/gzip/decompress"),
30471
+ options
30472
+ );
30473
+ }
30474
+ };
30475
+ }
30476
+ });
30477
+
30478
+ // ../../modules/compression/src/gzip-decompressor.ts
30479
+ var gzip_decompressor_exports = {};
30480
+ __export(gzip_decompressor_exports, {
30481
+ GZipDecompressor: () => GZipDecompressor
30482
+ });
30483
+ var GZipDecompressor;
30484
+ var init_gzip_decompressor = __esm({
30485
+ "../../modules/compression/src/gzip-decompressor.ts"() {
30486
+ "use strict";
30487
+ init_gzip_decompressor_compress_utils();
30488
+ init_decompression_stream();
30489
+ GZipDecompressor = class extends GZipCompressUtilsDecompressor {
30490
+ /** Decompresses with native streams when available, otherwise lazily initializes WASM. */
30491
+ async decompress(input, size) {
30492
+ if (this.options.useNative !== false) {
30493
+ const output = await decompressWithNativeDecompressionStream(input, "gzip");
30494
+ if (output) return output;
30495
+ }
30496
+ return super.decompress(input, size);
30497
+ }
30498
+ /** Streams native batches when available, otherwise uses the WASM stream. */
30499
+ async *decompressBatches(inputBatches) {
30500
+ if (this.options.useNative !== false) {
30501
+ const output = decompressBatchesWithNativeDecompressionStream(inputBatches, "gzip");
30502
+ if (output) {
30503
+ yield* output;
30504
+ return;
30505
+ }
30506
+ }
30507
+ yield* super.decompressBatches(inputBatches);
30508
+ }
30509
+ };
30510
+ }
30511
+ });
30512
+
30513
+ // ../../modules/compression/src/default-codecs.ts
30514
+ var GZIP, GZipDecompressor2;
30515
+ var init_default_codecs = __esm({
30516
+ "../../modules/compression/src/default-codecs.ts"() {
30517
+ "use strict";
30518
+ init_lazy_compression();
30519
+ GZIP = { name: "gzip", extensions: ["gz"], contentEncodings: ["gzip"] };
30520
+ GZipDecompressor2 = class extends LazyDecompressor {
30521
+ constructor(options = {}) {
30522
+ super(
30523
+ GZIP,
30524
+ async () => (await Promise.resolve().then(() => (init_gzip_decompressor(), gzip_decompressor_exports))).GZipDecompressor,
30525
+ options,
30526
+ "gzip"
30527
+ );
30528
+ }
30529
+ };
30530
+ }
30531
+ });
30532
+
30533
+ // ../../modules/compression/src/index.ts
30534
+ var init_src13 = __esm({
30535
+ "../../modules/compression/src/index.ts"() {
30536
+ "use strict";
30537
+ init_default_codecs();
30538
+ }
30539
+ });
30540
+
30888
30541
  // ../../modules/i3s/src/lib/parsers/parse-slpk/slpk-archieve.ts
30889
30542
  var PATH_DESCRIPTIONS, SLPKArchive;
30890
30543
  var init_slpk_archieve = __esm({
30891
30544
  "../../modules/i3s/src/lib/parsers/parse-slpk/slpk-archieve.ts"() {
30892
30545
  "use strict";
30893
- init_src11();
30894
- init_src13();
30895
30546
  init_src12();
30547
+ init_src13();
30896
30548
  PATH_DESCRIPTIONS = [
30897
30549
  {
30898
30550
  test: /^$/,
@@ -30932,20 +30584,14 @@ var init_slpk_archieve = __esm({
30932
30584
  }
30933
30585
  ];
30934
30586
  SLPKArchive = class extends IndexedArchive {
30935
- // Maps hex-encoded md5 filename hashes to bigint offsets into the archive
30936
- hashTable;
30937
- _textEncoder = new TextEncoder();
30938
- _textDecoder = new TextDecoder();
30939
- _md5Hash = new MD5Hash();
30940
30587
  /**
30941
30588
  * Constructor
30942
30589
  * @param fileProvider - readable file handle for random access
30943
30590
  * @param hashTable - pre-loaded hashTable. If presented, getFile will skip reading the hash file
30944
30591
  * @param fileName - name of the archive. It is used to add to an URL of a loader context
30945
30592
  */
30946
- constructor(fileProvider, hashTable, fileName) {
30947
- super(fileProvider, hashTable, fileName);
30948
- this.hashTable = hashTable;
30593
+ constructor(fileProvider, hashTable, fileName, options) {
30594
+ super(fileProvider, hashTable, fileName, options);
30949
30595
  }
30950
30596
  /**
30951
30597
  * Returns file with the given path from slpk archive
@@ -30990,7 +30636,7 @@ var init_slpk_archieve = __esm({
30990
30636
  * @returns buffer with the file data
30991
30637
  */
30992
30638
  async getDataByPath(path) {
30993
- let data = await this.getFileBytes(path.toLocaleLowerCase());
30639
+ let data = await this.getFileBytes(path.toLowerCase());
30994
30640
  if (!data) {
30995
30641
  data = await this.getFileBytes(path);
30996
30642
  }
@@ -31010,68 +30656,29 @@ var init_slpk_archieve = __esm({
31010
30656
  * @returns buffer with the raw file data
31011
30657
  */
31012
30658
  async getFileBytes(path) {
31013
- let compressedFile;
31014
- if (this.hashTable) {
31015
- const binaryPath = this._textEncoder.encode(path);
31016
- const nameHash = await this._md5Hash.hash(binaryPath.buffer, "hex");
31017
- const offset = this.hashTable[nameHash];
31018
- if (offset === void 0) {
31019
- return void 0;
31020
- }
31021
- const localFileHeader = await parseZipLocalFileHeader(offset, this.file);
31022
- if (!localFileHeader) {
31023
- return void 0;
31024
- }
31025
- compressedFile = await readRange(
31026
- this.file,
31027
- localFileHeader.fileDataOffset,
31028
- localFileHeader.fileDataOffset + localFileHeader.compressedSize
31029
- );
31030
- } else {
31031
- try {
31032
- compressedFile = await this.getFileWithoutHash(path);
31033
- } catch {
31034
- compressedFile = void 0;
31035
- }
31036
- }
31037
- return compressedFile;
30659
+ return await this.readZipEntry(path);
31038
30660
  }
31039
30661
  };
31040
30662
  }
31041
30663
  });
31042
30664
 
31043
30665
  // ../../modules/i3s/src/lib/parsers/parse-slpk/parse-slpk.ts
31044
- async function parseSLPKArchive(fileProvider, cb, fileName) {
31045
- const hashCDOffset = await searchFromTheEnd(fileProvider, signature2);
31046
- const cdFileHeader = await parseZipCDFileHeader(hashCDOffset, fileProvider);
31047
- let hashTable;
31048
- if (cdFileHeader?.fileName !== "@specialIndexFileHASH128@") {
31049
- hashTable = await makeHashTableFromZipHeaders(fileProvider);
31050
- cb?.(
31051
- "SLPK doesnt contain hash file, hash info has been composed according to zip archive headers"
31052
- );
31053
- } else {
31054
- const localFileHeader = await parseZipLocalFileHeader(
31055
- cdFileHeader.localHeaderOffset,
31056
- fileProvider
31057
- );
31058
- if (!localFileHeader) {
31059
- throw new Error("corrupted SLPK");
31060
- }
31061
- const fileDataOffset = localFileHeader.fileDataOffset;
31062
- const hashFile = await readRange(
31063
- fileProvider,
31064
- fileDataOffset,
31065
- fileDataOffset + localFileHeader.compressedSize
31066
- );
31067
- hashTable = parseHashTable(hashFile);
30666
+ async function parseSLPKArchive(fileProvider, callback, fileName, options) {
30667
+ const archive = new SLPKArchive(fileProvider, void 0, fileName, options);
30668
+ try {
30669
+ if (!await archive.initializeIndex("@specialIndexFileHASH128@", true))
30670
+ callback?.(
30671
+ "SLPK doesnt contain hash file, hash info has been composed according to zip archive headers"
30672
+ );
30673
+ return archive;
30674
+ } catch (error) {
30675
+ await archive.close();
30676
+ throw error;
31068
30677
  }
31069
- return new SLPKArchive(fileProvider, hashTable, fileName);
31070
30678
  }
31071
30679
  var init_parse_slpk = __esm({
31072
30680
  "../../modules/i3s/src/lib/parsers/parse-slpk/parse-slpk.ts"() {
31073
30681
  "use strict";
31074
- init_src13();
31075
30682
  init_slpk_archieve();
31076
30683
  }
31077
30684
  });
@@ -31980,7 +31587,7 @@ function encodeSync3(tile, options) {
31980
31587
 
31981
31588
  // ../../modules/3d-tiles/src/index.ts
31982
31589
  init_constants();
31983
- init_d_tiles_archive_archive();
31590
+ init_d_tiles_archive_parser();
31984
31591
 
31985
31592
  // src/v4/i3s-converter/i3s-converter.ts
31986
31593
  import { join as join8 } from "path";
@@ -32058,8 +31665,8 @@ async function writeFile(path, data, fileName = "index.json") {
32058
31665
  const pathFile = join2(path, fileName);
32059
31666
  try {
32060
31667
  await fs.writeFile(pathFile, toWriteData);
32061
- } catch (err2) {
32062
- throw err2;
31668
+ } catch (err) {
31669
+ throw err;
32063
31670
  }
32064
31671
  console.log(`${pathFile} saved.`);
32065
31672
  return pathFile;
@@ -32119,8 +31726,8 @@ function getAbsoluteFilePath(filePath) {
32119
31726
  async function renameFile(oldPath, newPath) {
32120
31727
  try {
32121
31728
  await fs.rename(oldPath, newPath);
32122
- } catch (err2) {
32123
- console.log("Can't rename file", err2);
31729
+ } catch (err) {
31730
+ console.log("Can't rename file", err);
32124
31731
  }
32125
31732
  }
32126
31733
 
@@ -34286,7 +33893,8 @@ var STORE = {
34286
33893
  },
34287
33894
  normalReferenceFrame: {
34288
33895
  path: "normalReferenceFrame",
34289
- default: "east-north-up"
33896
+ // Geometry conversion rotates normals into the ECEF frame.
33897
+ default: "earth-centered"
34290
33898
  },
34291
33899
  attributeEncoding: {
34292
33900
  path: "attributeEncoding",
@@ -35103,7 +34711,7 @@ var NodeIndexDocument = class _NodeIndexDocument {
35103
34711
  }
35104
34712
  }
35105
34713
  /**
35106
- * Add neighbors to child nodes of this node
34714
+ * Add neighbors, save leaf documents and children, then release finalized child data.
35107
34715
  */
35108
34716
  async addNeighbors() {
35109
34717
  if (this.finalized) {
@@ -35131,6 +34739,9 @@ var NodeIndexDocument = class _NodeIndexDocument {
35131
34739
  }
35132
34740
  await childNode.save();
35133
34741
  }
34742
+ if (!this.children.length) {
34743
+ await this.save();
34744
+ }
35134
34745
  this.finalize();
35135
34746
  }
35136
34747
  /** Save 3DNodeIndexDocument in file on disk */
@@ -35303,7 +34914,7 @@ var NodeIndexDocument = class _NodeIndexDocument {
35303
34914
  // src/v4/i3s-converter/helpers/load-3d-tiles.ts
35304
34915
  init_src5();
35305
34916
  init_src2();
35306
- init_src13();
34917
+ init_src12();
35307
34918
  var loadNestedTileset = async (sourceTileset, sourceTile, tilesetLoadOptions) => {
35308
34919
  const isTileset = isNestedTileset(sourceTile);
35309
34920
  if (!sourceTileset || !sourceTile.contentUrl || !isTileset) {
@@ -35362,8 +34973,7 @@ async function loadFromArchive(url, loader, loadOptions) {
35362
34973
  if (filename2) {
35363
34974
  const tz3Path = `${tz3UrlParts[0]}.3tz`;
35364
34975
  const fileProvider = createReadableFile(tz3Path);
35365
- const hashTable = await loadHashTable(fileProvider);
35366
- const archive = new Tiles3DArchive(fileProvider, hashTable, tz3Path);
34976
+ const archive = await parse3DTilesArchive(fileProvider, void 0, tz3Path);
35367
34977
  const fileSystem = new ZipFileSystem(archive);
35368
34978
  const archiveLoadOptions = {
35369
34979
  ...loadOptions,
@@ -35384,28 +34994,6 @@ function createReadableFile(path) {
35384
34994
  }
35385
34995
  return isBrowser ? new HttpFile(path) : new NodeFileFacade(path);
35386
34996
  }
35387
- async function loadHashTable(fileProvider) {
35388
- let hashTable;
35389
- const hashCDOffset = await searchFromTheEnd(fileProvider, signature2);
35390
- const cdFileHeader = await parseZipCDFileHeader(hashCDOffset, fileProvider);
35391
- if (cdFileHeader?.fileName === "@3dtilesIndex1@") {
35392
- const localFileHeader = await parseZipLocalFileHeader(
35393
- cdFileHeader.localHeaderOffset,
35394
- fileProvider
35395
- );
35396
- if (!localFileHeader) {
35397
- throw new Error("corrupted 3tz");
35398
- }
35399
- const fileDataOffset = localFileHeader.fileDataOffset;
35400
- const hashFile = await readRange(
35401
- fileProvider,
35402
- fileDataOffset,
35403
- fileDataOffset + localFileHeader.compressedSize
35404
- );
35405
- hashTable = parseHashTable(hashFile);
35406
- }
35407
- return hashTable;
35408
- }
35409
34997
 
35410
34998
  // src/v4/i3s-converter/i3s-converter.ts
35411
34999
  init_src10();
@@ -35469,7 +35057,7 @@ var analyzeTileContent = async (tileContent) => {
35469
35057
  return defaultResult;
35470
35058
  }
35471
35059
  const gltfData = await parse(tileContent.gltfArrayBuffer, GLTFLoader, {
35472
- gltf: { normalize: false, loadBuffers: false, loadImages: false, decompressMeshes: false }
35060
+ gltf: { normalize: true, loadBuffers: false, loadImages: false, decompressMeshes: false }
35473
35061
  });
35474
35062
  const gltf = gltfData.json;
35475
35063
  if (!gltf) {
@@ -35663,7 +35251,7 @@ var Progress = class {
35663
35251
  };
35664
35252
 
35665
35253
  // src/v4/i3s-converter/i3s-converter.ts
35666
- init_src13();
35254
+ init_src12();
35667
35255
 
35668
35256
  // src/v4/lib/utils/conversion-dump.ts
35669
35257
  import { isDeepStrictEqual } from "util";
@@ -38077,7 +37665,7 @@ var Tiles3DContentConverter = class {
38077
37665
  // src/v4/3d-tiles-converter/helpers/load-i3s.ts
38078
37666
  init_src5();
38079
37667
  init_src2();
38080
- init_src13();
37668
+ init_src12();
38081
37669
  var loadI3SContent = async (sourceTileset, sourceTile, tilesetLoadOptions, slpkFilesystem) => {
38082
37670
  if (!sourceTileset || !sourceTile.contentUrl) {
38083
37671
  return null;
@@ -38142,9 +37730,7 @@ async function getNodeCount(fileSystem) {
38142
37730
  return 0;
38143
37731
  }
38144
37732
  const nodeSet = /* @__PURE__ */ new Set();
38145
- const filesIterator = makeZipCDHeaderIterator(fileSystem.file);
38146
- for await (const file of filesIterator) {
38147
- const filename2 = file.fileName;
37733
+ for (const filename2 of await fileSystem.readdir()) {
38148
37734
  const nodeNumberSearchResult = /^nodes\/(\d+)\//.exec(filename2);
38149
37735
  if (nodeNumberSearchResult) {
38150
37736
  nodeSet.add(nodeNumberSearchResult[1]);