@loaders.gl/core 5.0.0-alpha.1 → 5.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +14 -3
  2. package/dist/dist.dev.js +1246 -227
  3. package/dist/dist.min.js +3 -3
  4. package/dist/index.cjs +2695 -270
  5. package/dist/index.cjs.map +3 -4
  6. package/dist/iterators/make-iterator/make-stream-iterator.js +49 -10
  7. package/dist/iterators/make-iterator/make-stream-iterator.js.map +1 -1
  8. package/dist/lib/api/create-data-source.d.ts +1 -1
  9. package/dist/lib/api/create-data-source.d.ts.map +1 -1
  10. package/dist/lib/api/create-data-source.js +23 -2
  11. package/dist/lib/api/create-data-source.js.map +1 -1
  12. package/dist/lib/api/load-in-batches.d.ts.map +1 -1
  13. package/dist/lib/api/load-in-batches.js +17 -6
  14. package/dist/lib/api/load-in-batches.js.map +1 -1
  15. package/dist/lib/api/load-loader.d.ts +2 -0
  16. package/dist/lib/api/load-loader.d.ts.map +1 -1
  17. package/dist/lib/api/load-loader.js +113 -7
  18. package/dist/lib/api/load-loader.js.map +1 -1
  19. package/dist/lib/api/load.d.ts +3 -3
  20. package/dist/lib/api/load.d.ts.map +1 -1
  21. package/dist/lib/api/load.js +36 -6
  22. package/dist/lib/api/load.js.map +1 -1
  23. package/dist/lib/api/parse-file.d.ts.map +1 -1
  24. package/dist/lib/api/parse-file.js +6 -2
  25. package/dist/lib/api/parse-file.js.map +1 -1
  26. package/dist/lib/api/parse-in-batches.d.ts.map +1 -1
  27. package/dist/lib/api/parse-in-batches.js +12 -3
  28. package/dist/lib/api/parse-in-batches.js.map +1 -1
  29. package/dist/lib/api/parse.d.ts.map +1 -1
  30. package/dist/lib/api/parse.js +11 -3
  31. package/dist/lib/api/parse.js.map +1 -1
  32. package/dist/lib/api/preload.d.ts +6 -3
  33. package/dist/lib/api/preload.d.ts.map +1 -1
  34. package/dist/lib/api/preload.js +4 -5
  35. package/dist/lib/api/preload.js.map +1 -1
  36. package/dist/lib/filesystems/browser-filesystem.d.ts.map +1 -1
  37. package/dist/lib/filesystems/browser-filesystem.js +25 -11
  38. package/dist/lib/filesystems/browser-filesystem.js.map +1 -1
  39. package/dist/lib/init.js +1 -1
  40. package/dist/lib/init.js.map +1 -1
  41. package/dist/lib/loader-utils/get-fetch-function.d.ts.map +1 -1
  42. package/dist/lib/loader-utils/get-fetch-function.js +16 -10
  43. package/dist/lib/loader-utils/get-fetch-function.js.map +1 -1
  44. package/dist/lib/loader-utils/loader-context.d.ts +1 -1
  45. package/dist/lib/loader-utils/loader-context.d.ts.map +1 -1
  46. package/dist/lib/loader-utils/loader-context.js +8 -3
  47. package/dist/lib/loader-utils/loader-context.js.map +1 -1
  48. package/dist/lib/loader-utils/option-defaults.d.ts.map +1 -1
  49. package/dist/lib/loader-utils/option-defaults.js +3 -0
  50. package/dist/lib/loader-utils/option-defaults.js.map +1 -1
  51. package/dist/lib/loader-utils/option-utils.d.ts +7 -0
  52. package/dist/lib/loader-utils/option-utils.d.ts.map +1 -1
  53. package/dist/lib/loader-utils/option-utils.js +41 -1
  54. package/dist/lib/loader-utils/option-utils.js.map +1 -1
  55. package/dist/lib/utils/response-utils.js +2 -11
  56. package/dist/lib/utils/response-utils.js.map +1 -1
  57. package/dist/null-loader.js +1 -1
  58. package/dist/null-loader.js.map +1 -1
  59. package/dist/null-worker-node.js +130 -58
  60. package/dist/null-worker.js +130 -58
  61. package/package.json +6 -6
  62. package/src/iterators/make-iterator/make-stream-iterator.ts +48 -10
  63. package/src/lib/api/create-data-source.ts +31 -2
  64. package/src/lib/api/load-in-batches.ts +18 -11
  65. package/src/lib/api/load-loader.ts +157 -14
  66. package/src/lib/api/load.ts +87 -9
  67. package/src/lib/api/parse-file.ts +15 -2
  68. package/src/lib/api/parse-in-batches.ts +22 -3
  69. package/src/lib/api/parse.ts +18 -3
  70. package/src/lib/api/preload.ts +22 -7
  71. package/src/lib/filesystems/browser-filesystem.ts +25 -11
  72. package/src/lib/loader-utils/get-fetch-function.ts +15 -14
  73. package/src/lib/loader-utils/loader-context.ts +8 -3
  74. package/src/lib/loader-utils/option-defaults.ts +3 -0
  75. package/src/lib/loader-utils/option-utils.ts +47 -1
  76. package/src/lib/utils/response-utils.ts +2 -12
package/dist/dist.dev.js CHANGED
@@ -10,7 +10,6 @@ var __exports__ = (() => {
10
10
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
11
  var __getOwnPropNames = Object.getOwnPropertyNames;
12
12
  var __hasOwnProp = Object.prototype.hasOwnProperty;
13
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
13
  var __export = (target, all) => {
15
14
  for (var name in all)
16
15
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -24,10 +23,6 @@ var __exports__ = (() => {
24
23
  return to;
25
24
  };
26
25
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
- var __publicField = (obj, key, value) => {
28
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
29
- return value;
30
- };
31
26
 
32
27
  // bundle.ts
33
28
  var bundle_exports = {};
@@ -686,7 +681,7 @@ var __exports__ = (() => {
686
681
  }
687
682
  const options = { ...baseOptions };
688
683
  for (const [key, newValue] of Object.entries(newOptions)) {
689
- if (newValue && typeof newValue === "object" && !Array.isArray(newValue)) {
684
+ if (isPureObject(newValue)) {
690
685
  options[key] = mergeOptionsRecursively(
691
686
  options[key] || {},
692
687
  newOptions[key],
@@ -784,7 +779,9 @@ var __exports__ = (() => {
784
779
  * Call to resolve the `result` Promise with the supplied value
785
780
  */
786
781
  done(value) {
787
- assert3(this.isRunning);
782
+ if (!this.isRunning) {
783
+ return;
784
+ }
788
785
  this.isRunning = false;
789
786
  this._resolve(value);
790
787
  }
@@ -792,14 +789,42 @@ var __exports__ = (() => {
792
789
  * Call to reject the `result` Promise with the supplied error
793
790
  */
794
791
  error(error) {
795
- assert3(this.isRunning);
792
+ if (!this.isRunning) {
793
+ return;
794
+ }
796
795
  this.isRunning = false;
797
796
  this._reject(error);
798
797
  }
798
+ /**
799
+ * Terminates the worker executing this job and rejects its result.
800
+ * @param reason Abort reason supplied by the caller, or a cross-runtime `AbortError`.
801
+ */
802
+ abort(reason) {
803
+ if (!this.isRunning) {
804
+ return;
805
+ }
806
+ const error = reason ?? createAbortError(`Worker job "${this.name}" was aborted`);
807
+ this.workerThread.destroy();
808
+ this.error(error);
809
+ }
799
810
  };
811
+ function createAbortError(message) {
812
+ const error = new Error(message);
813
+ error.name = "AbortError";
814
+ return error;
815
+ }
800
816
 
801
817
  // ../worker-utils/src/lib/node/worker_threads-browser.ts
802
818
  var NodeWorker = class {
819
+ /** Restores the native worker constructor when this browser shim is embedded in a Node bundle. */
820
+ constructor(...arguments_) {
821
+ const runtimeProcess = globalThis.process;
822
+ const WorkerConstructor = runtimeProcess?.getBuiltinModule?.("node:worker_threads").Worker;
823
+ if (WorkerConstructor) {
824
+ return new WorkerConstructor(...arguments_);
825
+ }
826
+ }
827
+ /** No-op browser fallback matching the native Worker API. */
803
828
  terminate() {
804
829
  }
805
830
  };
@@ -900,6 +925,10 @@ var __exports__ = (() => {
900
925
  name;
901
926
  source;
902
927
  url;
928
+ /** Lazily resolves the classic worker URL used as a fallback. */
929
+ getUrl;
930
+ /** Creates a browser Worker directly. */
931
+ loadWorker;
903
932
  terminated = false;
904
933
  worker;
905
934
  onMessage;
@@ -910,11 +939,13 @@ var __exports__ = (() => {
910
939
  return typeof Worker !== "undefined" && isBrowser3 || typeof NodeWorker !== "undefined" && !isBrowser3;
911
940
  }
912
941
  constructor(props) {
913
- const { name, source, url } = props;
914
- assert3(source || url);
942
+ const { name, source, url, getUrl, loadWorker } = props;
943
+ assert3(source || url || getUrl || loadWorker);
915
944
  this.name = name;
916
945
  this.source = source;
917
946
  this.url = url;
947
+ this.getUrl = getUrl;
948
+ this.loadWorker = loadWorker;
918
949
  this.onMessage = NOOP;
919
950
  this.onError = (error) => console.log(error);
920
951
  this.worker = isBrowser3 ? this._createBrowserWorker() : this._createNodeWorker();
@@ -960,7 +991,7 @@ var __exports__ = (() => {
960
991
  */
961
992
  _getErrorFromErrorEvent(event) {
962
993
  let message = "Failed to load ";
963
- message += `worker ${this.name} from ${this.url}. `;
994
+ message += `worker ${this.name} from ${this.url || "built-in worker factory"}. `;
964
995
  if (event.message) {
965
996
  message += `${event.message} in `;
966
997
  }
@@ -973,8 +1004,25 @@ var __exports__ = (() => {
973
1004
  * Creates a worker thread on the browser
974
1005
  */
975
1006
  _createBrowserWorker() {
976
- this._loadableURL = getLoadableWorkerURL({ source: this.source, url: this.url });
1007
+ if (this.loadWorker) {
1008
+ try {
1009
+ const worker2 = this.loadWorker();
1010
+ if (worker2) {
1011
+ return this._initializeBrowserWorker(worker2);
1012
+ }
1013
+ } catch (error) {
1014
+ if (!this.source && !this.url && !this.getUrl) {
1015
+ throw error;
1016
+ }
1017
+ }
1018
+ }
1019
+ const url = this.url || this.getUrl?.();
1020
+ this._loadableURL = getLoadableWorkerURL({ source: this.source, url });
977
1021
  const worker = new Worker(this._loadableURL, { name: this.name });
1022
+ return this._initializeBrowserWorker(worker);
1023
+ }
1024
+ /** Attaches protocol handlers to a browser worker. */
1025
+ _initializeBrowserWorker(worker) {
978
1026
  worker.onmessage = (event) => {
979
1027
  if (!event.data) {
980
1028
  this.onError(new Error("No data received"));
@@ -998,8 +1046,9 @@ var __exports__ = (() => {
998
1046
  if (this.url) {
999
1047
  const absolute = this.url.includes(":/") || this.url.startsWith("/");
1000
1048
  const url = absolute ? this.url : `./${this.url}`;
1049
+ const workerUrl = url.startsWith("file:") ? new URL(url) : url;
1001
1050
  const type = this.url.endsWith(".ts") || this.url.endsWith(".mjs") ? "module" : "commonjs";
1002
- worker = new NodeWorker(url, { eval: false, type });
1051
+ worker = new NodeWorker(workerUrl, { eval: false, type });
1003
1052
  } else if (this.source) {
1004
1053
  worker = new NodeWorker(this.source, { eval: true });
1005
1054
  } else {
@@ -1023,6 +1072,10 @@ var __exports__ = (() => {
1023
1072
  source;
1024
1073
  // | Function;
1025
1074
  url;
1075
+ /** Lazily resolves a classic worker fallback URL. */
1076
+ getUrl;
1077
+ /** Creates a browser Worker directly. */
1078
+ loadWorker;
1026
1079
  maxConcurrency = 1;
1027
1080
  maxMobileConcurrency = 1;
1028
1081
  onDebug = () => {
@@ -1031,6 +1084,7 @@ var __exports__ = (() => {
1031
1084
  props = {};
1032
1085
  jobQueue = [];
1033
1086
  idleQueue = [];
1087
+ activeJobs = /* @__PURE__ */ new Set();
1034
1088
  count = 0;
1035
1089
  isDestroyed = false;
1036
1090
  /** Checks if workers are supported on this platform */
@@ -1044,13 +1098,19 @@ var __exports__ = (() => {
1044
1098
  constructor(props) {
1045
1099
  this.source = props.source;
1046
1100
  this.url = props.url;
1101
+ this.getUrl = props.getUrl;
1102
+ this.loadWorker = props.loadWorker;
1047
1103
  this.setProps(props);
1048
1104
  }
1049
1105
  /**
1050
- * Terminates all workers in the pool
1106
+ * Terminates all workers in the pool and aborts active jobs.
1107
+ * @param reason Optional error delivered to active jobs.
1051
1108
  * @note Can free up significant memory
1052
1109
  */
1053
- destroy() {
1110
+ destroy(reason = new Error("Worker pool was destroyed")) {
1111
+ this.activeJobs.forEach((job) => job.abort(reason));
1112
+ const queuedJobs = this.jobQueue.splice(0);
1113
+ queuedJobs.forEach((queuedJob) => queuedJob.onReject(reason));
1054
1114
  this.idleQueue.forEach((worker) => worker.destroy());
1055
1115
  this.isDestroyed = true;
1056
1116
  }
@@ -1073,8 +1133,11 @@ var __exports__ = (() => {
1073
1133
  }
1074
1134
  }
1075
1135
  async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
1076
- const startPromise = new Promise((onStart) => {
1077
- this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart });
1136
+ if (this.isDestroyed) {
1137
+ return Promise.reject(new Error("Worker pool was destroyed"));
1138
+ }
1139
+ const startPromise = new Promise((onStart, onReject) => {
1140
+ this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart, onReject });
1078
1141
  return this;
1079
1142
  });
1080
1143
  this._startQueuedJob();
@@ -1102,6 +1165,7 @@ var __exports__ = (() => {
1102
1165
  backlog: this.jobQueue.length
1103
1166
  });
1104
1167
  const job = new WorkerJob(queuedJob.name, workerThread);
1168
+ this.activeJobs.add(job);
1105
1169
  workerThread.ref();
1106
1170
  workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
1107
1171
  workerThread.onError = (error) => queuedJob.onError(job, error);
@@ -1110,6 +1174,7 @@ var __exports__ = (() => {
1110
1174
  await job.result;
1111
1175
  } catch {
1112
1176
  } finally {
1177
+ this.activeJobs.delete(job);
1113
1178
  this.returnWorkerToQueue(workerThread);
1114
1179
  }
1115
1180
  }
@@ -1124,13 +1189,16 @@ var __exports__ = (() => {
1124
1189
  */
1125
1190
  returnWorkerToQueue(worker) {
1126
1191
  const shouldDestroyWorker = (
1127
- // If the pool is destroyed, there is no reason to keep the worker around
1192
+ // Aborted jobs terminate their worker immediately.
1193
+ worker.terminated || // If the pool is destroyed, there is no reason to keep the worker around
1128
1194
  this.isDestroyed || // If the app has disabled worker reuse, any completed workers should be destroyed
1129
1195
  !this.reuseWorkers || // If concurrency has been lowered, this worker might be surplus to requirements
1130
1196
  this.count > this._getMaxConcurrency()
1131
1197
  );
1132
1198
  if (shouldDestroyWorker) {
1133
- worker.destroy();
1199
+ if (!worker.terminated) {
1200
+ worker.destroy();
1201
+ }
1134
1202
  this.count--;
1135
1203
  } else {
1136
1204
  worker.unref();
@@ -1150,7 +1218,13 @@ var __exports__ = (() => {
1150
1218
  if (this.count < this._getMaxConcurrency()) {
1151
1219
  this.count++;
1152
1220
  const name = `${this.name.toLowerCase()} (#${this.count} of ${this.maxConcurrency})`;
1153
- return new WorkerThread({ name, source: this.source, url: this.url });
1221
+ return new WorkerThread({
1222
+ name,
1223
+ source: this.source,
1224
+ url: this.url,
1225
+ getUrl: this.getUrl,
1226
+ loadWorker: this.loadWorker
1227
+ });
1154
1228
  }
1155
1229
  return null;
1156
1230
  }
@@ -1167,9 +1241,13 @@ var __exports__ = (() => {
1167
1241
  onDebug: () => {
1168
1242
  }
1169
1243
  };
1170
- var _WorkerFarm = class {
1244
+ var loadWorkerIds = /* @__PURE__ */ new WeakMap();
1245
+ var nextLoadWorkerId = 1;
1246
+ var WorkerFarm = class _WorkerFarm {
1171
1247
  props;
1172
1248
  workerPools = /* @__PURE__ */ new Map();
1249
+ // singleton
1250
+ static _workerFarm;
1173
1251
  /** Checks if workers are supported on this platform */
1174
1252
  static isSupported() {
1175
1253
  return WorkerThread.isSupported();
@@ -1187,12 +1265,13 @@ var __exports__ = (() => {
1187
1265
  this.workerPools = /* @__PURE__ */ new Map();
1188
1266
  }
1189
1267
  /**
1190
- * Terminate all workers in the farm
1268
+ * Terminate all workers in the farm and abort active jobs.
1269
+ * @param reason Optional error delivered to active jobs.
1191
1270
  * @note Can free up significant memory
1192
1271
  */
1193
- destroy() {
1272
+ destroy(reason) {
1194
1273
  for (const workerPool of this.workerPools.values()) {
1195
- workerPool.destroy();
1274
+ workerPool.destroy(reason);
1196
1275
  }
1197
1276
  this.workerPools = /* @__PURE__ */ new Map();
1198
1277
  }
@@ -1208,24 +1287,28 @@ var __exports__ = (() => {
1208
1287
  }
1209
1288
  /**
1210
1289
  * Returns a worker pool for the specified worker
1211
- * @param options - only used first time for a specific worker name
1212
- * @param options.name - the name of the worker - used to identify worker pool
1213
- * @param options.url -
1214
- * @param options.source -
1290
+ * @param options Worker target used to identify and initialize the pool.
1291
+ * @param options.name Worker name used as the base pool identity.
1292
+ * @param options.url Worker script URL.
1293
+ * @param options.source Inline worker source.
1294
+ * @param options.loadWorker Built-in browser worker factory.
1215
1295
  * @example
1216
1296
  * const job = WorkerFarm.getWorkerFarm().getWorkerPool({name, url}).startJob(...);
1217
1297
  */
1218
1298
  getWorkerPool(options) {
1219
- const { name, source, url } = options;
1220
- let workerPool = this.workerPools.get(name);
1299
+ const { name, source, url, getUrl, loadWorker } = options;
1300
+ const workerPoolKey = getWorkerPoolKey(options);
1301
+ let workerPool = this.workerPools.get(workerPoolKey);
1221
1302
  if (!workerPool) {
1222
1303
  workerPool = new WorkerPool({
1223
1304
  name,
1224
1305
  source,
1225
- url
1306
+ url,
1307
+ getUrl,
1308
+ loadWorker
1226
1309
  });
1227
1310
  workerPool.setProps(this._getWorkerPoolProps());
1228
- this.workerPools.set(name, workerPool);
1311
+ this.workerPools.set(workerPoolKey, workerPool);
1229
1312
  }
1230
1313
  return workerPool;
1231
1314
  }
@@ -1238,9 +1321,91 @@ var __exports__ = (() => {
1238
1321
  };
1239
1322
  }
1240
1323
  };
1241
- var WorkerFarm = _WorkerFarm;
1242
- // singleton
1243
- __publicField(WorkerFarm, "_workerFarm");
1324
+ function getWorkerPoolKey(options) {
1325
+ const { name, source, url, urlKey, loadWorker } = options;
1326
+ const sourceKey = source ? `source:${source}` : "";
1327
+ const urlKeyPart = url || urlKey ? `url:${url || urlKey}` : "";
1328
+ const loadWorkerKey = loadWorker ? `loadWorker:${getLoadWorkerId(loadWorker)}` : "";
1329
+ return [name, sourceKey, urlKeyPart, loadWorkerKey].filter(Boolean).join("|");
1330
+ }
1331
+ function getLoadWorkerId(loadWorker) {
1332
+ let loadWorkerId = loadWorkerIds.get(loadWorker);
1333
+ if (!loadWorkerId) {
1334
+ loadWorkerId = nextLoadWorkerId++;
1335
+ loadWorkerIds.set(loadWorker, loadWorkerId);
1336
+ }
1337
+ return loadWorkerId;
1338
+ }
1339
+
1340
+ // ../worker-utils/src/lib/async-queue/async-queue.ts
1341
+ var AsyncQueue = class {
1342
+ _values;
1343
+ _settlers;
1344
+ _closed;
1345
+ constructor() {
1346
+ this._values = [];
1347
+ this._settlers = [];
1348
+ this._closed = false;
1349
+ }
1350
+ /** Return an async iterator for this queue */
1351
+ [Symbol.asyncIterator]() {
1352
+ return this;
1353
+ }
1354
+ /** Push a new value - the async iterator will yield a promise resolved to this value */
1355
+ push(value) {
1356
+ return this.enqueue(value);
1357
+ }
1358
+ /**
1359
+ * Push a new value - the async iterator will yield a promise resolved to this value
1360
+ * Add an error - the async iterator will yield a promise rejected with this value
1361
+ */
1362
+ enqueue(value) {
1363
+ if (this._closed) {
1364
+ throw new Error("Closed");
1365
+ }
1366
+ if (this._settlers.length > 0) {
1367
+ if (this._values.length > 0) {
1368
+ throw new Error("Illegal internal state");
1369
+ }
1370
+ const settler = this._settlers.shift();
1371
+ if (value instanceof Error) {
1372
+ settler.reject(value);
1373
+ } else {
1374
+ settler.resolve({ value });
1375
+ }
1376
+ } else {
1377
+ this._values.push(value);
1378
+ }
1379
+ }
1380
+ /** Indicate that we not waiting for more values - The async iterator will be done */
1381
+ close() {
1382
+ while (this._settlers.length > 0) {
1383
+ const settler = this._settlers.shift();
1384
+ settler.resolve({ done: true });
1385
+ }
1386
+ this._closed = true;
1387
+ }
1388
+ // ITERATOR IMPLEMENTATION
1389
+ /** @returns a Promise for an IteratorResult */
1390
+ next() {
1391
+ if (this._values.length > 0) {
1392
+ const value = this._values.shift();
1393
+ if (value instanceof Error) {
1394
+ return Promise.reject(value);
1395
+ }
1396
+ return Promise.resolve({ done: false, value });
1397
+ }
1398
+ if (this._closed) {
1399
+ if (this._settlers.length > 0) {
1400
+ throw new Error("Illegal internal state");
1401
+ }
1402
+ return Promise.resolve({ done: true, value: void 0 });
1403
+ }
1404
+ return new Promise((resolve2, reject) => {
1405
+ this._settlers.push({ resolve: resolve2, reject });
1406
+ });
1407
+ }
1408
+ };
1244
1409
 
1245
1410
  // ../worker-utils/src/lib/worker-api/get-worker-url.ts
1246
1411
  var warnedWorkerVersionFallbacks = /* @__PURE__ */ new Set();
@@ -1248,31 +1413,41 @@ var __exports__ = (() => {
1248
1413
  const warning = worker.version !== VERSION3 ? ` (worker-utils@${VERSION3})` : "";
1249
1414
  return `${worker.name}@${worker.version}${warning}`;
1250
1415
  }
1251
- function getWorkerURL(worker, options = {}) {
1416
+ function getCustomWorkerURL(worker, options = {}) {
1252
1417
  const workerOptions = options[worker.id] || {};
1253
- const workerFile = isBrowser3 ? `${worker.id}-worker.js` : `${worker.id}-worker-node.js`;
1418
+ const workerFile = isBrowser3 ? worker.workerFile || `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
1254
1419
  let url = workerOptions.workerUrl;
1255
1420
  if (!url && worker.id === "compression") {
1256
1421
  url = options.workerUrl;
1257
1422
  }
1258
1423
  const workerType = options._workerType || options?.core?._workerType;
1259
- if (workerType === "test") {
1424
+ if (!url && workerType === "test") {
1260
1425
  if (isBrowser3) {
1261
1426
  url = `modules/${worker.module}/dist/${workerFile}`;
1262
1427
  } else {
1263
1428
  url = `modules/${worker.module}/src/workers/${worker.id}-worker-node.ts`;
1264
1429
  }
1265
1430
  }
1266
- if (!url) {
1267
- let version2 = worker.version;
1268
- if (version2 === "latest") {
1269
- version2 = NPM_TAG;
1270
- }
1271
- const versionTag = version2 ? `@${version2}` : "";
1272
- url = `https://unpkg.com/@loaders.gl/${worker.module}${versionTag}/dist/${workerFile}`;
1431
+ return url || null;
1432
+ }
1433
+ function getWorkerURL(worker, options = {}) {
1434
+ const customWorkerUrl = getCustomWorkerURL(worker, options);
1435
+ const descriptorWorkerUrl = typeof worker.worker === "string" ? worker.worker : null;
1436
+ const url = customWorkerUrl || descriptorWorkerUrl || getDefaultWorkerURL(worker, true);
1437
+ assert3(url);
1438
+ return url;
1439
+ }
1440
+ function getDefaultWorkerURL(worker, warn = false) {
1441
+ const workerFile = isBrowser3 ? worker.workerFile || `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
1442
+ let version2 = worker.version;
1443
+ if (version2 === "latest") {
1444
+ version2 = NPM_TAG;
1445
+ }
1446
+ const versionTag = version2 ? `@${version2}` : "";
1447
+ const url = `https://unpkg.com/@loaders.gl/${worker.module}${versionTag}/dist/${workerFile}`;
1448
+ if (warn) {
1273
1449
  warnIfUsingNpmTagFallback(worker, url);
1274
1450
  }
1275
- assert3(url);
1276
1451
  return url;
1277
1452
  }
1278
1453
  function warnIfUsingNpmTagFallback(worker, url) {
@@ -1294,32 +1469,197 @@ var __exports__ = (() => {
1294
1469
  if (!WorkerFarm.isSupported()) {
1295
1470
  return false;
1296
1471
  }
1297
- return worker.worker && options?.worker;
1472
+ const workerOptions = options?.[worker.id];
1473
+ return Boolean(
1474
+ (worker.worker || worker.loadWorker || workerOptions?.workerUrl) && options?.worker
1475
+ );
1298
1476
  }
1299
1477
  async function processOnWorker(worker, data, options = {}, context = {}, jobContext = {}) {
1478
+ throwIfAborted(options.signal);
1300
1479
  const name = getWorkerName(worker);
1301
1480
  const workerFarm = WorkerFarm.getWorkerFarm(options);
1302
- const { source } = options;
1303
- const workerPoolProps = { name, source };
1304
- if (!source) {
1305
- workerPoolProps.url = getWorkerURL(worker, options);
1306
- }
1307
- const workerPool = workerFarm.getWorkerPool(workerPoolProps);
1481
+ const workerPool = workerFarm.getWorkerPool(getWorkerPoolTarget(worker, options, name));
1308
1482
  const jobName = options.jobName || worker.name;
1309
1483
  const job = await workerPool.startJob(
1310
1484
  jobName,
1311
1485
  // eslint-disable-next-line
1312
1486
  onMessage.bind(null, context)
1313
1487
  );
1314
- const transferableOptions = getTransferListForWriter(options);
1315
- const transferableContext = getTransferListForWriter(jobContext);
1316
- job.postMessage("process", {
1317
- input: data,
1318
- options: transferableOptions,
1319
- context: transferableContext
1320
- });
1321
- const result = await job.result;
1322
- return result.result;
1488
+ const abortJob = () => job.abort(getAbortReason(options.signal));
1489
+ options.signal?.addEventListener("abort", abortJob, { once: true });
1490
+ if (options.signal?.aborted) {
1491
+ abortJob();
1492
+ }
1493
+ try {
1494
+ const { signal: _signal, ...workerOptions } = options;
1495
+ const transferableOptions = getTransferListForWriter(workerOptions);
1496
+ const transferableContext = getTransferListForWriter(jobContext);
1497
+ if (job.isRunning) {
1498
+ job.postMessage("process", {
1499
+ input: data,
1500
+ options: transferableOptions,
1501
+ context: transferableContext
1502
+ });
1503
+ }
1504
+ const result = await job.result;
1505
+ return result.result;
1506
+ } finally {
1507
+ options.signal?.removeEventListener("abort", abortJob);
1508
+ }
1509
+ }
1510
+ function processOnWorkerInBatches(worker, input, options = {}, context = {}, jobContext = {}) {
1511
+ return processOnWorkerInBatchesIterator(worker, input, options, context, jobContext);
1512
+ }
1513
+ async function* processOnWorkerInBatchesIterator(worker, input, options, context, jobContext) {
1514
+ throwIfAborted(options.signal);
1515
+ const name = getWorkerName(worker);
1516
+ const workerFarm = WorkerFarm.getWorkerFarm(options);
1517
+ const workerPool = workerFarm.getWorkerPool(getWorkerPoolTarget(worker, options, name));
1518
+ const outputBatches = new AsyncQueue();
1519
+ const inputIterator = getAsyncIterator(input);
1520
+ let outputFinished = false;
1521
+ let inputFinished = false;
1522
+ let inputRequest = Promise.resolve();
1523
+ const batchJobFailed = new Error("Worker batch job failed");
1524
+ const finishOutput = () => {
1525
+ if (!outputFinished) {
1526
+ outputFinished = true;
1527
+ outputBatches.close();
1528
+ }
1529
+ };
1530
+ const failOutput = (_error) => {
1531
+ if (!outputFinished) {
1532
+ outputFinished = true;
1533
+ outputBatches.enqueue(batchJobFailed);
1534
+ outputBatches.close();
1535
+ }
1536
+ };
1537
+ const job = await workerPool.startJob(
1538
+ options.jobName || worker.name,
1539
+ (activeJob, type, payload) => {
1540
+ switch (type) {
1541
+ case "input-request":
1542
+ inputRequest = inputRequest.then(async () => {
1543
+ const nextBatch = await inputIterator.next();
1544
+ if (!activeJob.isRunning) {
1545
+ return;
1546
+ }
1547
+ if (nextBatch.done) {
1548
+ inputFinished = true;
1549
+ activeJob.postMessage("input-done", {});
1550
+ } else {
1551
+ activeJob.postMessage("input-batch", { input: nextBatch.value });
1552
+ }
1553
+ }).catch((error) => activeJob.abort(error));
1554
+ break;
1555
+ case "output-batch":
1556
+ outputBatches.push(payload.result);
1557
+ break;
1558
+ case "done":
1559
+ activeJob.done(payload);
1560
+ finishOutput();
1561
+ break;
1562
+ case "error": {
1563
+ const error = new Error(payload.error || "Worker batch processing failed");
1564
+ activeJob.error(error);
1565
+ failOutput(error);
1566
+ break;
1567
+ }
1568
+ case "process":
1569
+ void onMessage(context, activeJob, type, payload);
1570
+ break;
1571
+ default: {
1572
+ const error = new Error(`Unexpected worker batch message: ${type}`);
1573
+ activeJob.error(error);
1574
+ failOutput(error);
1575
+ break;
1576
+ }
1577
+ }
1578
+ }
1579
+ );
1580
+ const abortJob = () => job.abort(getAbortReason(options.signal));
1581
+ options.signal?.addEventListener("abort", abortJob, { once: true });
1582
+ if (options.signal?.aborted) {
1583
+ abortJob();
1584
+ }
1585
+ void job.result.catch(failOutput);
1586
+ try {
1587
+ const { signal: _signal, ...workerOptions } = options;
1588
+ if (job.isRunning) {
1589
+ job.postMessage("process-in-batches", {
1590
+ options: getTransferListForWriter(workerOptions),
1591
+ context: getTransferListForWriter(jobContext)
1592
+ });
1593
+ }
1594
+ try {
1595
+ for await (const outputBatch of outputBatches) {
1596
+ yield outputBatch;
1597
+ if (job.isRunning) {
1598
+ job.postMessage("output-ack", {});
1599
+ }
1600
+ }
1601
+ } catch (error) {
1602
+ if (error === batchJobFailed) {
1603
+ await job.result;
1604
+ }
1605
+ throw error;
1606
+ }
1607
+ await job.result;
1608
+ } finally {
1609
+ options.signal?.removeEventListener("abort", abortJob);
1610
+ if (job.isRunning) {
1611
+ job.abort(createAbortError2("Worker batch iterator was closed"));
1612
+ }
1613
+ if (!inputFinished) {
1614
+ closeInputIterator(inputIterator);
1615
+ }
1616
+ }
1617
+ }
1618
+ function throwIfAborted(signal) {
1619
+ if (!signal?.aborted) {
1620
+ return;
1621
+ }
1622
+ throw getAbortReason(signal);
1623
+ }
1624
+ function getAbortReason(signal) {
1625
+ return signal?.reason ?? createAbortError2("Worker job was aborted");
1626
+ }
1627
+ function createAbortError2(message) {
1628
+ const error = new Error(message);
1629
+ error.name = "AbortError";
1630
+ return error;
1631
+ }
1632
+ function getAsyncIterator(input) {
1633
+ if (Symbol.asyncIterator in input) {
1634
+ return input[Symbol.asyncIterator]();
1635
+ }
1636
+ return (async function* iterateSynchronously() {
1637
+ yield* input;
1638
+ })();
1639
+ }
1640
+ function closeInputIterator(inputIterator) {
1641
+ try {
1642
+ void Promise.resolve(inputIterator.return?.()).catch(() => void 0);
1643
+ } catch {
1644
+ }
1645
+ }
1646
+ function getWorkerPoolTarget(worker, options, name) {
1647
+ if (options.source) {
1648
+ return { name, source: options.source };
1649
+ }
1650
+ const customWorkerUrl = getCustomWorkerURL(worker, options);
1651
+ if (customWorkerUrl) {
1652
+ return { name, url: customWorkerUrl };
1653
+ }
1654
+ if (isBrowser3 && worker.loadWorker) {
1655
+ return {
1656
+ name,
1657
+ loadWorker: worker.loadWorker,
1658
+ getUrl: () => getWorkerURL(worker, options),
1659
+ urlKey: getDefaultWorkerURL(worker)
1660
+ };
1661
+ }
1662
+ return { name, url: getWorkerURL(worker, options) };
1323
1663
  }
1324
1664
  async function onMessage(context, job, type, payload) {
1325
1665
  switch (type) {
@@ -1360,12 +1700,16 @@ var __exports__ = (() => {
1360
1700
 
1361
1701
  // ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
1362
1702
  function canParseWithWorker(loader, options) {
1703
+ if (options?.core?.credentials?.some(
1704
+ (credential) => credential.type === "request" || "token" in credential && typeof credential.token === "function"
1705
+ ))
1706
+ return false;
1363
1707
  const workerOptions = getWorkerOptions(options);
1364
1708
  const nodeWorkers = workerOptions._nodeWorkers;
1365
1709
  if (!isBrowser3 && !nodeWorkers) {
1366
1710
  return false;
1367
1711
  }
1368
- if (loader.id === "excel" && options?.excel?.shape === "arrow-table" || loader.id === "ply" && options?.ply?.shape === "arrow-table") {
1712
+ if (loader.id === "las" && (options?.las?.shape ?? "arrow-table") === "arrow-table") {
1369
1713
  return false;
1370
1714
  }
1371
1715
  if (loader.id === "csv" && !shouldParseCSVWithWorker(options)) {
@@ -1373,22 +1717,42 @@ var __exports__ = (() => {
1373
1717
  }
1374
1718
  return Boolean(canProcessOnWorker(loader, workerOptions));
1375
1719
  }
1376
- async function parseWithWorker(loader, data, options, context, parseOnMainThread) {
1720
+ function shouldParseWithWorker(loader, data, options, context, estimateLoader = loader) {
1721
+ if (!canParseWithWorker(loader, options)) {
1722
+ return false;
1723
+ }
1724
+ if (options?.core?.worker !== "auto" || !estimateLoader.getWorkerEstimate) {
1725
+ return true;
1726
+ }
1727
+ try {
1728
+ const estimate = estimateLoader.getWorkerEstimate(data, options, context);
1729
+ if (estimate === void 0 || !Number.isFinite(estimate) || estimate < 0 || estimate > 1) {
1730
+ return true;
1731
+ }
1732
+ return estimate >= (options.core?.workerThreshold ?? 0.1);
1733
+ } catch {
1734
+ return true;
1735
+ }
1736
+ }
1737
+ async function parseWithWorker(loader, data, options, context, parseOnMainThread, signal) {
1738
+ const workerSignal = signal || getWorkerAbortSignal(options);
1377
1739
  const result = await processOnWorker(
1378
1740
  loader,
1379
1741
  data,
1380
- getWorkerOptions(options),
1742
+ { ...getWorkerOptions(options, loader), signal: workerSignal },
1381
1743
  {
1382
1744
  process: async (input, processOptions, _workerContext, parseContext) => {
1383
1745
  if (!parseOnMainThread) {
1384
1746
  throw new Error("Worker not set up to parse on main thread");
1385
1747
  }
1386
- const mainThreadContext = context ? { ...context, ...parseContext || {} } : void 0;
1748
+ const { _loaderIds, _loaderIsArray, ...workerParseContext } = parseContext || {};
1749
+ const mainThreadContext = context || parseContext ? { ...context, ...workerParseContext } : void 0;
1387
1750
  return await callParseOnMainThread(
1388
1751
  parseOnMainThread,
1389
1752
  input,
1390
1753
  processOptions,
1391
- mainThreadContext
1754
+ mainThreadContext,
1755
+ resolveWorkerLoaders(loader, _loaderIds, _loaderIsArray, context, options)
1392
1756
  );
1393
1757
  }
1394
1758
  },
@@ -1396,18 +1760,93 @@ var __exports__ = (() => {
1396
1760
  );
1397
1761
  return isLoaderWithWorkerResultDeserializer(loader) ? loader.deserializeWorkerResult(result, options, context) : result;
1398
1762
  }
1399
- function callParseOnMainThread(parseOnMainThread, input, options, context) {
1400
- if (parseOnMainThread.length <= 2) {
1763
+ async function* parseWithWorkerInBatches(loader, inputIterator, options, context, parseOnMainThread, signal) {
1764
+ const workerSignal = signal || getWorkerAbortSignal(options);
1765
+ const outputIterator = processOnWorkerInBatches(
1766
+ loader,
1767
+ inputIterator,
1768
+ { ...getWorkerOptions(options), signal: workerSignal },
1769
+ {
1770
+ process: async (input, processOptions, _workerContext, parseContext) => {
1771
+ if (!parseOnMainThread) {
1772
+ throw new Error("Worker not set up to parse on main thread");
1773
+ }
1774
+ const { _loaderIds, _loaderIsArray, ...workerParseContext } = parseContext || {};
1775
+ const mainThreadContext = context || parseContext ? { ...context, ...workerParseContext } : void 0;
1776
+ return await callParseOnMainThread(
1777
+ parseOnMainThread,
1778
+ input,
1779
+ processOptions,
1780
+ mainThreadContext,
1781
+ resolveWorkerLoaders(loader, _loaderIds, _loaderIsArray, context, options)
1782
+ );
1783
+ }
1784
+ },
1785
+ getSerializableLoaderContext(context)
1786
+ );
1787
+ for await (const batch of outputIterator) {
1788
+ yield loader.deserializeWorkerBatch ? loader.deserializeWorkerBatch(batch, options, context) : batch;
1789
+ }
1790
+ }
1791
+ function getWorkerAbortSignal(options) {
1792
+ const parquetSignal = options?.parquet?.signal;
1793
+ if (typeof AbortSignal !== "undefined" && parquetSignal instanceof AbortSignal) {
1794
+ return parquetSignal;
1795
+ }
1796
+ return void 0;
1797
+ }
1798
+ function callParseOnMainThread(parseOnMainThread, input, options, context, loaders) {
1799
+ if (!loaders && parseOnMainThread.length <= 2) {
1401
1800
  return parseOnMainThread(input, options);
1402
1801
  }
1403
- return parseOnMainThread(input, void 0, options, context);
1802
+ return parseOnMainThread(input, loaders, options, context);
1404
1803
  }
1405
- function getWorkerOptions(options = {}) {
1406
- const serializedOptions = JSON.parse(JSON.stringify(options));
1407
- return {
1804
+ function resolveWorkerLoaders(loader, loaderIds, loaderIsArray, context, options) {
1805
+ if (!loaderIds) return void 0;
1806
+ const availableLoaders = /* @__PURE__ */ new Map();
1807
+ const visitedLoaders = /* @__PURE__ */ new Set();
1808
+ for (const candidate of [loader, ...context?.loaders || []]) {
1809
+ visitLoader(candidate);
1810
+ }
1811
+ const selectedLoaders = loaderIds.map((loaderId) => {
1812
+ const selectedLoader = availableLoaders.get(loaderId);
1813
+ if (!selectedLoader) {
1814
+ throw new Error(
1815
+ `Worker requested unknown loader "${loaderId}". Declare it in loader.subloaders or pass it in context.loaders.`
1816
+ );
1817
+ }
1818
+ return selectedLoader;
1819
+ });
1820
+ return loaderIsArray ? selectedLoaders : selectedLoaders[0];
1821
+ function visitLoader(candidate) {
1822
+ if (visitedLoaders.has(candidate)) return;
1823
+ visitedLoaders.add(candidate);
1824
+ availableLoaders.set(candidate.id, candidate);
1825
+ for (const [name, dependency] of Object.entries(candidate.subloaders || {})) {
1826
+ const replacement = options?.core?.subloaders?.[name] || dependency;
1827
+ visitLoader(replacement);
1828
+ availableLoaders.set(dependency.id, replacement);
1829
+ }
1830
+ }
1831
+ }
1832
+ function getWorkerOptions(options = {}, loader) {
1833
+ const serializedOptions = JSON.parse(
1834
+ JSON.stringify({
1835
+ ...options,
1836
+ ...options.core ? { core: { ...options.core, authentications: void 0 } } : {}
1837
+ })
1838
+ );
1839
+ const workerOptions = {
1408
1840
  ...serializedOptions.core,
1409
1841
  ...serializedOptions
1410
1842
  };
1843
+ if (workerOptions.worker === "auto") {
1844
+ workerOptions.worker = true;
1845
+ }
1846
+ if (loader) {
1847
+ workerOptions._workerLoaderId = loader.id;
1848
+ }
1849
+ return workerOptions;
1411
1850
  }
1412
1851
  function getSerializableLoaderContext(context) {
1413
1852
  if (!context) {
@@ -1469,6 +1908,19 @@ var __exports__ = (() => {
1469
1908
  return result.buffer;
1470
1909
  }
1471
1910
 
1911
+ // ../loader-utils/src/lib/binary-utils/encode-array-buffer-to-base64.ts
1912
+ function encodeArrayBufferToBase64(arrayBuffer) {
1913
+ const bytes = new Uint8Array(arrayBuffer);
1914
+ const encodedChunks = [];
1915
+ const chunkByteLength = 3 * 4096;
1916
+ for (let byteOffset = 0; byteOffset < bytes.length; byteOffset += chunkByteLength) {
1917
+ encodedChunks.push(
1918
+ btoa(String.fromCharCode(...bytes.subarray(byteOffset, byteOffset + chunkByteLength)))
1919
+ );
1920
+ }
1921
+ return encodedChunks.join("");
1922
+ }
1923
+
1472
1924
  // ../loader-utils/src/lib/iterators/text-iterators.ts
1473
1925
  async function* makeTextDecoderIterator(arrayBufferIterator, options = {}) {
1474
1926
  const textDecoder = new TextDecoder(void 0, options);
@@ -1795,6 +2247,7 @@ var __exports__ = (() => {
1795
2247
  /** Tracks the number of active requests and prioritizes/cancels queued requests. */
1796
2248
  requestQueue = [];
1797
2249
  requestMap = /* @__PURE__ */ new Map();
2250
+ /** Pending arrival debounce or next-tick refill; only new arrivals replace this timer. */
1798
2251
  updateTimer = null;
1799
2252
  constructor(props = {}) {
1800
2253
  this.props = { ...DEFAULT_PROPS2, ...props };
@@ -1862,20 +2315,27 @@ var __exports__ = (() => {
1862
2315
  isDone = true;
1863
2316
  this.requestMap.delete(handle);
1864
2317
  this.activeRequestCount--;
1865
- this._issueNewRequests();
2318
+ this.scheduleRefill();
1866
2319
  }
1867
2320
  };
1868
2321
  this.activeRequestCount++;
1869
2322
  return resolve2 ? resolve2({ done }) : Promise.resolve({ done });
1870
2323
  }
1871
- /** We check requests asynchronously, to prevent multiple updates */
2324
+ /** Refills freed slots on the next tick while preserving any pending arrival debounce. */
2325
+ scheduleRefill() {
2326
+ if (this.updateTimer !== null) {
2327
+ return;
2328
+ }
2329
+ this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), 0);
2330
+ }
2331
+ /** Restarts the quiet period when a new request enters the queue. */
1872
2332
  _issueNewRequests() {
1873
2333
  if (this.updateTimer !== null) {
1874
2334
  clearTimeout(this.updateTimer);
1875
2335
  }
1876
2336
  this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), this.props.debounceTime);
1877
2337
  }
1878
- /** Refresh all requests */
2338
+ /** Clears timer ownership before updating priorities and dispatching queued requests. */
1879
2339
  _issueNewRequestsAsync() {
1880
2340
  if (this.updateTimer !== null) {
1881
2341
  clearTimeout(this.updateTimer);
@@ -1917,6 +2377,267 @@ var __exports__ = (() => {
1917
2377
  }
1918
2378
  };
1919
2379
 
2380
+ // ../loader-utils/src/lib/request-utils/authentication.ts
2381
+ function resolveCredentials(credentials, authentications = []) {
2382
+ if (credentials.every(isAuthentication)) return credentials;
2383
+ return credentials.map((credential, index) => {
2384
+ if (isAuthentication(credential)) return credential;
2385
+ const AuthenticationClass = authentications.find(
2386
+ (authentication2) => authentication2.type === credential?.type
2387
+ );
2388
+ if (!AuthenticationClass) {
2389
+ throw new Error(`No authentication class registered for credential at index ${index}.`);
2390
+ }
2391
+ let authentication;
2392
+ try {
2393
+ authentication = new AuthenticationClass(credential);
2394
+ } catch {
2395
+ throw new Error(`Invalid authentication configuration at index ${index}.`);
2396
+ }
2397
+ if (!isAuthentication(authentication)) {
2398
+ throw new Error(`Authentication class returned an invalid credential at index ${index}.`);
2399
+ }
2400
+ return authentication;
2401
+ });
2402
+ }
2403
+ function resolveAuthenticationOptions(options) {
2404
+ if (!options.core?.credentials?.length) return options;
2405
+ const credentials = resolveCredentials(options.core.credentials, options.core.authentications);
2406
+ if (credentials === options.core.credentials) return options;
2407
+ return { ...options, core: { ...options.core, credentials } };
2408
+ }
2409
+ async function resolveLoaderAuthenticationOptions(loader, url, options) {
2410
+ if (!options.core?.credentials?.length || options.core.credentials.every(isAuthentication)) {
2411
+ return options;
2412
+ }
2413
+ const contributions = await loader?.getAuthentications?.(url, options);
2414
+ if (!contributions?.length) return resolveAuthenticationOptions(options);
2415
+ return resolveAuthenticationOptions({
2416
+ ...options,
2417
+ core: {
2418
+ ...options.core,
2419
+ authentications: [...options.core?.authentications || [], ...contributions]
2420
+ }
2421
+ });
2422
+ }
2423
+ function isAuthentication(credential) {
2424
+ if (!credential || typeof credential !== "object") return false;
2425
+ if (typeof credential.id !== "string" || !Array.isArray(credential.origins)) return false;
2426
+ if (credential.type === "request") return typeof credential.authenticate === "function";
2427
+ return (credential.type === "header" || credential.type === "query-parameter") && typeof credential.name === "string" && (typeof credential.token === "string" || typeof credential.token === "function") && Array.isArray(credential.refreshStatusCodes);
2428
+ }
2429
+
2430
+ // ../loader-utils/src/lib/request-utils/request-credentials.ts
2431
+ var AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
2432
+ var refreshPromises = /* @__PURE__ */ new WeakMap();
2433
+ function createAuthenticatedFetch(options) {
2434
+ const suppliedFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
2435
+ const existingMetadata = suppliedFetch[AUTHENTICATED_FETCH];
2436
+ const credentialResolutions = new Map(existingMetadata?.credentialResolutions);
2437
+ const resolvedCredentials = resolveCredentials(
2438
+ options.credentials.map((credential) => credentialResolutions.get(credential) || credential),
2439
+ options.authentications
2440
+ );
2441
+ options.credentials.forEach((credential, index) => {
2442
+ credentialResolutions.set(credential, resolvedCredentials[index]);
2443
+ });
2444
+ if (!options.fetchOptions && (!resolvedCredentials.length || existingMetadata?.credentials.length === resolvedCredentials.length && resolvedCredentials.every(
2445
+ (credential, index) => credential === existingMetadata.credentials[index]
2446
+ )))
2447
+ return suppliedFetch;
2448
+ const baseFetch = existingMetadata?.fetch || suppliedFetch;
2449
+ const credentials = existingMetadata ? [.../* @__PURE__ */ new Set([...resolvedCredentials, ...existingMetadata.credentials])] : resolvedCredentials;
2450
+ const fetchOptions = mergeFetchOptions(
2451
+ existingMetadata?.fetchOptions || {},
2452
+ options.fetchOptions
2453
+ );
2454
+ const tokenCredentials = credentials.filter(
2455
+ (credential) => credential.type !== "request"
2456
+ );
2457
+ const requestCredentials = credentials.filter(
2458
+ (credential) => credential.type === "request"
2459
+ );
2460
+ for (const credential of requestCredentials) normalizeRequestOrigins(credential.origins);
2461
+ const authenticatedFetch = async (url, requestOptions = {}) => {
2462
+ requestOptions = mergeFetchOptions(fetchOptions, requestOptions);
2463
+ if (requestOptions.signal?.aborted) throw createAbortError3();
2464
+ if (!credentials.length) return baseFetch(url, requestOptions);
2465
+ const resolvedURL = parseHTTPURL(url);
2466
+ const authorization = resolvedURL ? await authorizeRequest(resolvedURL, requestOptions, tokenCredentials) : { url, options: requestOptions, credentials: [] };
2467
+ const signedRequest = await authenticateRequest(authorization, requestCredentials, "request");
2468
+ const response = await baseFetch(signedRequest.url, signedRequest.options);
2469
+ const refreshableCredentials = [];
2470
+ for (const resolvedCredential of authorization.credentials) {
2471
+ const { credential } = resolvedCredential;
2472
+ if (typeof credential.token === "function" && (isReplayableRequest(requestOptions) || credential.canReplayRequest?.(url, requestOptions)) && (isReplayableRequest(signedRequest.options) || credential.canReplayRequest?.(signedRequest.url, signedRequest.options)) && (credential.refreshStatusCodes.includes(response.status) || await credential.shouldRefresh?.(response)))
2473
+ refreshableCredentials.push(resolvedCredential);
2474
+ }
2475
+ const shouldRetrySignature = isReplayableRequest(requestOptions) && isReplayableRequest(signedRequest.options) && signedRequest.credentials.some(
2476
+ (credential) => credential.refreshStatusCodes?.includes(response.status)
2477
+ );
2478
+ if (!refreshableCredentials.length && !shouldRetrySignature) return response;
2479
+ if (requestOptions.signal?.aborted) throw createAbortError3();
2480
+ const refreshedTokens = /* @__PURE__ */ new Map();
2481
+ await Promise.all(
2482
+ refreshableCredentials.map(async ({ credential }) => {
2483
+ const token = await refreshCredential(credential, url, response);
2484
+ if (token) refreshedTokens.set(credential, token);
2485
+ })
2486
+ );
2487
+ if (!refreshedTokens.size && !shouldRetrySignature) return response;
2488
+ await response.body?.cancel().catch(() => {
2489
+ });
2490
+ if (requestOptions.signal?.aborted) throw createAbortError3();
2491
+ const replayAuthorization = resolvedURL ? await authorizeRequest(
2492
+ resolvedURL,
2493
+ requestOptions,
2494
+ tokenCredentials,
2495
+ refreshedTokens,
2496
+ authorization.credentials
2497
+ ) : { url, options: requestOptions };
2498
+ const replayRequest = await authenticateRequest(
2499
+ replayAuthorization,
2500
+ requestCredentials,
2501
+ "retry",
2502
+ response
2503
+ );
2504
+ return baseFetch(replayRequest.url, replayRequest.options);
2505
+ };
2506
+ Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
2507
+ value: {
2508
+ fetch: baseFetch,
2509
+ credentials,
2510
+ credentialResolutions,
2511
+ fetchOptions
2512
+ }
2513
+ });
2514
+ return authenticatedFetch;
2515
+ }
2516
+ function mergeFetchOptions(defaultOptions, requestOptions) {
2517
+ const mergedOptions = { ...defaultOptions, ...requestOptions };
2518
+ if (defaultOptions.headers || requestOptions?.headers) {
2519
+ const headers = new Headers(defaultOptions.headers);
2520
+ new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
2521
+ mergedOptions.headers = headers;
2522
+ }
2523
+ return mergedOptions;
2524
+ }
2525
+ async function authenticateRequest(request, credentials, reason, response) {
2526
+ const appliedCredentials = [];
2527
+ const signal = request.options.signal;
2528
+ for (const credential of credentials) {
2529
+ const origin = getRequestOrigin(request.url);
2530
+ if (!origin || !normalizeRequestOrigins(credential.origins).includes(origin)) continue;
2531
+ if (signal?.aborted) throw createAbortError3();
2532
+ const authenticatedRequest = await credential.authenticate({
2533
+ url: request.url,
2534
+ options: { ...request.options, headers: new Headers(request.options.headers) },
2535
+ reason,
2536
+ response: response ? { status: response.status, headers: new Headers(response.headers) } : void 0
2537
+ });
2538
+ if (!authenticatedRequest || typeof authenticatedRequest.url !== "string" || !authenticatedRequest.options || typeof authenticatedRequest.options !== "object") {
2539
+ throw new Error("Authentication callback returned an invalid request.");
2540
+ }
2541
+ request = {
2542
+ url: authenticatedRequest.url,
2543
+ options: { ...authenticatedRequest.options, ...signal ? { signal } : {} }
2544
+ };
2545
+ appliedCredentials.push(credential);
2546
+ }
2547
+ if (signal?.aborted) throw createAbortError3();
2548
+ return { ...request, credentials: appliedCredentials };
2549
+ }
2550
+ function getRequestOrigin(url) {
2551
+ try {
2552
+ const parsedURL = new URL(url);
2553
+ if (!parsedURL.host || parsedURL.username || parsedURL.password) return null;
2554
+ return parsedURL.origin !== "null" ? parsedURL.origin : `${parsedURL.protocol}//${parsedURL.host}`;
2555
+ } catch {
2556
+ return null;
2557
+ }
2558
+ }
2559
+ function normalizeRequestOrigins(origins) {
2560
+ if (!origins.length)
2561
+ throw new Error("Request authentication requires at least one exact origin.");
2562
+ return origins.map((origin) => {
2563
+ const resolvedOrigin = getRequestOrigin(origin);
2564
+ let url;
2565
+ try {
2566
+ url = new URL(origin);
2567
+ } catch {
2568
+ throw new Error("Invalid request authentication origin.");
2569
+ }
2570
+ if (!resolvedOrigin || url.pathname && url.pathname !== "/" || url.search || url.hash) {
2571
+ throw new Error("Invalid request authentication origin.");
2572
+ }
2573
+ return resolvedOrigin;
2574
+ });
2575
+ }
2576
+ async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
2577
+ const url = new URL(sourceURL);
2578
+ const headers = new Headers(requestOptions.headers);
2579
+ const resolvedCredentials = [];
2580
+ const previousTokens = new Map(
2581
+ previousCredentials.map(({ credential, token }) => [credential, token])
2582
+ );
2583
+ for (const credential of credentials) {
2584
+ if (!credential.origins.includes(url.origin)) continue;
2585
+ const overrideToken = tokenOverrides.get(credential);
2586
+ const previousToken = previousTokens.get(credential);
2587
+ const ownsQueryParameter = credential.type === "query-parameter" && previousToken !== void 0;
2588
+ const ownsHeader = credential.type === "header" && previousToken !== void 0;
2589
+ if (credential.type === "query-parameter" && url.searchParams.has(credential.name) && !ownsQueryParameter || credential.type === "header" && headers.has(credential.name) && !ownsHeader) {
2590
+ continue;
2591
+ }
2592
+ const token = overrideToken ?? previousToken ?? await resolveToken(credential.token, { url: sourceURL.toString(), reason: "request" });
2593
+ if (!token) continue;
2594
+ if (credential.type === "query-parameter") {
2595
+ url.searchParams.set(credential.name, token);
2596
+ } else {
2597
+ headers.set(credential.name, `${credential.prefix || ""}${token}`);
2598
+ }
2599
+ resolvedCredentials.push({ credential, token });
2600
+ }
2601
+ return {
2602
+ url: url.toString(),
2603
+ options: { ...requestOptions, headers },
2604
+ credentials: resolvedCredentials
2605
+ };
2606
+ }
2607
+ async function refreshCredential(credential, url, response) {
2608
+ const existingPromise = refreshPromises.get(credential);
2609
+ if (existingPromise) return existingPromise;
2610
+ const tokenProvider = credential.token;
2611
+ const promise = Promise.resolve(
2612
+ tokenProvider({
2613
+ url,
2614
+ reason: "refresh",
2615
+ response: { status: response.status, headers: response.headers }
2616
+ })
2617
+ ).finally(() => refreshPromises.delete(credential));
2618
+ refreshPromises.set(credential, promise);
2619
+ return promise;
2620
+ }
2621
+ async function resolveToken(token, context) {
2622
+ return typeof token === "function" ? token(context) : token;
2623
+ }
2624
+ function parseHTTPURL(url) {
2625
+ try {
2626
+ const parsedURL = new URL(url);
2627
+ return ["http:", "https:"].includes(parsedURL.protocol) ? parsedURL : null;
2628
+ } catch {
2629
+ return null;
2630
+ }
2631
+ }
2632
+ function isReplayableRequest(options) {
2633
+ const method = (options.method || "GET").toUpperCase();
2634
+ if (!["GET", "HEAD", "OPTIONS", "PUT", "DELETE"].includes(method)) return false;
2635
+ return !(options.body && typeof ReadableStream !== "undefined" && options.body instanceof ReadableStream);
2636
+ }
2637
+ function createAbortError3() {
2638
+ return new DOMException("The operation was aborted.", "AbortError");
2639
+ }
2640
+
1920
2641
  // ../loader-utils/src/lib/path-utils/file-aliases.ts
1921
2642
  var pathPrefix = "";
1922
2643
  var fileAliases = {};
@@ -1939,91 +2660,6 @@ var __exports__ = (() => {
1939
2660
  return filename2;
1940
2661
  }
1941
2662
 
1942
- // ../loader-utils/src/json-loader.ts
1943
- var VERSION4 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
1944
- var JSONLoader = {
1945
- dataType: null,
1946
- batchType: null,
1947
- name: "JSON",
1948
- id: "json",
1949
- module: "json",
1950
- version: VERSION4,
1951
- encoding: "json",
1952
- format: "json",
1953
- extensions: ["json", "geojson"],
1954
- mimeTypes: ["application/json"],
1955
- category: "json",
1956
- text: true,
1957
- parseTextSync,
1958
- parse: async (arrayBuffer) => parseTextSync(new TextDecoder().decode(arrayBuffer)),
1959
- options: {}
1960
- };
1961
- function parseTextSync(text) {
1962
- return JSON.parse(text);
1963
- }
1964
-
1965
- // ../loader-utils/src/lib/node/buffer.browser.ts
1966
- function toArrayBuffer(buffer) {
1967
- return buffer;
1968
- }
1969
-
1970
- // ../loader-utils/src/lib/binary-utils/memory-conversion-utils.ts
1971
- function isBuffer(value) {
1972
- return value && typeof value === "object" && value.isBuffer;
1973
- }
1974
- function toArrayBuffer2(data) {
1975
- if (isBuffer(data)) {
1976
- return toArrayBuffer(data);
1977
- }
1978
- if (data instanceof ArrayBuffer) {
1979
- return data;
1980
- }
1981
- if (isSharedArrayBuffer(data)) {
1982
- return copyToArrayBuffer2(data);
1983
- }
1984
- if (ArrayBuffer.isView(data)) {
1985
- const buffer = data.buffer;
1986
- if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
1987
- return buffer;
1988
- }
1989
- return buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
1990
- }
1991
- if (typeof data === "string") {
1992
- const text = data;
1993
- const uint8Array = new TextEncoder().encode(text);
1994
- return uint8Array.buffer;
1995
- }
1996
- if (data && typeof data === "object" && data._toArrayBuffer) {
1997
- return data._toArrayBuffer();
1998
- }
1999
- throw new Error("toArrayBuffer");
2000
- }
2001
- function ensureArrayBuffer(bufferSource) {
2002
- if (bufferSource instanceof ArrayBuffer) {
2003
- return bufferSource;
2004
- }
2005
- if (isSharedArrayBuffer(bufferSource)) {
2006
- return copyToArrayBuffer2(bufferSource);
2007
- }
2008
- const { buffer, byteOffset, byteLength } = bufferSource;
2009
- if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) {
2010
- return buffer;
2011
- }
2012
- return copyToArrayBuffer2(buffer, byteOffset, byteLength);
2013
- }
2014
- function copyToArrayBuffer2(buffer, byteOffset = 0, byteLength = buffer.byteLength - byteOffset) {
2015
- const view = new Uint8Array(buffer, byteOffset, byteLength);
2016
- const copy = new Uint8Array(view.length);
2017
- copy.set(view);
2018
- return copy.buffer;
2019
- }
2020
- function toArrayBufferView(data) {
2021
- if (ArrayBuffer.isView(data)) {
2022
- return data;
2023
- }
2024
- return new Uint8Array(data);
2025
- }
2026
-
2027
2663
  // ../loader-utils/src/lib/path-utils/path.ts
2028
2664
  var path_exports = {};
2029
2665
  __export(path_exports, {
@@ -2038,7 +2674,7 @@ var __exports__ = (() => {
2038
2674
  if (typeof process !== "undefined" && typeof process.cwd !== "undefined") {
2039
2675
  return process.cwd();
2040
2676
  }
2041
- const pathname = window.location?.pathname;
2677
+ const pathname = globalThis.location?.pathname;
2042
2678
  return pathname?.slice(0, pathname.lastIndexOf("/") + 1) || "";
2043
2679
  }
2044
2680
 
@@ -2167,6 +2803,91 @@ var __exports__ = (() => {
2167
2803
  return res;
2168
2804
  }
2169
2805
 
2806
+ // ../loader-utils/src/json-loader.ts
2807
+ var VERSION4 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
2808
+ var JSONLoader = {
2809
+ dataType: null,
2810
+ batchType: null,
2811
+ name: "JSON",
2812
+ id: "json",
2813
+ module: "json",
2814
+ version: VERSION4,
2815
+ encoding: "json",
2816
+ format: "json",
2817
+ extensions: ["json", "geojson"],
2818
+ mimeTypes: ["application/json"],
2819
+ category: "json",
2820
+ text: true,
2821
+ parseTextSync,
2822
+ parse: async (arrayBuffer) => parseTextSync(new TextDecoder().decode(arrayBuffer)),
2823
+ options: {}
2824
+ };
2825
+ function parseTextSync(text) {
2826
+ return JSON.parse(text);
2827
+ }
2828
+
2829
+ // ../loader-utils/src/lib/node/buffer.browser.ts
2830
+ function toArrayBuffer(buffer) {
2831
+ return buffer;
2832
+ }
2833
+
2834
+ // ../loader-utils/src/lib/binary-utils/memory-conversion-utils.ts
2835
+ function isBuffer(value) {
2836
+ return value && typeof value === "object" && value.isBuffer;
2837
+ }
2838
+ function toArrayBuffer2(data) {
2839
+ if (isBuffer(data)) {
2840
+ return toArrayBuffer(data);
2841
+ }
2842
+ if (data instanceof ArrayBuffer) {
2843
+ return data;
2844
+ }
2845
+ if (isSharedArrayBuffer(data)) {
2846
+ return copyToArrayBuffer2(data);
2847
+ }
2848
+ if (ArrayBuffer.isView(data)) {
2849
+ const buffer = data.buffer;
2850
+ if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
2851
+ return buffer;
2852
+ }
2853
+ return buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
2854
+ }
2855
+ if (typeof data === "string") {
2856
+ const text = data;
2857
+ const uint8Array = new TextEncoder().encode(text);
2858
+ return uint8Array.buffer;
2859
+ }
2860
+ if (data && typeof data === "object" && data._toArrayBuffer) {
2861
+ return data._toArrayBuffer();
2862
+ }
2863
+ throw new Error("toArrayBuffer");
2864
+ }
2865
+ function ensureArrayBuffer(bufferSource) {
2866
+ if (bufferSource instanceof ArrayBuffer) {
2867
+ return bufferSource;
2868
+ }
2869
+ if (isSharedArrayBuffer(bufferSource)) {
2870
+ return copyToArrayBuffer2(bufferSource);
2871
+ }
2872
+ const { buffer, byteOffset, byteLength } = bufferSource;
2873
+ if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) {
2874
+ return buffer;
2875
+ }
2876
+ return copyToArrayBuffer2(buffer, byteOffset, byteLength);
2877
+ }
2878
+ function copyToArrayBuffer2(buffer, byteOffset = 0, byteLength = buffer.byteLength - byteOffset) {
2879
+ const view = new Uint8Array(buffer, byteOffset, byteLength);
2880
+ const copy = new Uint8Array(view.length);
2881
+ copy.set(view);
2882
+ return copy.buffer;
2883
+ }
2884
+ function toArrayBufferView(data) {
2885
+ if (ArrayBuffer.isView(data)) {
2886
+ return data;
2887
+ }
2888
+ return new Uint8Array(data);
2889
+ }
2890
+
2170
2891
  // ../loader-utils/src/lib/files/blob-file.ts
2171
2892
  var BlobFile = class {
2172
2893
  handle;
@@ -2188,8 +2909,14 @@ var __exports__ = (() => {
2188
2909
  isDirectory: false
2189
2910
  };
2190
2911
  }
2191
- async read(start, length) {
2912
+ async read(start, length, signal) {
2913
+ if (signal?.aborted) {
2914
+ throw new Error("Request aborted");
2915
+ }
2192
2916
  const arrayBuffer = await this.handle.slice(Number(start), Number(start) + Number(length)).arrayBuffer();
2917
+ if (signal?.aborted) {
2918
+ throw new Error("Request aborted");
2919
+ }
2193
2920
  return arrayBuffer;
2194
2921
  }
2195
2922
  };
@@ -2410,19 +3137,11 @@ var __exports__ = (() => {
2410
3137
  }
2411
3138
  if (resource instanceof ArrayBuffer) {
2412
3139
  const slice = resource.slice(0, INITIAL_DATA_LENGTH);
2413
- const base64 = arrayBufferToBase64(slice);
3140
+ const base64 = encodeArrayBufferToBase64(slice);
2414
3141
  return `data:base64,${base64}`;
2415
3142
  }
2416
3143
  return null;
2417
3144
  }
2418
- function arrayBufferToBase64(buffer) {
2419
- let binary = "";
2420
- const bytes = new Uint8Array(buffer);
2421
- for (let i = 0; i < bytes.byteLength; i++) {
2422
- binary += String.fromCharCode(bytes[i]);
2423
- }
2424
- return btoa(binary);
2425
- }
2426
3145
 
2427
3146
  // src/lib/fetch/fetch-file.ts
2428
3147
  function isNodePath(url) {
@@ -2532,6 +3251,7 @@ var __exports__ = (() => {
2532
3251
 
2533
3252
  // src/lib/loader-utils/option-defaults.ts
2534
3253
  var DEFAULT_LOADER_OPTIONS = {
3254
+ searchParams: void 0,
2535
3255
  core: {
2536
3256
  baseUrl: void 0,
2537
3257
  // baseUrl
@@ -2544,9 +3264,11 @@ var __exports__ = (() => {
2544
3264
  log: new ConsoleLog(),
2545
3265
  // A probe.gl compatible (`log.log()()` syntax) that just logs to console
2546
3266
  useLocalLibraries: false,
3267
+ subloaders: void 0,
2547
3268
  CDN: "https://unpkg.com/@loaders.gl",
2548
3269
  worker: true,
2549
3270
  // By default, use worker if provided by loader.
3271
+ workerThreshold: 0.1,
2550
3272
  maxConcurrency: 3,
2551
3273
  // How many worker instances should be created for each loader.
2552
3274
  maxMobileConcurrency: 1,
@@ -2622,6 +3344,7 @@ var __exports__ = (() => {
2622
3344
  "useLocalLibraries",
2623
3345
  "CDN",
2624
3346
  "worker",
3347
+ "workerThreshold",
2625
3348
  "maxConcurrency",
2626
3349
  "maxMobileConcurrency",
2627
3350
  "reuseWorkers",
@@ -2636,6 +3359,27 @@ var __exports__ = (() => {
2636
3359
  "metadata",
2637
3360
  "transforms"
2638
3361
  ];
3362
+ function applySearchParamsToUrl(url, options) {
3363
+ const searchParams = options?.searchParams;
3364
+ if (!searchParams || Object.keys(searchParams).length === 0 || /^(?:data|blob):/i.test(url)) {
3365
+ return url;
3366
+ }
3367
+ const hashIndex = url.indexOf("#");
3368
+ const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
3369
+ const urlWithoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
3370
+ const queryIndex = urlWithoutHash.indexOf("?");
3371
+ const path = queryIndex >= 0 ? urlWithoutHash.slice(0, queryIndex) : urlWithoutHash;
3372
+ const query = queryIndex >= 0 ? urlWithoutHash.slice(queryIndex + 1) : "";
3373
+ const existingSearchParams = new URLSearchParams(query);
3374
+ const appendedSearchParams = new URLSearchParams();
3375
+ for (const [key, value] of Object.entries(searchParams)) {
3376
+ if (!existingSearchParams.has(key)) {
3377
+ appendedSearchParams.set(key, String(value));
3378
+ }
3379
+ }
3380
+ const serializedAppendedSearchParams = appendedSearchParams.toString();
3381
+ return `${path}${queryIndex >= 0 ? `?${query}` : ""}${serializedAppendedSearchParams ? `${queryIndex >= 0 ? "&" : "?"}${serializedAppendedSearchParams}` : ""}${hash}`;
3382
+ }
2639
3383
  function getGlobalLoaderState() {
2640
3384
  globalThis.loaders = globalThis.loaders || {};
2641
3385
  const { loaders } = globalThis;
@@ -2662,7 +3406,10 @@ var __exports__ = (() => {
2662
3406
  loaders = loaders || [];
2663
3407
  loaders = Array.isArray(loaders) ? loaders : [loaders];
2664
3408
  validateOptions(options, loaders);
2665
- return normalizeLoaderOptions(normalizeOptionsInternal(loader, options, url));
3409
+ validateWorkerThreshold(options);
3410
+ const normalizedOptions = normalizeLoaderOptions(normalizeOptionsInternal(loader, options, url));
3411
+ validateWorkerThreshold(normalizedOptions);
3412
+ return normalizedOptions;
2666
3413
  }
2667
3414
  function normalizeLoaderOptions(options) {
2668
3415
  const normalized = cloneLoaderOptions(options);
@@ -2686,6 +3433,12 @@ var __exports__ = (() => {
2686
3433
  validateOptionsObject(idOptions, loader.id, loaderOptions, deprecatedOptions, loaders);
2687
3434
  }
2688
3435
  }
3436
+ function validateWorkerThreshold(options) {
3437
+ const threshold = options.core?.workerThreshold;
3438
+ if (threshold !== void 0 && (!Number.isFinite(threshold) || threshold < 0 || threshold > 1)) {
3439
+ throw new Error("core.workerThreshold must be a finite number between 0 and 1");
3440
+ }
3441
+ }
2689
3442
  function validateOptionsObject(options, id, defaultOptions, deprecatedOptions, loaders) {
2690
3443
  const loaderName = id || "Top level";
2691
3444
  const prefix = id ? `${id}.` : "";
@@ -3201,20 +3954,57 @@ var __exports__ = (() => {
3201
3954
  async function* makeBrowserStreamIterator(stream, options) {
3202
3955
  const reader = stream.getReader();
3203
3956
  let nextBatchPromise;
3957
+ let streamFinished = false;
3958
+ let streamReadFailed = false;
3959
+ let iteratorFailed = false;
3204
3960
  try {
3205
3961
  while (true) {
3206
3962
  const currentBatchPromise = nextBatchPromise || reader.read();
3207
- if (options?._streamReadAhead) {
3208
- nextBatchPromise = reader.read();
3963
+ nextBatchPromise = void 0;
3964
+ let batch;
3965
+ try {
3966
+ batch = await currentBatchPromise;
3967
+ } catch (error) {
3968
+ streamReadFailed = true;
3969
+ throw error;
3209
3970
  }
3210
- const { done, value } = await currentBatchPromise;
3971
+ const { done, value } = batch;
3211
3972
  if (done) {
3973
+ streamFinished = true;
3212
3974
  return;
3213
3975
  }
3976
+ if (options?._streamReadAhead) {
3977
+ nextBatchPromise = reader.read();
3978
+ void nextBatchPromise.catch(() => {
3979
+ });
3980
+ }
3214
3981
  yield toArrayBuffer2(value);
3215
3982
  }
3216
- } catch (_error) {
3217
- reader.releaseLock();
3983
+ } catch (error) {
3984
+ iteratorFailed = true;
3985
+ throw error;
3986
+ } finally {
3987
+ let cleanupFailed = false;
3988
+ let cleanupError;
3989
+ if (!streamFinished && !streamReadFailed) {
3990
+ try {
3991
+ await reader.cancel();
3992
+ } catch (error) {
3993
+ cleanupFailed = true;
3994
+ cleanupError = error;
3995
+ }
3996
+ }
3997
+ try {
3998
+ reader.releaseLock();
3999
+ } catch (error) {
4000
+ if (!cleanupFailed) {
4001
+ cleanupFailed = true;
4002
+ cleanupError = error;
4003
+ }
4004
+ }
4005
+ if (!iteratorFailed && cleanupFailed) {
4006
+ throw cleanupError;
4007
+ }
3218
4008
  }
3219
4009
  }
3220
4010
  async function* makeNodeStreamIterator(stream, options) {
@@ -3335,14 +4125,14 @@ var __exports__ = (() => {
3335
4125
  }
3336
4126
  function getIterableFromData(data) {
3337
4127
  if (ArrayBuffer.isView(data)) {
3338
- return function* oneChunk() {
4128
+ return (function* oneChunk() {
3339
4129
  yield toArrayBuffer2(data);
3340
- }();
4130
+ })();
3341
4131
  }
3342
4132
  if (isArrayBufferLike(data)) {
3343
- return function* oneChunk() {
4133
+ return (function* oneChunk() {
3344
4134
  yield toArrayBuffer2(data);
3345
- }();
4135
+ })();
3346
4136
  }
3347
4137
  if (isIterator(data)) {
3348
4138
  return data;
@@ -3358,22 +4148,37 @@ var __exports__ = (() => {
3358
4148
  const globalOptions = getGlobalLoaderOptions();
3359
4149
  const loaderOptions = options || globalOptions;
3360
4150
  const fetchOption = loaderOptions.fetch ?? loaderOptions.core?.fetch;
4151
+ let fetchFunction;
3361
4152
  if (typeof fetchOption === "function") {
3362
- return fetchOption;
3363
- }
3364
- if (isObject(fetchOption)) {
3365
- return (url) => fetchFile(url, fetchOption);
3366
- }
3367
- if (context?.fetch) {
3368
- return context?.fetch;
4153
+ fetchFunction = fetchOption;
4154
+ } else if (isObject(fetchOption)) {
4155
+ fetchFunction = context?.fetch || fetchFile;
4156
+ } else if (context?.fetch) {
4157
+ fetchFunction = context.fetch;
4158
+ } else {
4159
+ fetchFunction = fetchFile;
3369
4160
  }
3370
- return fetchFile;
4161
+ return createAuthenticatedFetch({
4162
+ fetch: fetchFunction,
4163
+ credentials: loaderOptions.core?.credentials || [],
4164
+ authentications: loaderOptions.core?.authentications,
4165
+ fetchOptions: isObject(fetchOption) ? fetchOption : void 0
4166
+ });
3371
4167
  }
3372
4168
 
3373
4169
  // src/lib/api/load-loader.ts
3374
4170
  var loaderImplementationPromises = /* @__PURE__ */ new Map();
3375
4171
  var loaderImplementations = /* @__PURE__ */ new Map();
3376
4172
  async function getLoaderImplementation(loader, options, url) {
4173
+ if (isSourceLoader(loader)) {
4174
+ const source = loader.preload ? await loader.preload(url || "", options) : loader;
4175
+ if (!isSourceLoader(source)) {
4176
+ throw new Error(
4177
+ `${loader.id} source loader preload() did not return a runtime source loader`
4178
+ );
4179
+ }
4180
+ return source;
4181
+ }
3377
4182
  if (isLoaderWithParser(loader)) {
3378
4183
  return loader;
3379
4184
  }
@@ -3409,6 +4214,11 @@ var __exports__ = (() => {
3409
4214
  return await loaderImplementationPromise;
3410
4215
  }
3411
4216
  function getLoaderImplementationSync(loader) {
4217
+ if (loader.subloaders && !preparedLoaders.has(loader)) {
4218
+ const prepared = preparedDefaults.get(loader);
4219
+ if (prepared) return prepared;
4220
+ if (!isLoaderWithParser(loader)) return null;
4221
+ }
3412
4222
  if (isLoaderWithParser(loader)) {
3413
4223
  return loader;
3414
4224
  }
@@ -3451,12 +4261,7 @@ var __exports__ = (() => {
3451
4261
  function getLoaderImplementationCacheKey(loader, options) {
3452
4262
  const loaderOptions = options?.[loader.id];
3453
4263
  const defaultLoaderOptions = loader.options?.[loader.id];
3454
- return String(
3455
- loaderOptions?.backend || getDeprecatedImplementationBackend(loaderOptions?.implementation) || defaultLoaderOptions?.backend || ""
3456
- );
3457
- }
3458
- function getDeprecatedImplementationBackend(implementation) {
3459
- return implementation === "js" ? "typescript" : implementation;
4264
+ return String(loaderOptions?.backend || defaultLoaderOptions?.backend || "");
3460
4265
  }
3461
4266
  async function importLoaderImplementation(implementationSpecifier, loaderId) {
3462
4267
  const moduleExports = await import(
@@ -3473,6 +4278,104 @@ var __exports__ = (() => {
3473
4278
  `Could not find parser implementation for ${loaderId} in ${implementationSpecifier}`
3474
4279
  );
3475
4280
  }
4281
+ var preparedLoaders = /* @__PURE__ */ new WeakSet();
4282
+ var preparedDefaults = /* @__PURE__ */ new WeakMap();
4283
+ var subloaderPreparations = /* @__PURE__ */ new WeakMap();
4284
+ async function preloadLoaderDependencies(loader, options, url) {
4285
+ if (preparedLoaders.has(loader)) return await getLoaderImplementation(loader, options, url);
4286
+ validateSubloaderGraph(loader, options);
4287
+ return await prepareLoaderDependencies(loader, options, url);
4288
+ }
4289
+ async function prepareLoaderDependencies(loader, options, url) {
4290
+ if (!options) {
4291
+ const cached = subloaderPreparations.get(loader);
4292
+ if (cached) return await cached;
4293
+ }
4294
+ const preparation = bindSubloaders(loader, options, url);
4295
+ if (!options) {
4296
+ subloaderPreparations.set(loader, preparation);
4297
+ void preparation.catch(() => subloaderPreparations.delete(loader));
4298
+ }
4299
+ const prepared = await preparation;
4300
+ if (!options) preparedDefaults.set(loader, prepared);
4301
+ return prepared;
4302
+ }
4303
+ function getSubloaders(loader, options) {
4304
+ const overrides = options?.core?.subloaders || {};
4305
+ return Object.fromEntries(
4306
+ Object.entries(loader.subloaders || {}).map(([name, dependency]) => [
4307
+ name,
4308
+ Object.hasOwn(overrides, name) ? overrides[name] : dependency
4309
+ ])
4310
+ );
4311
+ }
4312
+ function validateSubloaderGraph(loader, options) {
4313
+ visitLoader(loader, []);
4314
+ function visitLoader(currentLoader, ancestors) {
4315
+ if (ancestors.includes(currentLoader)) {
4316
+ throw new Error(
4317
+ `Subloader cycle: ${[...ancestors, currentLoader].map((value) => value.id).join(" -> ")}`
4318
+ );
4319
+ }
4320
+ for (const dependency of Object.values(getSubloaders(currentLoader, options))) {
4321
+ visitLoader(dependency, [...ancestors, currentLoader]);
4322
+ }
4323
+ }
4324
+ }
4325
+ async function bindSubloaders(loader, options, url) {
4326
+ const [implementation, entries] = await Promise.all([
4327
+ getLoaderImplementation(loader, options, url),
4328
+ Promise.all(
4329
+ Object.entries(getSubloaders(loader, options)).map(
4330
+ async ([name, dependency]) => [name, await prepareLoaderDependencies(dependency, options, url)]
4331
+ )
4332
+ )
4333
+ ]);
4334
+ const subloaders = Object.fromEntries(entries);
4335
+ const defaultOptions = mergeOptions(
4336
+ implementation.options,
4337
+ options || {}
4338
+ );
4339
+ defaultOptions.core = { ...defaultOptions.core, worker: false };
4340
+ const prepared = { ...implementation, options: defaultOptions, subloaders };
4341
+ delete prepared.preload;
4342
+ prepared.worker = false;
4343
+ for (const method of [
4344
+ "parseBlob",
4345
+ "createDataSource",
4346
+ "parse",
4347
+ "parseSync",
4348
+ "parseText",
4349
+ "parseTextSync",
4350
+ "parseInBatches",
4351
+ "parseFile",
4352
+ "parseFileInBatches",
4353
+ "parseUrl"
4354
+ ]) {
4355
+ const parser = implementation[method];
4356
+ if (typeof parser === "function") {
4357
+ prepared[method] = (data, parseOptions, context) => {
4358
+ const forwardedOptions = mergeOptions(options, parseOptions || {});
4359
+ return parser.call(
4360
+ implementation,
4361
+ data,
4362
+ {
4363
+ ...forwardedOptions,
4364
+ core: {
4365
+ ...forwardedOptions.core,
4366
+ subloaders: options?.core?.subloaders || parseOptions?.core?.subloaders,
4367
+ worker: false
4368
+ },
4369
+ [loader.id]: { ...forwardedOptions[loader.id], subloaders }
4370
+ },
4371
+ context
4372
+ );
4373
+ };
4374
+ }
4375
+ }
4376
+ preparedLoaders.add(prepared);
4377
+ return prepared;
4378
+ }
3476
4379
 
3477
4380
  // src/lib/api/parse-file.ts
3478
4381
  async function parseFile(file, loaders, options, context) {
@@ -3494,7 +4397,13 @@ var __exports__ = (() => {
3494
4397
  `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parseFile().`
3495
4398
  );
3496
4399
  }
3497
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4400
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
4401
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4402
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4403
+ authenticationLoader,
4404
+ url,
4405
+ normalizedOptions
4406
+ );
3498
4407
  context = getLoaderContext(
3499
4408
  // @ts-expect-error candidateLoaders may be a single forced loader
3500
4409
  { url, _parse: parse, loaders: candidateLoaders },
@@ -3587,7 +4496,7 @@ var __exports__ = (() => {
3587
4496
  case "geojson-table":
3588
4497
  return Array.isArray(table.features);
3589
4498
  case "columnar-table":
3590
- return table.data && typeof table.data === "object";
4499
+ return Boolean(table.data && typeof table.data === "object");
3591
4500
  case "arrow-table":
3592
4501
  return Boolean(table?.data?.numRows !== void 0);
3593
4502
  default:
@@ -3634,7 +4543,13 @@ var __exports__ = (() => {
3634
4543
  if (!loader) {
3635
4544
  return [];
3636
4545
  }
3637
- const strictOptions = normalizeOptions(options, loader, loaderArray, url);
4546
+ const normalizedOptions = normalizeOptions(options, loader, loaderArray, url);
4547
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4548
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4549
+ authenticationLoader,
4550
+ url || "",
4551
+ normalizedOptions
4552
+ );
3638
4553
  context = getLoaderContext(
3639
4554
  { url, _parseInBatches: parseInBatches, _parse: parse, loaders: loaderArray },
3640
4555
  strictOptions,
@@ -3672,6 +4587,9 @@ var __exports__ = (() => {
3672
4587
  options?.core?.transforms || []
3673
4588
  );
3674
4589
  if (loader.parseInBatches) {
4590
+ if (loader.id === "csv" && isBrowser && canParseWithWorker(loader, options)) {
4591
+ return parseWithWorkerInBatches(loader, transformedIterator, options, context, parse);
4592
+ }
3675
4593
  return loader.parseInBatches(transformedIterator, options, context);
3676
4594
  }
3677
4595
  return parseChunkInBatches(transformedIterator, loader, options, context);
@@ -3716,19 +4634,23 @@ var __exports__ = (() => {
3716
4634
  } else {
3717
4635
  loadersArray = loaders;
3718
4636
  }
3719
- const fetch2 = getFetchFunction(options || {});
3720
4637
  if (!Array.isArray(files)) {
3721
- return loadOneFileInBatches(files, loadersArray, options || {}, fetch2);
4638
+ return loadOneFileInBatches(files, loadersArray, options || {});
3722
4639
  }
3723
- const promises = files.map(
3724
- (file) => loadOneFileInBatches(file, loadersArray, options || {}, fetch2)
3725
- );
4640
+ const promises = files.map((file) => loadOneFileInBatches(file, loadersArray, options || {}));
3726
4641
  return promises;
3727
4642
  }
3728
- async function loadOneFileInBatches(file, loaders, options, fetch2) {
4643
+ async function loadOneFileInBatches(file, loaders, options) {
3729
4644
  if (typeof file === "string") {
3730
4645
  const url = file;
3731
- const response = await fetch2(url);
4646
+ const loader = await selectLoader(url, loaders, {
4647
+ ...options,
4648
+ core: { ...options.core, nothrow: true }
4649
+ });
4650
+ const authenticationLoader = loader && !loader.getAuthentications && options.core?.credentials?.length ? await getLoaderImplementation(loader, options, url) : loader;
4651
+ options = await resolveLoaderAuthenticationOptions(authenticationLoader, url, options);
4652
+ const fetch2 = getFetchFunction(options);
4653
+ const response = await fetch2(applySearchParamsToUrl(url, options));
3732
4654
  return Array.isArray(loaders) ? await parseInBatches(response, loaders, options) : await parseInBatches(response, loaders, options);
3733
4655
  }
3734
4656
  return Array.isArray(loaders) ? await parseInBatches(file, loaders, options) : await parseInBatches(file, loaders, options);
@@ -3746,7 +4668,14 @@ var __exports__ = (() => {
3746
4668
  resolvedLoaders = loaders;
3747
4669
  resolvedOptions = options;
3748
4670
  }
4671
+ resolvedOptions ||= getGlobalLoaderOptions();
3749
4672
  if (!Array.isArray(resolvedLoaders) && isSourceLoader(resolvedLoaders)) {
4673
+ const sourceLoader = await resolveSourceLoader(resolvedLoaders, url, resolvedOptions);
4674
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4675
+ resolvedLoaders.getAuthentications ? resolvedLoaders : sourceLoader,
4676
+ typeof url === "string" ? url : "",
4677
+ resolvedOptions || {}
4678
+ );
3750
4679
  const runtimeCoreApi = {
3751
4680
  fetchFile,
3752
4681
  parse,
@@ -3756,13 +4685,19 @@ var __exports__ = (() => {
3756
4685
  load,
3757
4686
  loadInBatches
3758
4687
  };
3759
- return resolvedLoaders.createDataSource(
4688
+ return sourceLoader.createDataSource(
3760
4689
  url,
3761
4690
  resolvedOptions || {},
3762
4691
  runtimeCoreApi
3763
4692
  );
3764
4693
  }
3765
4694
  if (Array.isArray(resolvedLoaders) && resolvedLoaders.length === 1 && isSourceLoader(resolvedLoaders[0])) {
4695
+ const sourceLoader = await resolveSourceLoader(resolvedLoaders[0], url, resolvedOptions);
4696
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4697
+ resolvedLoaders[0].getAuthentications ? resolvedLoaders[0] : sourceLoader,
4698
+ typeof url === "string" ? url : "",
4699
+ resolvedOptions || {}
4700
+ );
3766
4701
  const runtimeCoreApi = {
3767
4702
  fetchFile,
3768
4703
  parse,
@@ -3772,7 +4707,7 @@ var __exports__ = (() => {
3772
4707
  load,
3773
4708
  loadInBatches
3774
4709
  };
3775
- return resolvedLoaders[0].createDataSource(
4710
+ return sourceLoader.createDataSource(
3776
4711
  url,
3777
4712
  resolvedOptions || {},
3778
4713
  runtimeCoreApi
@@ -3784,7 +4719,13 @@ var __exports__ = (() => {
3784
4719
  core: { ...resolvedOptions?.core, nothrow: true }
3785
4720
  });
3786
4721
  if (selectedLoader && isSourceLoader(selectedLoader)) {
3787
- return selectedLoader.createDataSource(
4722
+ const sourceLoader = await resolveSourceLoader(selectedLoader, url, resolvedOptions);
4723
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4724
+ selectedLoader.getAuthentications ? selectedLoader : sourceLoader,
4725
+ typeof url === "string" ? url : "",
4726
+ resolvedOptions || {}
4727
+ );
4728
+ return sourceLoader.createDataSource(
3788
4729
  url,
3789
4730
  resolvedOptions || {},
3790
4731
  {
@@ -3798,11 +4739,29 @@ var __exports__ = (() => {
3798
4739
  }
3799
4740
  );
3800
4741
  }
4742
+ if (selectedLoader && typeof url === "string") {
4743
+ const loaderImplementation = await getLoaderImplementation(
4744
+ selectedLoader,
4745
+ resolvedOptions,
4746
+ url
4747
+ );
4748
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4749
+ selectedLoader.getAuthentications ? selectedLoader : loaderImplementation,
4750
+ url,
4751
+ resolvedOptions || {}
4752
+ );
4753
+ const parseUrl = loaderImplementation.parseUrl;
4754
+ if (parseUrl) {
4755
+ const requestUrl = applySearchParamsToUrl(url, resolvedOptions);
4756
+ return await parseUrl(requestUrl, resolvedOptions, context);
4757
+ }
4758
+ }
3801
4759
  }
4760
+ if (resolvedOptions) resolvedOptions = resolveAuthenticationOptions(resolvedOptions);
3802
4761
  const fetch2 = getFetchFunction(resolvedOptions);
3803
4762
  let data = url;
3804
4763
  if (typeof url === "string") {
3805
- data = await fetch2(url);
4764
+ data = await fetch2(applySearchParamsToUrl(url, resolvedOptions));
3806
4765
  }
3807
4766
  if (isBlob(url)) {
3808
4767
  data = await fetch2(url);
@@ -3821,6 +4780,16 @@ var __exports__ = (() => {
3821
4780
  }
3822
4781
  return Array.isArray(resolvedLoaders) ? await parse(data, resolvedLoaders, resolvedOptions, context) : await parse(data, resolvedLoaders, resolvedOptions, context);
3823
4782
  }
4783
+ async function resolveSourceLoader(loader, url, options) {
4784
+ if (!loader.preload) {
4785
+ return loader;
4786
+ }
4787
+ const sourceLoader = await loader.preload(typeof url === "string" ? url : "", options);
4788
+ if (!isSourceLoader(sourceLoader)) {
4789
+ throw new Error(`${loader.id} source loader preload() did not return a runtime source loader`);
4790
+ }
4791
+ return sourceLoader;
4792
+ }
3824
4793
 
3825
4794
  // src/lib/api/core-api.ts
3826
4795
  var coreApi = Object.freeze({
@@ -3836,7 +4805,12 @@ var __exports__ = (() => {
3836
4805
  // src/lib/loader-utils/loader-context.ts
3837
4806
  function getLoaderContext(context, options, parentContext) {
3838
4807
  if (parentContext) {
3839
- return parentContext;
4808
+ return {
4809
+ ...parentContext,
4810
+ coreApi: parentContext.coreApi || context.coreApi || coreApi,
4811
+ _parse: parentContext._parse || context._parse,
4812
+ fetch: getFetchFunction(options, parentContext)
4813
+ };
3840
4814
  }
3841
4815
  const newContext = {
3842
4816
  ...context,
@@ -3891,7 +4865,13 @@ var __exports__ = (() => {
3891
4865
  `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parse().`
3892
4866
  );
3893
4867
  }
3894
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4868
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
4869
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4870
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4871
+ authenticationLoader,
4872
+ url || "",
4873
+ normalizedOptions
4874
+ );
3895
4875
  context = getLoaderContext(
3896
4876
  // @ts-expect-error
3897
4877
  { url, _parse: parse, loaders: candidateLoaders },
@@ -3909,10 +4889,13 @@ var __exports__ = (() => {
3909
4889
  context.response = { headers, ok, redirected, status, statusText, type, url };
3910
4890
  }
3911
4891
  const loaderWithParser = await getLoaderImplementation(loader, options, context.url);
3912
- if (canParseWithWorker(loaderWithParser, options)) {
4892
+ if (shouldParseWithWorker(loaderWithParser, data, options, context, loader)) {
3913
4893
  data = await getArrayBufferFromData(data, options);
3914
4894
  return await parseWithWorker(loaderWithParser, data, options, context, parse);
3915
4895
  }
4896
+ if (isBlob(data) && loaderWithParser.parseBlob) {
4897
+ return await loaderWithParser.parseBlob(data, options, context);
4898
+ }
3916
4899
  data = await getArrayBufferOrStringFromData(data, loader, options);
3917
4900
  return await parseWithLoaderImplementation(loaderWithParser, data, options, context);
3918
4901
  }
@@ -3936,7 +4919,7 @@ var __exports__ = (() => {
3936
4919
 
3937
4920
  // src/lib/api/preload.ts
3938
4921
  async function preload(loader, options, url) {
3939
- return await getLoaderImplementation(loader, options, url);
4922
+ return loader.subloaders ? await preloadLoaderDependencies(loader, options, url) : await getLoaderImplementation(loader, options, url);
3940
4923
  }
3941
4924
  function preloadSync(loader) {
3942
4925
  return getLoaderImplementationSync(loader);
@@ -4064,7 +5047,7 @@ var __exports__ = (() => {
4064
5047
  }
4065
5048
 
4066
5049
  // src/lib/api/create-data-source.ts
4067
- function createDataSource(data, sources, options) {
5050
+ function createDataSource(data, sources, options = {}) {
4068
5051
  const resolvedOptions = options || {};
4069
5052
  const type = resolvedOptions?.core?.type || resolvedOptions.type || "auto";
4070
5053
  const source = sources.length === 1 ? sources[0] : type === "auto" ? selectLoaderSync(data, sources, {
@@ -4076,7 +5059,29 @@ var __exports__ = (() => {
4076
5059
  if (!source) {
4077
5060
  throw new Error("Not a valid source type");
4078
5061
  }
4079
- return source.createDataSource(data, resolvedOptions, coreApi);
5062
+ const contributions = resolvedOptions.core?.credentials?.length ? source.getAuthentications?.(typeof data === "string" ? data : "", resolvedOptions) : void 0;
5063
+ if (contributions && "then" in contributions) {
5064
+ void contributions.catch(() => {
5065
+ });
5066
+ throw new Error("Use load() with an asynchronous getAuthentications() hook.");
5067
+ }
5068
+ const authenticatedOptions = resolveAuthenticationOptions(
5069
+ contributions?.length ? {
5070
+ ...resolvedOptions,
5071
+ core: {
5072
+ ...resolvedOptions.core,
5073
+ authentications: [
5074
+ ...resolvedOptions.core?.authentications || [],
5075
+ ...contributions || []
5076
+ ]
5077
+ }
5078
+ } : resolvedOptions
5079
+ );
5080
+ return source.createDataSource(
5081
+ data,
5082
+ authenticatedOptions,
5083
+ coreApi
5084
+ );
4080
5085
  }
4081
5086
  function getSourceOfType(type, sources) {
4082
5087
  for (const service of sources) {
@@ -4267,18 +5272,29 @@ var __exports__ = (() => {
4267
5272
  if (path.includes("://")) {
4268
5273
  return this._fetch(path, options);
4269
5274
  }
4270
- const file = this.files[path];
5275
+ const file = this._getFile(path, true);
4271
5276
  if (!file) {
4272
5277
  return new Response(path, { status: 400, statusText: "NOT FOUND" });
4273
5278
  }
4274
5279
  const headers = new Headers(options?.headers);
4275
5280
  const range = headers.get("Range");
4276
- const bytes = range && /bytes=($1)-($2)/.exec(range);
5281
+ const bytes = range && /bytes=(\d+)-(\d+)/.exec(range);
4277
5282
  if (bytes) {
4278
5283
  const start = parseInt(bytes[1]);
4279
- const end = parseInt(bytes[2]);
4280
- const data = await file.slice(start, end).arrayBuffer();
4281
- const response2 = new Response(data);
5284
+ const end = Math.min(parseInt(bytes[2]), file.size - 1);
5285
+ if (start > end) {
5286
+ const response3 = new Response(null, {
5287
+ status: 416,
5288
+ headers: { "Content-Range": `bytes */${file.size}` }
5289
+ });
5290
+ Object.defineProperty(response3, "url", { value: path });
5291
+ return response3;
5292
+ }
5293
+ const data = await file.slice(start, end + 1).arrayBuffer();
5294
+ const response2 = new Response(data, {
5295
+ status: 206,
5296
+ headers: { "Content-Range": `bytes ${start}-${end}/${file.size}` }
5297
+ });
4282
5298
  Object.defineProperty(response2, "url", { value: path });
4283
5299
  return response2;
4284
5300
  }
@@ -4302,7 +5318,7 @@ var __exports__ = (() => {
4302
5318
  * Return information (size) about files in this file system
4303
5319
  */
4304
5320
  async stat(path, options) {
4305
- const file = this.files[path];
5321
+ const file = this._getFile(path, false);
4306
5322
  if (!file) {
4307
5323
  throw new Error(path);
4308
5324
  }
@@ -4312,19 +5328,22 @@ var __exports__ = (() => {
4312
5328
  * Just removes the file from the list
4313
5329
  */
4314
5330
  async unlink(path) {
4315
- delete this.files[path];
4316
- delete this.lowerCaseFiles[path];
4317
- this.usedFiles[path] = true;
5331
+ const file = this._getFile(path, false);
5332
+ if (file) {
5333
+ delete this.files[file.name];
5334
+ delete this.lowerCaseFiles[file.name.toLowerCase()];
5335
+ this.usedFiles[file.name] = true;
5336
+ }
4318
5337
  }
4319
5338
  // implements IRandomAccessFileSystem
4320
5339
  // RANDOM ACCESS
4321
5340
  async openReadableFile(pathname, flags) {
4322
- return new BlobFile(this.files[pathname]);
5341
+ return new BlobFile(this._getFile(pathname, true));
4323
5342
  }
4324
5343
  // PRIVATE
4325
5344
  // Supports case independent paths, and file usage tracking
4326
5345
  _getFile(path, used) {
4327
- const file = this.files[path] || this.lowerCaseFiles[path];
5346
+ const file = this.files[path] || this.lowerCaseFiles[path.toLowerCase()];
4328
5347
  if (file && used) {
4329
5348
  this.usedFiles[path] = true;
4330
5349
  }