@loaders.gl/core 4.5.3 → 5.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +14 -3
  2. package/dist/dist.dev.js +1789 -352
  3. package/dist/dist.min.js +4 -3
  4. package/dist/index.cjs +3087 -311
  5. package/dist/index.cjs.map +3 -4
  6. package/dist/index.d.ts +8 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +7 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/iterators/make-iterator/make-stream-iterator.js +48 -9
  11. package/dist/iterators/make-iterator/make-stream-iterator.js.map +1 -1
  12. package/dist/lib/api/core-api.d.ts +6 -0
  13. package/dist/lib/api/core-api.d.ts.map +1 -0
  14. package/dist/lib/api/core-api.js +23 -0
  15. package/dist/lib/api/core-api.js.map +1 -0
  16. package/dist/lib/api/create-data-source.d.ts +2 -2
  17. package/dist/lib/api/create-data-source.d.ts.map +1 -1
  18. package/dist/lib/api/create-data-source.js +36 -14
  19. package/dist/lib/api/create-data-source.js.map +1 -1
  20. package/dist/lib/api/load-in-batches.d.ts +4 -4
  21. package/dist/lib/api/load-in-batches.d.ts.map +1 -1
  22. package/dist/lib/api/load-in-batches.js +17 -6
  23. package/dist/lib/api/load-in-batches.js.map +1 -1
  24. package/dist/lib/api/load-loader.d.ts +10 -0
  25. package/dist/lib/api/load-loader.d.ts.map +1 -0
  26. package/dist/lib/api/load-loader.js +222 -0
  27. package/dist/lib/api/load-loader.js.map +1 -0
  28. package/dist/lib/api/load.d.ts +3 -3
  29. package/dist/lib/api/load.d.ts.map +1 -1
  30. package/dist/lib/api/load.js +84 -5
  31. package/dist/lib/api/load.js.map +1 -1
  32. package/dist/lib/api/parse-file.d.ts +15 -0
  33. package/dist/lib/api/parse-file.d.ts.map +1 -0
  34. package/dist/lib/api/parse-file.js +74 -0
  35. package/dist/lib/api/parse-file.js.map +1 -0
  36. package/dist/lib/api/parse-in-batches.d.ts +2 -2
  37. package/dist/lib/api/parse-in-batches.d.ts.map +1 -1
  38. package/dist/lib/api/parse-in-batches.js +18 -7
  39. package/dist/lib/api/parse-in-batches.js.map +1 -1
  40. package/dist/lib/api/parse-sync.d.ts +2 -2
  41. package/dist/lib/api/parse-sync.d.ts.map +1 -1
  42. package/dist/lib/api/parse-sync.js +10 -1
  43. package/dist/lib/api/parse-sync.js.map +1 -1
  44. package/dist/lib/api/parse.d.ts +2 -2
  45. package/dist/lib/api/parse.d.ts.map +1 -1
  46. package/dist/lib/api/parse.js +34 -17
  47. package/dist/lib/api/parse.js.map +1 -1
  48. package/dist/lib/api/preload.d.ts +14 -0
  49. package/dist/lib/api/preload.d.ts.map +1 -0
  50. package/dist/lib/api/preload.js +13 -0
  51. package/dist/lib/api/preload.js.map +1 -0
  52. package/dist/lib/api/register-loaders.js +1 -1
  53. package/dist/lib/api/register-loaders.js.map +1 -1
  54. package/dist/lib/api/select-loader.d.ts.map +1 -1
  55. package/dist/lib/api/select-loader.js +48 -5
  56. package/dist/lib/api/select-loader.js.map +1 -1
  57. package/dist/lib/api/select-source.d.ts +3 -3
  58. package/dist/lib/api/select-source.d.ts.map +1 -1
  59. package/dist/lib/api/select-source.js +2 -5
  60. package/dist/lib/api/select-source.js.map +1 -1
  61. package/dist/lib/fetch/fetch-error-message.js +1 -1
  62. package/dist/lib/fetch/fetch-error-message.js.map +1 -1
  63. package/dist/lib/filesystems/browser-filesystem.d.ts.map +1 -1
  64. package/dist/lib/filesystems/browser-filesystem.js +25 -11
  65. package/dist/lib/filesystems/browser-filesystem.js.map +1 -1
  66. package/dist/lib/init.js +1 -1
  67. package/dist/lib/init.js.map +1 -1
  68. package/dist/lib/loader-utils/check-errors.js +1 -1
  69. package/dist/lib/loader-utils/check-errors.js.map +1 -1
  70. package/dist/lib/loader-utils/get-data.d.ts +4 -0
  71. package/dist/lib/loader-utils/get-data.d.ts.map +1 -1
  72. package/dist/lib/loader-utils/get-data.js +26 -0
  73. package/dist/lib/loader-utils/get-data.js.map +1 -1
  74. package/dist/lib/loader-utils/get-fetch-function.d.ts +1 -1
  75. package/dist/lib/loader-utils/get-fetch-function.d.ts.map +1 -1
  76. package/dist/lib/loader-utils/get-fetch-function.js +16 -10
  77. package/dist/lib/loader-utils/get-fetch-function.js.map +1 -1
  78. package/dist/lib/loader-utils/loader-context.d.ts +2 -2
  79. package/dist/lib/loader-utils/loader-context.d.ts.map +1 -1
  80. package/dist/lib/loader-utils/loader-context.js +11 -4
  81. package/dist/lib/loader-utils/loader-context.js.map +1 -1
  82. package/dist/lib/loader-utils/loggers.d.ts +19 -0
  83. package/dist/lib/loader-utils/loggers.d.ts.map +1 -1
  84. package/dist/lib/loader-utils/loggers.js +28 -2
  85. package/dist/lib/loader-utils/loggers.js.map +1 -1
  86. package/dist/lib/loader-utils/option-defaults.d.ts +1 -0
  87. package/dist/lib/loader-utils/option-defaults.d.ts.map +1 -1
  88. package/dist/lib/loader-utils/option-defaults.js +5 -0
  89. package/dist/lib/loader-utils/option-defaults.js.map +1 -1
  90. package/dist/lib/loader-utils/option-utils.d.ts +7 -0
  91. package/dist/lib/loader-utils/option-utils.d.ts.map +1 -1
  92. package/dist/lib/loader-utils/option-utils.js +91 -3
  93. package/dist/lib/loader-utils/option-utils.js.map +1 -1
  94. package/dist/lib/utils/response-utils.js +5 -14
  95. package/dist/lib/utils/response-utils.js.map +1 -1
  96. package/dist/null-loader.d.ts.map +1 -1
  97. package/dist/null-loader.js +1 -1
  98. package/dist/null-loader.js.map +1 -1
  99. package/dist/null-worker-node.js +270 -42
  100. package/dist/null-worker.js +270 -42
  101. package/package.json +6 -6
  102. package/src/index.ts +10 -1
  103. package/src/iterators/make-iterator/make-stream-iterator.ts +47 -9
  104. package/src/lib/api/core-api.ts +25 -0
  105. package/src/lib/api/create-data-source.ts +53 -24
  106. package/src/lib/api/load-in-batches.ts +33 -21
  107. package/src/lib/api/load-loader.ts +306 -0
  108. package/src/lib/api/load.ts +160 -9
  109. package/src/lib/api/parse-file.ts +156 -0
  110. package/src/lib/api/parse-in-batches.ts +35 -8
  111. package/src/lib/api/parse-sync.ts +27 -2
  112. package/src/lib/api/parse.ts +61 -20
  113. package/src/lib/api/preload.ts +46 -0
  114. package/src/lib/api/register-loaders.ts +1 -1
  115. package/src/lib/api/select-loader.ts +57 -5
  116. package/src/lib/api/select-source.ts +7 -10
  117. package/src/lib/fetch/fetch-error-message.ts +1 -1
  118. package/src/lib/filesystems/browser-filesystem.ts +25 -11
  119. package/src/lib/loader-utils/check-errors.ts +1 -1
  120. package/src/lib/loader-utils/get-data.ts +36 -0
  121. package/src/lib/loader-utils/get-fetch-function.ts +17 -15
  122. package/src/lib/loader-utils/loader-context.ts +13 -5
  123. package/src/lib/loader-utils/loggers.ts +28 -2
  124. package/src/lib/loader-utils/option-defaults.ts +5 -0
  125. package/src/lib/loader-utils/option-utils.ts +106 -3
  126. package/src/lib/utils/response-utils.ts +5 -15
  127. package/src/null-loader.ts +3 -3
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 = {};
@@ -39,10 +34,11 @@ var __exports__ = (() => {
39
34
  RequestScheduler: () => RequestScheduler,
40
35
  _BrowserFileSystem: () => BrowserFileSystem,
41
36
  _fetchProgress: () => fetchProgress,
42
- _selectSource: () => selectSource2,
37
+ _selectSource: () => selectSource,
43
38
  _unregisterLoaders: () => _unregisterLoaders,
44
39
  assert: () => assert,
45
40
  concatenateArrayBuffersAsync: () => concatenateArrayBuffersAsync,
41
+ coreApi: () => coreApi,
46
42
  createDataSource: () => createDataSource,
47
43
  document: () => document_,
48
44
  encode: () => encode,
@@ -78,8 +74,11 @@ var __exports__ = (() => {
78
74
  makeTextDecoderIterator: () => makeTextDecoderIterator,
79
75
  makeTextEncoderIterator: () => makeTextEncoderIterator,
80
76
  parse: () => parse,
77
+ parseFile: () => parseFile,
81
78
  parseInBatches: () => parseInBatches,
82
79
  parseSync: () => parseSync,
80
+ preload: () => preload,
81
+ preloadSync: () => preloadSync,
83
82
  readArrayBuffer: () => readArrayBuffer,
84
83
  registerLoaders: () => registerLoaders,
85
84
  resolvePath: () => resolvePath,
@@ -682,7 +681,7 @@ var __exports__ = (() => {
682
681
  }
683
682
  const options = { ...baseOptions };
684
683
  for (const [key, newValue] of Object.entries(newOptions)) {
685
- if (newValue && typeof newValue === "object" && !Array.isArray(newValue)) {
684
+ if (isPureObject(newValue)) {
686
685
  options[key] = mergeOptionsRecursively(
687
686
  options[key] || {},
688
687
  newOptions[key],
@@ -706,16 +705,11 @@ var __exports__ = (() => {
706
705
  var NPM_TAG = "latest";
707
706
 
708
707
  // ../worker-utils/src/lib/env-utils/version.ts
709
- var warningIssued = false;
710
708
  function getVersion() {
711
709
  if (!globalThis._loadersgl_?.version) {
712
710
  globalThis._loadersgl_ = globalThis._loadersgl_ || {};
713
- if (typeof __VERSION__ === "undefined" && !warningIssued) {
714
- console.warn(
715
- "loaders.gl: The __VERSION__ variable is not injected using babel plugin. Latest unstable workers would be fetched from the CDN."
716
- );
711
+ if (typeof __VERSION__ === "undefined") {
717
712
  globalThis._loadersgl_.version = NPM_TAG;
718
- warningIssued = true;
719
713
  } else {
720
714
  globalThis._loadersgl_.version = __VERSION__;
721
715
  }
@@ -785,7 +779,9 @@ var __exports__ = (() => {
785
779
  * Call to resolve the `result` Promise with the supplied value
786
780
  */
787
781
  done(value) {
788
- assert3(this.isRunning);
782
+ if (!this.isRunning) {
783
+ return;
784
+ }
789
785
  this.isRunning = false;
790
786
  this._resolve(value);
791
787
  }
@@ -793,14 +789,42 @@ var __exports__ = (() => {
793
789
  * Call to reject the `result` Promise with the supplied error
794
790
  */
795
791
  error(error) {
796
- assert3(this.isRunning);
792
+ if (!this.isRunning) {
793
+ return;
794
+ }
797
795
  this.isRunning = false;
798
796
  this._reject(error);
799
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
+ }
800
810
  };
811
+ function createAbortError(message) {
812
+ const error = new Error(message);
813
+ error.name = "AbortError";
814
+ return error;
815
+ }
801
816
 
802
817
  // ../worker-utils/src/lib/node/worker_threads-browser.ts
803
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. */
804
828
  terminate() {
805
829
  }
806
830
  };
@@ -901,6 +925,10 @@ var __exports__ = (() => {
901
925
  name;
902
926
  source;
903
927
  url;
928
+ /** Lazily resolves the classic worker URL used as a fallback. */
929
+ getUrl;
930
+ /** Creates a browser Worker directly. */
931
+ loadWorker;
904
932
  terminated = false;
905
933
  worker;
906
934
  onMessage;
@@ -911,11 +939,13 @@ var __exports__ = (() => {
911
939
  return typeof Worker !== "undefined" && isBrowser3 || typeof NodeWorker !== "undefined" && !isBrowser3;
912
940
  }
913
941
  constructor(props) {
914
- const { name, source, url } = props;
915
- assert3(source || url);
942
+ const { name, source, url, getUrl, loadWorker } = props;
943
+ assert3(source || url || getUrl || loadWorker);
916
944
  this.name = name;
917
945
  this.source = source;
918
946
  this.url = url;
947
+ this.getUrl = getUrl;
948
+ this.loadWorker = loadWorker;
919
949
  this.onMessage = NOOP;
920
950
  this.onError = (error) => console.log(error);
921
951
  this.worker = isBrowser3 ? this._createBrowserWorker() : this._createNodeWorker();
@@ -930,6 +960,18 @@ var __exports__ = (() => {
930
960
  this.worker.terminate();
931
961
  this.terminated = true;
932
962
  }
963
+ /** Keeps this worker from preventing Node.js process exit while idle. */
964
+ unref() {
965
+ if (!isBrowser3 && typeof this.worker.unref === "function") {
966
+ this.worker.unref();
967
+ }
968
+ }
969
+ /** Keeps this worker alive while it is actively processing a job. */
970
+ ref() {
971
+ if (!isBrowser3 && typeof this.worker.ref === "function") {
972
+ this.worker.ref();
973
+ }
974
+ }
933
975
  get isRunning() {
934
976
  return Boolean(this.onMessage);
935
977
  }
@@ -949,7 +991,7 @@ var __exports__ = (() => {
949
991
  */
950
992
  _getErrorFromErrorEvent(event) {
951
993
  let message = "Failed to load ";
952
- message += `worker ${this.name} from ${this.url}. `;
994
+ message += `worker ${this.name} from ${this.url || "built-in worker factory"}. `;
953
995
  if (event.message) {
954
996
  message += `${event.message} in `;
955
997
  }
@@ -962,8 +1004,25 @@ var __exports__ = (() => {
962
1004
  * Creates a worker thread on the browser
963
1005
  */
964
1006
  _createBrowserWorker() {
965
- 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 });
966
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) {
967
1026
  worker.onmessage = (event) => {
968
1027
  if (!event.data) {
969
1028
  this.onError(new Error("No data received"));
@@ -987,8 +1046,9 @@ var __exports__ = (() => {
987
1046
  if (this.url) {
988
1047
  const absolute = this.url.includes(":/") || this.url.startsWith("/");
989
1048
  const url = absolute ? this.url : `./${this.url}`;
1049
+ const workerUrl = url.startsWith("file:") ? new URL(url) : url;
990
1050
  const type = this.url.endsWith(".ts") || this.url.endsWith(".mjs") ? "module" : "commonjs";
991
- worker = new NodeWorker(url, { eval: false, type });
1051
+ worker = new NodeWorker(workerUrl, { eval: false, type });
992
1052
  } else if (this.source) {
993
1053
  worker = new NodeWorker(this.source, { eval: true });
994
1054
  } else {
@@ -1000,7 +1060,7 @@ var __exports__ = (() => {
1000
1060
  worker.on("error", (error) => {
1001
1061
  this.onError(error);
1002
1062
  });
1003
- worker.on("exit", (code) => {
1063
+ worker.on("exit", (_code) => {
1004
1064
  });
1005
1065
  return worker;
1006
1066
  }
@@ -1012,6 +1072,10 @@ var __exports__ = (() => {
1012
1072
  source;
1013
1073
  // | Function;
1014
1074
  url;
1075
+ /** Lazily resolves a classic worker fallback URL. */
1076
+ getUrl;
1077
+ /** Creates a browser Worker directly. */
1078
+ loadWorker;
1015
1079
  maxConcurrency = 1;
1016
1080
  maxMobileConcurrency = 1;
1017
1081
  onDebug = () => {
@@ -1020,6 +1084,7 @@ var __exports__ = (() => {
1020
1084
  props = {};
1021
1085
  jobQueue = [];
1022
1086
  idleQueue = [];
1087
+ activeJobs = /* @__PURE__ */ new Set();
1023
1088
  count = 0;
1024
1089
  isDestroyed = false;
1025
1090
  /** Checks if workers are supported on this platform */
@@ -1033,13 +1098,19 @@ var __exports__ = (() => {
1033
1098
  constructor(props) {
1034
1099
  this.source = props.source;
1035
1100
  this.url = props.url;
1101
+ this.getUrl = props.getUrl;
1102
+ this.loadWorker = props.loadWorker;
1036
1103
  this.setProps(props);
1037
1104
  }
1038
1105
  /**
1039
- * 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.
1040
1108
  * @note Can free up significant memory
1041
1109
  */
1042
- 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));
1043
1114
  this.idleQueue.forEach((worker) => worker.destroy());
1044
1115
  this.isDestroyed = true;
1045
1116
  }
@@ -1061,9 +1132,12 @@ var __exports__ = (() => {
1061
1132
  this.onDebug = props.onDebug;
1062
1133
  }
1063
1134
  }
1064
- async startJob(name, onMessage3 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
1065
- const startPromise = new Promise((onStart) => {
1066
- this.jobQueue.push({ name, onMessage: onMessage3, onError, onStart });
1135
+ async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
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 });
1067
1141
  return this;
1068
1142
  });
1069
1143
  this._startQueuedJob();
@@ -1091,14 +1165,16 @@ var __exports__ = (() => {
1091
1165
  backlog: this.jobQueue.length
1092
1166
  });
1093
1167
  const job = new WorkerJob(queuedJob.name, workerThread);
1168
+ this.activeJobs.add(job);
1169
+ workerThread.ref();
1094
1170
  workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
1095
1171
  workerThread.onError = (error) => queuedJob.onError(job, error);
1096
1172
  queuedJob.onStart(job);
1097
1173
  try {
1098
1174
  await job.result;
1099
- } catch (error) {
1100
- console.error(`Worker exception: ${error}`);
1175
+ } catch {
1101
1176
  } finally {
1177
+ this.activeJobs.delete(job);
1102
1178
  this.returnWorkerToQueue(workerThread);
1103
1179
  }
1104
1180
  }
@@ -1113,17 +1189,19 @@ var __exports__ = (() => {
1113
1189
  */
1114
1190
  returnWorkerToQueue(worker) {
1115
1191
  const shouldDestroyWorker = (
1116
- // Workers on Node.js prevent the process from exiting.
1117
- // Until we figure out how to close them before exit, we always destroy them
1118
- !isBrowser3 || // 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
1119
1194
  this.isDestroyed || // If the app has disabled worker reuse, any completed workers should be destroyed
1120
1195
  !this.reuseWorkers || // If concurrency has been lowered, this worker might be surplus to requirements
1121
1196
  this.count > this._getMaxConcurrency()
1122
1197
  );
1123
1198
  if (shouldDestroyWorker) {
1124
- worker.destroy();
1199
+ if (!worker.terminated) {
1200
+ worker.destroy();
1201
+ }
1125
1202
  this.count--;
1126
1203
  } else {
1204
+ worker.unref();
1127
1205
  this.idleQueue.push(worker);
1128
1206
  }
1129
1207
  if (!this.isDestroyed) {
@@ -1140,7 +1218,13 @@ var __exports__ = (() => {
1140
1218
  if (this.count < this._getMaxConcurrency()) {
1141
1219
  this.count++;
1142
1220
  const name = `${this.name.toLowerCase()} (#${this.count} of ${this.maxConcurrency})`;
1143
- 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
+ });
1144
1228
  }
1145
1229
  return null;
1146
1230
  }
@@ -1157,9 +1241,13 @@ var __exports__ = (() => {
1157
1241
  onDebug: () => {
1158
1242
  }
1159
1243
  };
1160
- var _WorkerFarm = class {
1244
+ var loadWorkerIds = /* @__PURE__ */ new WeakMap();
1245
+ var nextLoadWorkerId = 1;
1246
+ var WorkerFarm = class _WorkerFarm {
1161
1247
  props;
1162
1248
  workerPools = /* @__PURE__ */ new Map();
1249
+ // singleton
1250
+ static _workerFarm;
1163
1251
  /** Checks if workers are supported on this platform */
1164
1252
  static isSupported() {
1165
1253
  return WorkerThread.isSupported();
@@ -1177,12 +1265,13 @@ var __exports__ = (() => {
1177
1265
  this.workerPools = /* @__PURE__ */ new Map();
1178
1266
  }
1179
1267
  /**
1180
- * 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.
1181
1270
  * @note Can free up significant memory
1182
1271
  */
1183
- destroy() {
1272
+ destroy(reason) {
1184
1273
  for (const workerPool of this.workerPools.values()) {
1185
- workerPool.destroy();
1274
+ workerPool.destroy(reason);
1186
1275
  }
1187
1276
  this.workerPools = /* @__PURE__ */ new Map();
1188
1277
  }
@@ -1198,24 +1287,28 @@ var __exports__ = (() => {
1198
1287
  }
1199
1288
  /**
1200
1289
  * Returns a worker pool for the specified worker
1201
- * @param options - only used first time for a specific worker name
1202
- * @param options.name - the name of the worker - used to identify worker pool
1203
- * @param options.url -
1204
- * @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.
1205
1295
  * @example
1206
1296
  * const job = WorkerFarm.getWorkerFarm().getWorkerPool({name, url}).startJob(...);
1207
1297
  */
1208
1298
  getWorkerPool(options) {
1209
- const { name, source, url } = options;
1210
- 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);
1211
1302
  if (!workerPool) {
1212
1303
  workerPool = new WorkerPool({
1213
1304
  name,
1214
1305
  source,
1215
- url
1306
+ url,
1307
+ getUrl,
1308
+ loadWorker
1216
1309
  });
1217
1310
  workerPool.setProps(this._getWorkerPoolProps());
1218
- this.workerPools.set(name, workerPool);
1311
+ this.workerPools.set(workerPoolKey, workerPool);
1219
1312
  }
1220
1313
  return workerPool;
1221
1314
  }
@@ -1228,62 +1321,345 @@ var __exports__ = (() => {
1228
1321
  };
1229
1322
  }
1230
1323
  };
1231
- var WorkerFarm = _WorkerFarm;
1232
- // singleton
1233
- __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
+ };
1234
1409
 
1235
1410
  // ../worker-utils/src/lib/worker-api/get-worker-url.ts
1411
+ var warnedWorkerVersionFallbacks = /* @__PURE__ */ new Set();
1236
1412
  function getWorkerName(worker) {
1237
1413
  const warning = worker.version !== VERSION3 ? ` (worker-utils@${VERSION3})` : "";
1238
1414
  return `${worker.name}@${worker.version}${warning}`;
1239
1415
  }
1240
- function getWorkerURL(worker, options = {}) {
1416
+ function getCustomWorkerURL(worker, options = {}) {
1241
1417
  const workerOptions = options[worker.id] || {};
1242
- const workerFile = isBrowser3 ? worker.workerFile || `${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`;
1243
1419
  let url = workerOptions.workerUrl;
1244
1420
  if (!url && worker.id === "compression") {
1245
1421
  url = options.workerUrl;
1246
1422
  }
1247
1423
  const workerType = options._workerType || options?.core?._workerType;
1248
- if (workerType === "test") {
1424
+ if (!url && workerType === "test") {
1249
1425
  if (isBrowser3) {
1250
1426
  url = `modules/${worker.module}/dist/${workerFile}`;
1251
1427
  } else {
1252
1428
  url = `modules/${worker.module}/src/workers/${worker.id}-worker-node.ts`;
1253
1429
  }
1254
1430
  }
1255
- if (!url) {
1256
- let version2 = worker.version;
1257
- if (version2 === "latest") {
1258
- version2 = NPM_TAG;
1259
- }
1260
- const versionTag = version2 ? `@${version2}` : "";
1261
- url = `https://unpkg.com/@loaders.gl/${worker.module}${versionTag}/dist/${workerFile}`;
1262
- }
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);
1263
1437
  assert3(url);
1264
1438
  return url;
1265
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) {
1449
+ warnIfUsingNpmTagFallback(worker, url);
1450
+ }
1451
+ return url;
1452
+ }
1453
+ function warnIfUsingNpmTagFallback(worker, url) {
1454
+ if (worker.version !== "latest") {
1455
+ return;
1456
+ }
1457
+ const workerId = `${worker.module}:${worker.id}`;
1458
+ if (warnedWorkerVersionFallbacks.has(workerId)) {
1459
+ return;
1460
+ }
1461
+ warnedWorkerVersionFallbacks.add(workerId);
1462
+ console.warn(
1463
+ `loaders.gl: ${worker.name} loader worker version is "latest" because __VERSION__ was not injected. Fetching ${url} from CDN.`
1464
+ );
1465
+ }
1266
1466
 
1267
1467
  // ../worker-utils/src/lib/worker-api/process-on-worker.ts
1268
- async function processOnWorker(worker, data, options = {}, context = {}) {
1468
+ function canProcessOnWorker(worker, options) {
1469
+ if (!WorkerFarm.isSupported()) {
1470
+ return false;
1471
+ }
1472
+ const workerOptions = options?.[worker.id];
1473
+ return Boolean(
1474
+ (worker.worker || worker.loadWorker || workerOptions?.workerUrl) && options?.worker
1475
+ );
1476
+ }
1477
+ async function processOnWorker(worker, data, options = {}, context = {}, jobContext = {}) {
1478
+ throwIfAborted(options.signal);
1269
1479
  const name = getWorkerName(worker);
1270
1480
  const workerFarm = WorkerFarm.getWorkerFarm(options);
1271
- const { source } = options;
1272
- const workerPoolProps = { name, source };
1273
- if (!source) {
1274
- workerPoolProps.url = getWorkerURL(worker, options);
1275
- }
1276
- const workerPool = workerFarm.getWorkerPool(workerPoolProps);
1481
+ const workerPool = workerFarm.getWorkerPool(getWorkerPoolTarget(worker, options, name));
1277
1482
  const jobName = options.jobName || worker.name;
1278
1483
  const job = await workerPool.startJob(
1279
1484
  jobName,
1280
1485
  // eslint-disable-next-line
1281
1486
  onMessage.bind(null, context)
1282
1487
  );
1283
- const transferableOptions = getTransferListForWriter(options);
1284
- job.postMessage("process", { input: data, options: transferableOptions });
1285
- const result = await job.result;
1286
- 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) };
1287
1663
  }
1288
1664
  async function onMessage(context, job, type, payload) {
1289
1665
  switch (type) {
@@ -1300,7 +1676,7 @@ var __exports__ = (() => {
1300
1676
  job.postMessage("error", { id, error: "Worker not set up to process on main thread" });
1301
1677
  return;
1302
1678
  }
1303
- const result = await context.process(input, options);
1679
+ const result = await context.process(input, options, void 0, payload.context || {});
1304
1680
  job.postMessage("done", { id, result });
1305
1681
  } catch (error) {
1306
1682
  const message = error instanceof Error ? error.message : "unknown error";
@@ -1324,60 +1700,167 @@ var __exports__ = (() => {
1324
1700
 
1325
1701
  // ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
1326
1702
  function canParseWithWorker(loader, options) {
1327
- if (!WorkerFarm.isSupported()) {
1703
+ if (options?.core?.credentials?.some(
1704
+ (credential) => credential.type === "request" || "token" in credential && typeof credential.token === "function"
1705
+ ))
1328
1706
  return false;
1329
- }
1330
- const nodeWorkers = options?._nodeWorkers ?? options?.core?._nodeWorkers;
1707
+ const workerOptions = getWorkerOptions(options);
1708
+ const nodeWorkers = workerOptions._nodeWorkers;
1331
1709
  if (!isBrowser3 && !nodeWorkers) {
1332
1710
  return false;
1333
1711
  }
1334
- const useWorkers = options?.worker ?? options?.core?.worker;
1335
- return Boolean(loader.worker && useWorkers);
1336
- }
1337
- async function parseWithWorker(loader, data, options, context, parseOnMainThread) {
1338
- const name = loader.id;
1339
- const url = getWorkerURL(loader, options);
1340
- const workerFarm = WorkerFarm.getWorkerFarm(options?.core);
1341
- const workerPool = workerFarm.getWorkerPool({ name, url });
1342
- options = JSON.parse(JSON.stringify(options || {}));
1343
- options._workerLoaderId = loader.id;
1344
- context = JSON.parse(JSON.stringify(context || {}));
1345
- const job = await workerPool.startJob(
1346
- "process-on-worker",
1347
- // @ts-expect-error
1348
- onMessage2.bind(null, parseOnMainThread)
1349
- // eslint-disable-line @typescript-eslint/no-misused-promises
1712
+ if (loader.id === "las" && (options?.las?.shape ?? "arrow-table") === "arrow-table") {
1713
+ return false;
1714
+ }
1715
+ if (loader.id === "csv" && !shouldParseCSVWithWorker(options)) {
1716
+ return false;
1717
+ }
1718
+ return Boolean(canProcessOnWorker(loader, workerOptions));
1719
+ }
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);
1739
+ const result = await processOnWorker(
1740
+ loader,
1741
+ data,
1742
+ { ...getWorkerOptions(options, loader), signal: workerSignal },
1743
+ {
1744
+ process: async (input, processOptions, _workerContext, parseContext) => {
1745
+ if (!parseOnMainThread) {
1746
+ throw new Error("Worker not set up to parse on main thread");
1747
+ }
1748
+ const { _loaderIds, _loaderIsArray, ...workerParseContext } = parseContext || {};
1749
+ const mainThreadContext = context || parseContext ? { ...context, ...workerParseContext } : void 0;
1750
+ return await callParseOnMainThread(
1751
+ parseOnMainThread,
1752
+ input,
1753
+ processOptions,
1754
+ mainThreadContext,
1755
+ resolveWorkerLoaders(loader, _loaderIds, _loaderIsArray, context, options)
1756
+ );
1757
+ }
1758
+ },
1759
+ getSerializableLoaderContext(context)
1350
1760
  );
1351
- job.postMessage("process", {
1352
- // @ts-ignore
1353
- input: data,
1354
- options,
1355
- context
1356
- });
1357
- const result = await job.result;
1358
- return await result.result;
1761
+ return isLoaderWithWorkerResultDeserializer(loader) ? loader.deserializeWorkerResult(result, options, context) : result;
1359
1762
  }
1360
- async function onMessage2(parseOnMainThread, job, type, payload) {
1361
- switch (type) {
1362
- case "done":
1363
- job.done(payload);
1364
- break;
1365
- case "error":
1366
- job.error(new Error(payload.error));
1367
- break;
1368
- case "process":
1369
- const { id, input, options } = payload;
1370
- try {
1371
- const result = await parseOnMainThread(input, options);
1372
- job.postMessage("done", { id, result });
1373
- } catch (error) {
1374
- const message = error instanceof Error ? error.message : "unknown error";
1375
- job.postMessage("error", { id, error: message });
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
+ );
1376
1783
  }
1377
- break;
1378
- default:
1379
- console.warn(`parse-with-worker unknown message ${type}`);
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) {
1800
+ return parseOnMainThread(input, options);
1801
+ }
1802
+ return parseOnMainThread(input, loaders, options, context);
1803
+ }
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 = {
1840
+ ...serializedOptions.core,
1841
+ ...serializedOptions
1842
+ };
1843
+ if (workerOptions.worker === "auto") {
1844
+ workerOptions.worker = true;
1845
+ }
1846
+ if (loader) {
1847
+ workerOptions._workerLoaderId = loader.id;
1848
+ }
1849
+ return workerOptions;
1850
+ }
1851
+ function getSerializableLoaderContext(context) {
1852
+ if (!context) {
1853
+ return {};
1380
1854
  }
1855
+ const { fetch: fetch2, loaders, coreApi: coreApi2, _parse, _parseSync, _parseInBatches, ...serializableContext } = context;
1856
+ return JSON.parse(JSON.stringify(serializableContext));
1857
+ }
1858
+ function shouldParseCSVWithWorker(options) {
1859
+ const csvOptions = options;
1860
+ return (csvOptions?.csv?.shape ?? csvOptions?.core?.shape) === "arrow-table";
1861
+ }
1862
+ function isLoaderWithWorkerResultDeserializer(loader) {
1863
+ return typeof loader.deserializeWorkerResult === "function";
1381
1864
  }
1382
1865
 
1383
1866
  // ../loader-utils/src/lib/worker-loader-utils/encode-with-worker.ts
@@ -1425,6 +1908,19 @@ var __exports__ = (() => {
1425
1908
  return result.buffer;
1426
1909
  }
1427
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
+
1428
1924
  // ../loader-utils/src/lib/iterators/text-iterators.ts
1429
1925
  async function* makeTextDecoderIterator(arrayBufferIterator, options = {}) {
1430
1926
  const textDecoder = new TextDecoder(void 0, options);
@@ -1443,10 +1939,12 @@ var __exports__ = (() => {
1443
1939
  for await (const textChunk of textIterator) {
1444
1940
  previous += textChunk;
1445
1941
  let eolIndex;
1446
- while ((eolIndex = previous.indexOf("\n")) >= 0) {
1942
+ eolIndex = previous.indexOf("\n");
1943
+ while (eolIndex >= 0) {
1447
1944
  const line = previous.slice(0, eolIndex + 1);
1448
1945
  previous = previous.slice(eolIndex + 1);
1449
1946
  yield line;
1947
+ eolIndex = previous.indexOf("\n");
1450
1948
  }
1451
1949
  }
1452
1950
  if (previous.length > 0) {
@@ -1749,6 +2247,7 @@ var __exports__ = (() => {
1749
2247
  /** Tracks the number of active requests and prioritizes/cancels queued requests. */
1750
2248
  requestQueue = [];
1751
2249
  requestMap = /* @__PURE__ */ new Map();
2250
+ /** Pending arrival debounce or next-tick refill; only new arrivals replace this timer. */
1752
2251
  updateTimer = null;
1753
2252
  constructor(props = {}) {
1754
2253
  this.props = { ...DEFAULT_PROPS2, ...props };
@@ -1816,22 +2315,27 @@ var __exports__ = (() => {
1816
2315
  isDone = true;
1817
2316
  this.requestMap.delete(handle);
1818
2317
  this.activeRequestCount--;
1819
- if (this.updateTimer === null) {
1820
- this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), 0);
1821
- }
2318
+ this.scheduleRefill();
1822
2319
  }
1823
2320
  };
1824
2321
  this.activeRequestCount++;
1825
2322
  return resolve2 ? resolve2({ done }) : Promise.resolve({ done });
1826
2323
  }
1827
- /** 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. */
1828
2332
  _issueNewRequests() {
1829
2333
  if (this.updateTimer !== null) {
1830
2334
  clearTimeout(this.updateTimer);
1831
2335
  }
1832
2336
  this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), this.props.debounceTime);
1833
2337
  }
1834
- /** Refresh all requests */
2338
+ /** Clears timer ownership before updating priorities and dispatching queued requests. */
1835
2339
  _issueNewRequestsAsync() {
1836
2340
  if (this.updateTimer !== null) {
1837
2341
  clearTimeout(this.updateTimer);
@@ -1873,109 +2377,287 @@ var __exports__ = (() => {
1873
2377
  }
1874
2378
  };
1875
2379
 
1876
- // ../loader-utils/src/lib/path-utils/file-aliases.ts
1877
- var pathPrefix = "";
1878
- var fileAliases = {};
1879
- function setPathPrefix(prefix) {
1880
- pathPrefix = prefix;
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
+ });
1881
2402
  }
1882
- function getPathPrefix() {
1883
- return pathPrefix;
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
+ });
1884
2422
  }
1885
- function resolvePath(filename2) {
1886
- for (const alias in fileAliases) {
1887
- if (filename2.startsWith(alias)) {
1888
- const replacement = fileAliases[alias];
1889
- filename2 = filename2.replace(alias, replacement);
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);
1890
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;
1891
2522
  }
1892
- if (!filename2.startsWith("http://") && !filename2.startsWith("https://")) {
1893
- filename2 = `${pathPrefix}${filename2}`;
1894
- }
1895
- return filename2;
2523
+ return mergedOptions;
1896
2524
  }
1897
-
1898
- // ../loader-utils/src/json-loader.ts
1899
- var VERSION4 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
1900
- var JSONLoader = {
1901
- dataType: null,
1902
- batchType: null,
1903
- name: "JSON",
1904
- id: "json",
1905
- module: "json",
1906
- version: VERSION4,
1907
- extensions: ["json", "geojson"],
1908
- mimeTypes: ["application/json"],
1909
- category: "json",
1910
- text: true,
1911
- parseTextSync,
1912
- parse: async (arrayBuffer) => parseTextSync(new TextDecoder().decode(arrayBuffer)),
1913
- options: {}
1914
- };
1915
- function parseTextSync(text) {
1916
- return JSON.parse(text);
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 };
1917
2549
  }
1918
-
1919
- // ../loader-utils/src/lib/node/buffer.browser.ts
1920
- function toArrayBuffer(buffer) {
1921
- return buffer;
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
+ }
1922
2558
  }
1923
-
1924
- // ../loader-utils/src/lib/binary-utils/memory-conversion-utils.ts
1925
- function isBuffer(value) {
1926
- return value && typeof value === "object" && value.isBuffer;
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
+ });
1927
2575
  }
1928
- function toArrayBuffer2(data) {
1929
- if (isBuffer(data)) {
1930
- return toArrayBuffer(data);
1931
- }
1932
- if (data instanceof ArrayBuffer) {
1933
- return data;
1934
- }
1935
- if (isSharedArrayBuffer(data)) {
1936
- return copyToArrayBuffer2(data);
1937
- }
1938
- if (ArrayBuffer.isView(data)) {
1939
- const buffer = data.buffer;
1940
- if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
1941
- return buffer;
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;
1942
2591
  }
1943
- return buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
1944
- }
1945
- if (typeof data === "string") {
1946
- const text = data;
1947
- const uint8Array = new TextEncoder().encode(text);
1948
- return uint8Array.buffer;
1949
- }
1950
- if (data && typeof data === "object" && data._toArrayBuffer) {
1951
- return data._toArrayBuffer();
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 });
1952
2600
  }
1953
- throw new Error("toArrayBuffer");
2601
+ return {
2602
+ url: url.toString(),
2603
+ options: { ...requestOptions, headers },
2604
+ credentials: resolvedCredentials
2605
+ };
1954
2606
  }
1955
- function ensureArrayBuffer(bufferSource) {
1956
- if (bufferSource instanceof ArrayBuffer) {
1957
- return bufferSource;
1958
- }
1959
- if (isSharedArrayBuffer(bufferSource)) {
1960
- return copyToArrayBuffer2(bufferSource);
1961
- }
1962
- const { buffer, byteOffset, byteLength } = bufferSource;
1963
- if (buffer instanceof ArrayBuffer && byteOffset === 0 && byteLength === buffer.byteLength) {
1964
- return buffer;
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;
1965
2630
  }
1966
- return copyToArrayBuffer2(buffer, byteOffset, byteLength);
1967
2631
  }
1968
- function copyToArrayBuffer2(buffer, byteOffset = 0, byteLength = buffer.byteLength - byteOffset) {
1969
- const view = new Uint8Array(buffer, byteOffset, byteLength);
1970
- const copy = new Uint8Array(view.length);
1971
- copy.set(view);
1972
- return copy.buffer;
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);
1973
2636
  }
1974
- function toArrayBufferView(data) {
1975
- if (ArrayBuffer.isView(data)) {
1976
- return data;
2637
+ function createAbortError3() {
2638
+ return new DOMException("The operation was aborted.", "AbortError");
2639
+ }
2640
+
2641
+ // ../loader-utils/src/lib/path-utils/file-aliases.ts
2642
+ var pathPrefix = "";
2643
+ var fileAliases = {};
2644
+ function setPathPrefix(prefix) {
2645
+ pathPrefix = prefix;
2646
+ }
2647
+ function getPathPrefix() {
2648
+ return pathPrefix;
2649
+ }
2650
+ function resolvePath(filename2) {
2651
+ for (const alias in fileAliases) {
2652
+ if (filename2.startsWith(alias)) {
2653
+ const replacement = fileAliases[alias];
2654
+ filename2 = filename2.replace(alias, replacement);
2655
+ }
1977
2656
  }
1978
- return new Uint8Array(data);
2657
+ if (!filename2.startsWith("http://") && !filename2.startsWith("https://")) {
2658
+ filename2 = `${pathPrefix}${filename2}`;
2659
+ }
2660
+ return filename2;
1979
2661
  }
1980
2662
 
1981
2663
  // ../loader-utils/src/lib/path-utils/path.ts
@@ -1992,7 +2674,7 @@ var __exports__ = (() => {
1992
2674
  if (typeof process !== "undefined" && typeof process.cwd !== "undefined") {
1993
2675
  return process.cwd();
1994
2676
  }
1995
- const pathname = window.location?.pathname;
2677
+ const pathname = globalThis.location?.pathname;
1996
2678
  return pathname?.slice(0, pathname.lastIndexOf("/") + 1) || "";
1997
2679
  }
1998
2680
 
@@ -2121,6 +2803,91 @@ var __exports__ = (() => {
2121
2803
  return res;
2122
2804
  }
2123
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
+
2124
2891
  // ../loader-utils/src/lib/files/blob-file.ts
2125
2892
  var BlobFile = class {
2126
2893
  handle;
@@ -2142,8 +2909,14 @@ var __exports__ = (() => {
2142
2909
  isDirectory: false
2143
2910
  };
2144
2911
  }
2145
- async read(start, length) {
2912
+ async read(start, length, signal) {
2913
+ if (signal?.aborted) {
2914
+ throw new Error("Request aborted");
2915
+ }
2146
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
+ }
2147
2920
  return arrayBuffer;
2148
2921
  }
2149
2922
  };
@@ -2189,6 +2962,11 @@ var __exports__ = (() => {
2189
2962
  }
2190
2963
  };
2191
2964
 
2965
+ // ../loader-utils/src/source-types.ts
2966
+ function isSourceLoader(loader) {
2967
+ return Boolean(loader && typeof loader === "object" && "createDataSource" in loader);
2968
+ }
2969
+
2192
2970
  // src/lib/fetch/fetch-error.ts
2193
2971
  var FetchError = class extends Error {
2194
2972
  constructor(message, info) {
@@ -2340,7 +3118,7 @@ var __exports__ = (() => {
2340
3118
  try {
2341
3119
  const contentType = response.headers.get("Content-Type");
2342
3120
  info.reason = !response.bodyUsed && contentType?.includes("application/json") ? await response.json() : await response.text();
2343
- } catch (error) {
3121
+ } catch (_error) {
2344
3122
  }
2345
3123
  return new FetchError(message, info);
2346
3124
  }
@@ -2359,19 +3137,11 @@ var __exports__ = (() => {
2359
3137
  }
2360
3138
  if (resource instanceof ArrayBuffer) {
2361
3139
  const slice = resource.slice(0, INITIAL_DATA_LENGTH);
2362
- const base64 = arrayBufferToBase64(slice);
3140
+ const base64 = encodeArrayBufferToBase64(slice);
2363
3141
  return `data:base64,${base64}`;
2364
3142
  }
2365
3143
  return null;
2366
3144
  }
2367
- function arrayBufferToBase64(buffer) {
2368
- let binary = "";
2369
- const bytes = new Uint8Array(buffer);
2370
- for (let i = 0; i < bytes.byteLength; i++) {
2371
- binary += String.fromCharCode(bytes[i]);
2372
- }
2373
- return btoa(binary);
2374
- }
2375
3145
 
2376
3146
  // src/lib/fetch/fetch-file.ts
2377
3147
  function isNodePath(url) {
@@ -2416,37 +3186,64 @@ var __exports__ = (() => {
2416
3186
  // src/lib/loader-utils/loggers.ts
2417
3187
  var probeLog = new ProbeLog({ id: "loaders.gl" });
2418
3188
  var NullLog = class {
3189
+ /** Drops a log message. */
2419
3190
  log() {
2420
3191
  return () => {
2421
3192
  };
2422
3193
  }
3194
+ /** Drops an info message. */
2423
3195
  info() {
2424
3196
  return () => {
2425
3197
  };
2426
3198
  }
3199
+ /** Logs one message once; no-op for the null logger. */
3200
+ once() {
3201
+ return () => {
3202
+ };
3203
+ }
3204
+ /** Drops a warning message. */
2427
3205
  warn() {
2428
3206
  return () => {
2429
3207
  };
2430
3208
  }
3209
+ /** Drops an error message. */
2431
3210
  error() {
2432
3211
  return () => {
2433
3212
  };
2434
3213
  }
2435
3214
  };
2436
3215
  var ConsoleLog = class {
3216
+ /** Console-like object used for message output. */
2437
3217
  console;
3218
+ /** Messages already emitted through `once`. */
3219
+ onceMessages = /* @__PURE__ */ new Set();
3220
+ /** Creates a console-backed logger. */
2438
3221
  constructor() {
2439
3222
  this.console = console;
2440
3223
  }
3224
+ /** Logs a message to the console. */
2441
3225
  log(...args) {
2442
3226
  return this.console.log.bind(this.console, ...args);
2443
3227
  }
3228
+ /** Logs an informational message to the console. */
2444
3229
  info(...args) {
2445
3230
  return this.console.info.bind(this.console, ...args);
2446
3231
  }
3232
+ /** Logs one message once to the console. */
3233
+ once(...args) {
3234
+ const message = String(args[0]);
3235
+ if (this.onceMessages.has(message)) {
3236
+ return () => {
3237
+ };
3238
+ }
3239
+ this.onceMessages.add(message);
3240
+ return this.console.info.bind(this.console, ...args);
3241
+ }
3242
+ /** Logs a warning message to the console. */
2447
3243
  warn(...args) {
2448
3244
  return this.console.warn.bind(this.console, ...args);
2449
3245
  }
3246
+ /** Logs an error message to the console. */
2450
3247
  error(...args) {
2451
3248
  return this.console.error.bind(this.console, ...args);
2452
3249
  }
@@ -2454,6 +3251,7 @@ var __exports__ = (() => {
2454
3251
 
2455
3252
  // src/lib/loader-utils/option-defaults.ts
2456
3253
  var DEFAULT_LOADER_OPTIONS = {
3254
+ searchParams: void 0,
2457
3255
  core: {
2458
3256
  baseUrl: void 0,
2459
3257
  // baseUrl
@@ -2462,12 +3260,15 @@ var __exports__ = (() => {
2462
3260
  fallbackMimeType: void 0,
2463
3261
  ignoreRegisteredLoaders: void 0,
2464
3262
  nothrow: false,
3263
+ shape: void 0,
2465
3264
  log: new ConsoleLog(),
2466
3265
  // A probe.gl compatible (`log.log()()` syntax) that just logs to console
2467
3266
  useLocalLibraries: false,
3267
+ subloaders: void 0,
2468
3268
  CDN: "https://unpkg.com/@loaders.gl",
2469
3269
  worker: true,
2470
3270
  // By default, use worker if provided by loader.
3271
+ workerThreshold: 0.1,
2471
3272
  maxConcurrency: 3,
2472
3273
  // How many worker instances should be created for each loader.
2473
3274
  maxMobileConcurrency: 1,
@@ -2507,6 +3308,7 @@ var __exports__ = (() => {
2507
3308
  _worker: "core._workerType",
2508
3309
  limit: "core.limit",
2509
3310
  _limitMB: "core._limitMB",
3311
+ shape: "core.shape",
2510
3312
  batchSize: "core.batchSize",
2511
3313
  batchDebounceMs: "core.batchDebounceMs",
2512
3314
  metadata: "core.metadata",
@@ -2542,18 +3344,42 @@ var __exports__ = (() => {
2542
3344
  "useLocalLibraries",
2543
3345
  "CDN",
2544
3346
  "worker",
3347
+ "workerThreshold",
2545
3348
  "maxConcurrency",
2546
3349
  "maxMobileConcurrency",
2547
3350
  "reuseWorkers",
3351
+ "workerTransferBufferCopy",
2548
3352
  "_nodeWorkers",
2549
3353
  "_workerType",
2550
3354
  "limit",
2551
3355
  "_limitMB",
3356
+ "shape",
2552
3357
  "batchSize",
2553
3358
  "batchDebounceMs",
2554
3359
  "metadata",
2555
3360
  "transforms"
2556
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
+ }
2557
3383
  function getGlobalLoaderState() {
2558
3384
  globalThis.loaders = globalThis.loaders || {};
2559
3385
  const { loaders } = globalThis;
@@ -2580,7 +3406,10 @@ var __exports__ = (() => {
2580
3406
  loaders = loaders || [];
2581
3407
  loaders = Array.isArray(loaders) ? loaders : [loaders];
2582
3408
  validateOptions(options, loaders);
2583
- return normalizeLoaderOptions(normalizeOptionsInternal(loader, options, url));
3409
+ validateWorkerThreshold(options);
3410
+ const normalizedOptions = normalizeLoaderOptions(normalizeOptionsInternal(loader, options, url));
3411
+ validateWorkerThreshold(normalizedOptions);
3412
+ return normalizedOptions;
2584
3413
  }
2585
3414
  function normalizeLoaderOptions(options) {
2586
3415
  const normalized = cloneLoaderOptions(options);
@@ -2604,6 +3433,12 @@ var __exports__ = (() => {
2604
3433
  validateOptionsObject(idOptions, loader.id, loaderOptions, deprecatedOptions, loaders);
2605
3434
  }
2606
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
+ }
2607
3442
  function validateOptionsObject(options, id, defaultOptions, deprecatedOptions, loaders) {
2608
3443
  const loaderName = id || "Top level";
2609
3444
  const prefix = id ? `${id}.` : "";
@@ -2659,10 +3494,34 @@ var __exports__ = (() => {
2659
3494
  mergeNestedFields(mergedOptions, normalizeLoaderOptions(getGlobalLoaderOptions()));
2660
3495
  const userOptions = normalizeLoaderOptions(options);
2661
3496
  mergeNestedFields(mergedOptions, userOptions);
3497
+ applyCoreShapeDefault(mergedOptions, userOptions, loader);
2662
3498
  addUrlOptions(mergedOptions, url);
2663
3499
  addDeprecatedTopLevelOptions(mergedOptions);
2664
3500
  return mergedOptions;
2665
3501
  }
3502
+ function applyCoreShapeDefault(mergedOptions, userOptions, loader) {
3503
+ const coreShape = mergedOptions.core?.shape;
3504
+ if (coreShape === void 0) {
3505
+ return;
3506
+ }
3507
+ const loaderScopedDefaults = loader.options?.[loader.id];
3508
+ if (!isPureObject(loaderScopedDefaults) || !("shape" in loaderScopedDefaults)) {
3509
+ return;
3510
+ }
3511
+ const globalLoaderScopedOptions = getGlobalLoaderOptions()[loader.id];
3512
+ if (isPureObject(globalLoaderScopedOptions) && "shape" in globalLoaderScopedOptions) {
3513
+ return;
3514
+ }
3515
+ const userLoaderScopedOptions = userOptions[loader.id];
3516
+ if (isPureObject(userLoaderScopedOptions) && "shape" in userLoaderScopedOptions) {
3517
+ return;
3518
+ }
3519
+ const loaderScopedOptions = mergedOptions[loader.id];
3520
+ mergedOptions[loader.id] = {
3521
+ ...isPureObject(loaderScopedOptions) ? loaderScopedOptions : {},
3522
+ shape: coreShape
3523
+ };
3524
+ }
2666
3525
  function mergeNestedFields(mergedOptions, options) {
2667
3526
  for (const key in options) {
2668
3527
  if (key in options) {
@@ -2704,7 +3563,8 @@ var __exports__ = (() => {
2704
3563
  }
2705
3564
  for (const key of CORE_LOADER_OPTION_KEYS) {
2706
3565
  if (options[key] !== void 0) {
2707
- const coreOptions = options.core = options.core || {};
3566
+ options.core ||= {};
3567
+ const coreOptions = options.core;
2708
3568
  const coreRecord = coreOptions;
2709
3569
  if (coreRecord[key] === void 0) {
2710
3570
  coreRecord[key] = options[key];
@@ -2864,16 +3724,27 @@ var __exports__ = (() => {
2864
3724
  const testUrl = stripQueryString(url) || context?.url;
2865
3725
  let loader = null;
2866
3726
  let reason = "";
3727
+ const sourceType = options?.core && "type" in options.core ? options.core.type : void 0;
3728
+ if (sourceType && sourceType !== "auto") {
3729
+ loader = findSourceLoaderByType(loaders, sourceType);
3730
+ reason = loader ? `match forced by supplied source type ${sourceType}` : "";
3731
+ }
2867
3732
  if (options?.core?.mimeType) {
2868
3733
  loader = findLoaderByMIMEType(loaders, options?.core?.mimeType);
2869
3734
  reason = `match forced by supplied MIME type ${options?.core?.mimeType}`;
2870
3735
  }
3736
+ loader = loader || findSourceLoaderByTestURL(loaders, testUrl);
3737
+ reason = reason || (loader ? `matched source url ${testUrl}` : "");
2871
3738
  loader = loader || findLoaderByUrl(loaders, testUrl);
2872
3739
  reason = reason || (loader ? `matched url ${testUrl}` : "");
2873
3740
  loader = loader || findLoaderByMIMEType(loaders, type);
2874
3741
  reason = reason || (loader ? `matched MIME type ${type}` : "");
2875
3742
  loader = loader || findLoaderByInitialBytes(loaders, data);
2876
3743
  reason = reason || (loader ? `matched initial data ${getFirstCharacters(data)}` : "");
3744
+ if (!loader && isBlob(data)) {
3745
+ loader = findSourceLoaderByTestData(loaders, data);
3746
+ reason = reason || (loader ? "matched source testData" : "");
3747
+ }
2877
3748
  if (options?.core?.fallbackMimeType) {
2878
3749
  loader = loader || findLoaderByMIMEType(loaders, options?.core?.fallbackMimeType);
2879
3750
  reason = reason || (loader ? `matched fallback MIME type ${type}` : "");
@@ -2923,6 +3794,35 @@ var __exports__ = (() => {
2923
3794
  }
2924
3795
  return null;
2925
3796
  }
3797
+ function findSourceLoaderByType(loaders, type) {
3798
+ for (const loader of loaders) {
3799
+ if (isSourceLoader(loader) && loader.type === type) {
3800
+ return loader;
3801
+ }
3802
+ }
3803
+ return null;
3804
+ }
3805
+ function findSourceLoaderByTestURL(loaders, url) {
3806
+ if (!url) {
3807
+ return null;
3808
+ }
3809
+ for (const loader of loaders) {
3810
+ if (isSourceLoader(loader) && loader.testURL(url)) {
3811
+ return loader;
3812
+ }
3813
+ }
3814
+ return null;
3815
+ }
3816
+ function findSourceLoaderByTestData(loaders, data) {
3817
+ for (const loader of loaders) {
3818
+ if (isSourceLoader(loader)) {
3819
+ if (loader.testData?.(data)) {
3820
+ return loader;
3821
+ }
3822
+ }
3823
+ }
3824
+ return null;
3825
+ }
2926
3826
  function findLoaderByMIMEType(loaders, mimeType) {
2927
3827
  for (const loader of loaders) {
2928
3828
  if (loader.mimeTypes?.some((mimeType1) => compareMIMETypes(mimeType, mimeType1))) {
@@ -3054,20 +3954,57 @@ var __exports__ = (() => {
3054
3954
  async function* makeBrowserStreamIterator(stream, options) {
3055
3955
  const reader = stream.getReader();
3056
3956
  let nextBatchPromise;
3957
+ let streamFinished = false;
3958
+ let streamReadFailed = false;
3959
+ let iteratorFailed = false;
3057
3960
  try {
3058
3961
  while (true) {
3059
3962
  const currentBatchPromise = nextBatchPromise || reader.read();
3060
- if (options?._streamReadAhead) {
3061
- 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;
3062
3970
  }
3063
- const { done, value } = await currentBatchPromise;
3971
+ const { done, value } = batch;
3064
3972
  if (done) {
3973
+ streamFinished = true;
3065
3974
  return;
3066
3975
  }
3976
+ if (options?._streamReadAhead) {
3977
+ nextBatchPromise = reader.read();
3978
+ void nextBatchPromise.catch(() => {
3979
+ });
3980
+ }
3067
3981
  yield toArrayBuffer2(value);
3068
3982
  }
3069
3983
  } catch (error) {
3070
- reader.releaseLock();
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
+ }
3071
4008
  }
3072
4009
  }
3073
4010
  async function* makeNodeStreamIterator(stream, options) {
@@ -3138,6 +4075,28 @@ var __exports__ = (() => {
3138
4075
  }
3139
4076
  throw new Error(ERR_DATA);
3140
4077
  }
4078
+ async function getArrayBufferFromData(data, options) {
4079
+ if (typeof data === "string") {
4080
+ return new TextEncoder().encode(data).buffer;
4081
+ }
4082
+ if (isArrayBufferLike(data)) {
4083
+ return toArrayBuffer2(toArrayBufferView(data));
4084
+ }
4085
+ if (isBlob(data)) {
4086
+ data = await makeResponse(data);
4087
+ }
4088
+ if (isResponse(data)) {
4089
+ await checkResponse(data);
4090
+ return await data.arrayBuffer();
4091
+ }
4092
+ if (isReadableStream(data)) {
4093
+ data = makeIterator(data, options);
4094
+ }
4095
+ if (isIterable(data) || isAsyncIterable(data)) {
4096
+ return concatenateArrayBuffersAsync(data);
4097
+ }
4098
+ throw new Error(ERR_DATA);
4099
+ }
3141
4100
  async function getAsyncIterableFromData(data, options) {
3142
4101
  if (isPromise(data)) {
3143
4102
  data = await data;
@@ -3166,14 +4125,14 @@ var __exports__ = (() => {
3166
4125
  }
3167
4126
  function getIterableFromData(data) {
3168
4127
  if (ArrayBuffer.isView(data)) {
3169
- return function* oneChunk() {
4128
+ return (function* oneChunk() {
3170
4129
  yield toArrayBuffer2(data);
3171
- }();
4130
+ })();
3172
4131
  }
3173
4132
  if (isArrayBufferLike(data)) {
3174
- return function* oneChunk() {
4133
+ return (function* oneChunk() {
3175
4134
  yield toArrayBuffer2(data);
3176
- }();
4135
+ })();
3177
4136
  }
3178
4137
  if (isIterator(data)) {
3179
4138
  return data;
@@ -3189,103 +4148,287 @@ var __exports__ = (() => {
3189
4148
  const globalOptions = getGlobalLoaderOptions();
3190
4149
  const loaderOptions = options || globalOptions;
3191
4150
  const fetchOption = loaderOptions.fetch ?? loaderOptions.core?.fetch;
4151
+ let fetchFunction;
3192
4152
  if (typeof fetchOption === "function") {
3193
- return fetchOption;
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;
3194
4160
  }
3195
- if (isObject(fetchOption)) {
3196
- return (url) => fetchFile(url, fetchOption);
4161
+ return createAuthenticatedFetch({
4162
+ fetch: fetchFunction,
4163
+ credentials: loaderOptions.core?.credentials || [],
4164
+ authentications: loaderOptions.core?.authentications,
4165
+ fetchOptions: isObject(fetchOption) ? fetchOption : void 0
4166
+ });
4167
+ }
4168
+
4169
+ // src/lib/api/load-loader.ts
4170
+ var loaderImplementationPromises = /* @__PURE__ */ new Map();
4171
+ var loaderImplementations = /* @__PURE__ */ new Map();
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;
3197
4181
  }
3198
- if (context?.fetch) {
3199
- return context?.fetch;
4182
+ if (isLoaderWithParser(loader)) {
4183
+ return loader;
4184
+ }
4185
+ const implementationCacheKey = getLoaderImplementationCacheKey(loader, options);
4186
+ const loaderImplementation = loaderImplementations.get(loader)?.get(implementationCacheKey);
4187
+ if (loaderImplementation) {
4188
+ return loaderImplementation;
4189
+ }
4190
+ let loaderImplementationPromisesForLoader = loaderImplementationPromises.get(loader);
4191
+ if (!loaderImplementationPromisesForLoader) {
4192
+ loaderImplementationPromisesForLoader = /* @__PURE__ */ new Map();
4193
+ loaderImplementationPromises.set(loader, loaderImplementationPromisesForLoader);
4194
+ }
4195
+ let loaderImplementationPromise = loaderImplementationPromisesForLoader.get(implementationCacheKey);
4196
+ if (!loaderImplementationPromise) {
4197
+ loaderImplementationPromise = resolveLoaderImplementation(loader, options, url).then((implementation) => {
4198
+ let loaderImplementationsForLoader = loaderImplementations.get(loader);
4199
+ if (!loaderImplementationsForLoader) {
4200
+ loaderImplementationsForLoader = /* @__PURE__ */ new Map();
4201
+ loaderImplementations.set(loader, loaderImplementationsForLoader);
4202
+ }
4203
+ loaderImplementationsForLoader.set(implementationCacheKey, implementation);
4204
+ return implementation;
4205
+ }).catch((error) => {
4206
+ loaderImplementationPromisesForLoader.delete(implementationCacheKey);
4207
+ if (loaderImplementationPromisesForLoader.size === 0) {
4208
+ loaderImplementationPromises.delete(loader);
4209
+ }
4210
+ throw error;
4211
+ });
4212
+ loaderImplementationPromisesForLoader.set(implementationCacheKey, loaderImplementationPromise);
3200
4213
  }
3201
- return fetchFile;
4214
+ return await loaderImplementationPromise;
3202
4215
  }
3203
-
3204
- // src/lib/loader-utils/loader-context.ts
3205
- function getLoaderContext(context, options, parentContext) {
3206
- if (parentContext) {
3207
- return parentContext;
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;
3208
4221
  }
3209
- const newContext = {
3210
- fetch: getFetchFunction(options, context),
3211
- ...context
3212
- };
3213
- if (newContext.url) {
3214
- const baseUrl = stripQueryString(newContext.url);
3215
- newContext.baseUrl = baseUrl;
3216
- newContext.queryString = extractQueryString(newContext.url);
3217
- newContext.filename = path_exports.filename(baseUrl);
3218
- newContext.baseUrl = path_exports.dirname(baseUrl);
4222
+ if (isLoaderWithParser(loader)) {
4223
+ return loader;
3219
4224
  }
3220
- if (!Array.isArray(newContext.loaders)) {
3221
- newContext.loaders = null;
4225
+ const implementationCacheKey = getLoaderImplementationCacheKey(loader);
4226
+ return loaderImplementations.get(loader)?.get(implementationCacheKey) || null;
4227
+ }
4228
+ function isLoaderWithParser(loader) {
4229
+ const candidate = loader;
4230
+ return Boolean(
4231
+ candidate.parse || candidate.parseSync || candidate.parseInBatches || candidate.parseText || candidate.parseTextSync || candidate.parseFile || candidate.parseFileInBatches
4232
+ );
4233
+ }
4234
+ async function resolveLoaderImplementation(loader, options, url) {
4235
+ if (loader.preload) {
4236
+ const preloadedLoader = await loader.preload(url || "", options);
4237
+ if (isLoaderWithParser(preloadedLoader)) {
4238
+ return preloadedLoader;
4239
+ }
4240
+ throw new Error(`${loader.id} loader preload() did not return a parser-bearing loader`);
3222
4241
  }
3223
- return newContext;
4242
+ const implementationSpecifier = getLoaderImplementationSpecifier(loader, options);
4243
+ return await importLoaderImplementation(implementationSpecifier, loader.id);
3224
4244
  }
3225
- function getLoadersFromContext(loaders, context) {
3226
- if (loaders && !Array.isArray(loaders)) {
3227
- return loaders;
4245
+ function getLoaderImplementationSpecifier(loader, options) {
4246
+ const workerType = options?._workerType || options?.core?._workerType;
4247
+ if (workerType === "test") {
4248
+ const sourcePath = `modules/${loader.module}/src/${loader.id}-loader.ts`;
4249
+ if (typeof window !== "undefined") {
4250
+ return `/${sourcePath}`;
4251
+ }
4252
+ if (typeof process !== "undefined" && process.cwd) {
4253
+ return new URL(sourcePath, `file://${process.cwd()}/`).toString();
4254
+ }
4255
+ return sourcePath;
3228
4256
  }
3229
- let candidateLoaders;
3230
- if (loaders) {
3231
- candidateLoaders = Array.isArray(loaders) ? loaders : [loaders];
4257
+ throw new Error(
4258
+ `${loader.id} loader does not provide a parser implementation. Import a parser-bearing loader directly, or use preload() before parse/load.`
4259
+ );
4260
+ }
4261
+ function getLoaderImplementationCacheKey(loader, options) {
4262
+ const loaderOptions = options?.[loader.id];
4263
+ const defaultLoaderOptions = loader.options?.[loader.id];
4264
+ return String(loaderOptions?.backend || defaultLoaderOptions?.backend || "");
4265
+ }
4266
+ async function importLoaderImplementation(implementationSpecifier, loaderId) {
4267
+ const moduleExports = await import(
4268
+ /* webpackIgnore: true */
4269
+ /* @vite-ignore */
4270
+ implementationSpecifier
4271
+ );
4272
+ for (const exportValue of Object.values(moduleExports)) {
4273
+ if (exportValue && typeof exportValue === "object" && exportValue.id === loaderId && isLoaderWithParser(exportValue)) {
4274
+ return exportValue;
4275
+ }
3232
4276
  }
3233
- if (context && context.loaders) {
3234
- const contextLoaders = Array.isArray(context.loaders) ? context.loaders : [context.loaders];
3235
- candidateLoaders = candidateLoaders ? [...candidateLoaders, ...contextLoaders] : contextLoaders;
4277
+ throw new Error(
4278
+ `Could not find parser implementation for ${loaderId} in ${implementationSpecifier}`
4279
+ );
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
+ }
3236
4323
  }
3237
- return candidateLoaders && candidateLoaders.length ? candidateLoaders : void 0;
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;
3238
4378
  }
3239
4379
 
3240
- // src/lib/api/parse.ts
3241
- async function parse(data, loaders, options, context) {
4380
+ // src/lib/api/parse-file.ts
4381
+ async function parseFile(file, loaders, options, context) {
3242
4382
  if (loaders && !Array.isArray(loaders) && !isLoaderObject(loaders)) {
3243
4383
  context = void 0;
3244
4384
  options = loaders;
3245
4385
  loaders = void 0;
3246
4386
  }
3247
- data = await data;
3248
4387
  options = options || {};
3249
- const url = getResourceUrl(data);
4388
+ const url = file.url || "";
3250
4389
  const typedLoaders = loaders;
3251
4390
  const candidateLoaders = getLoadersFromContext(typedLoaders, context);
3252
- const loader = await selectLoader(data, candidateLoaders, options);
4391
+ const loader = await selectLoader(url, candidateLoaders, options);
3253
4392
  if (!loader) {
3254
4393
  return null;
3255
4394
  }
3256
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4395
+ if (isSourceLoader(loader)) {
4396
+ throw new Error(
4397
+ `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parseFile().`
4398
+ );
4399
+ }
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
+ );
3257
4407
  context = getLoaderContext(
3258
- // @ts-expect-error
4408
+ // @ts-expect-error candidateLoaders may be a single forced loader
3259
4409
  { url, _parse: parse, loaders: candidateLoaders },
3260
4410
  strictOptions,
3261
4411
  context || null
3262
4412
  );
3263
- return await parseWithLoader(loader, data, strictOptions, context);
4413
+ return await parseFileWithLoader(loader, file, strictOptions, context);
3264
4414
  }
3265
- async function parseWithLoader(loader, data, options, context) {
4415
+ async function parseFileWithLoader(loader, file, options, context) {
3266
4416
  validateWorkerVersion(loader);
3267
4417
  options = mergeOptions(loader.options, options);
3268
- if (isResponse(data)) {
3269
- const { ok, redirected, status, statusText, type, url } = data;
3270
- const headers = Object.fromEntries(data.headers.entries());
3271
- context.response = { headers, ok, redirected, status, statusText, type, url };
3272
- }
3273
- data = await getArrayBufferOrStringFromData(data, loader, options);
3274
- const loaderWithParser = loader;
3275
- if (loaderWithParser.parseTextSync && typeof data === "string") {
3276
- return loaderWithParser.parseTextSync(data, options, context);
3277
- }
3278
- if (canParseWithWorker(loader, options)) {
3279
- return await parseWithWorker(loader, data, options, context, parse);
3280
- }
3281
- if (loaderWithParser.parseText && typeof data === "string") {
3282
- return await loaderWithParser.parseText(data, options, context);
3283
- }
3284
- if (loaderWithParser.parse) {
3285
- return await loaderWithParser.parse(data, options, context);
4418
+ const loaderWithParser = await getLoaderImplementation(loader, options, context.url);
4419
+ if (loaderWithParser.parseFile) {
4420
+ return await loaderWithParser.parseFile(file, options, context);
4421
+ }
4422
+ const parseFunction = loaderWithParser.parse;
4423
+ if (parseFunction) {
4424
+ const length = file.bigsize > 0n ? Number(file.bigsize) : file.size;
4425
+ if (!length) {
4426
+ throw new Error(`${loader.id} loader - cannot fall back to parse without a file size`);
4427
+ }
4428
+ const data = await file.read(0n, length);
4429
+ return await parse(data, loaderWithParser, options, context);
3286
4430
  }
3287
- assert3(!loaderWithParser.parseSync);
3288
- throw new Error(`${loader.id} loader - no parser found and worker is disabled`);
4431
+ throw new Error(`${loader.id} loader - no file parser found`);
3289
4432
  }
3290
4433
 
3291
4434
  // src/lib/api/parse-sync.ts
@@ -3302,6 +4445,11 @@ var __exports__ = (() => {
3302
4445
  if (!loader) {
3303
4446
  return null;
3304
4447
  }
4448
+ if (isSourceLoader(loader)) {
4449
+ throw new Error(
4450
+ `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parseSync().`
4451
+ );
4452
+ }
3305
4453
  const strictOptions = normalizeOptions(options, loader, candidateLoaders);
3306
4454
  const url = getResourceUrl(data);
3307
4455
  const parse2 = () => {
@@ -3312,7 +4460,13 @@ var __exports__ = (() => {
3312
4460
  strictOptions,
3313
4461
  context || null
3314
4462
  );
3315
- return parseWithLoaderSync(loader, data, strictOptions, context);
4463
+ const loaderWithParser = getLoaderImplementationSync(loader);
4464
+ return parseWithLoaderSync(
4465
+ loaderWithParser || loader,
4466
+ data,
4467
+ strictOptions,
4468
+ context
4469
+ );
3316
4470
  }
3317
4471
  function parseWithLoaderSync(loader, data, options, context) {
3318
4472
  data = getArrayBufferOrStringFromDataSync(data, loader, options);
@@ -3322,6 +4476,11 @@ var __exports__ = (() => {
3322
4476
  if (loader.parseSync && data instanceof ArrayBuffer) {
3323
4477
  return loader.parseSync(data, options, context);
3324
4478
  }
4479
+ if (loader.preload) {
4480
+ throw new Error(
4481
+ `${loader.name} loader: 'parseSync' requires a parser-bearing loader. Import the loader implementation directly, or call preload(loader) before parseSync(). ${context.url || ""}`
4482
+ );
4483
+ }
3325
4484
  throw new Error(
3326
4485
  `${loader.name} loader: 'parseSync' not supported by this loader, use 'parse' instead. ${context.url || ""}`
3327
4486
  );
@@ -3337,7 +4496,7 @@ var __exports__ = (() => {
3337
4496
  case "geojson-table":
3338
4497
  return Array.isArray(table.features);
3339
4498
  case "columnar-table":
3340
- return table.data && typeof table.data === "object";
4499
+ return Boolean(table.data && typeof table.data === "object");
3341
4500
  case "arrow-table":
3342
4501
  return Boolean(table?.data?.numRows !== void 0);
3343
4502
  default:
@@ -3384,15 +4543,22 @@ var __exports__ = (() => {
3384
4543
  if (!loader) {
3385
4544
  return [];
3386
4545
  }
3387
- 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
+ );
3388
4553
  context = getLoaderContext(
3389
4554
  { url, _parseInBatches: parseInBatches, _parse: parse, loaders: loaderArray },
3390
4555
  strictOptions,
3391
4556
  context || null
3392
4557
  );
3393
- return await parseWithLoaderInBatches(loader, data, strictOptions, context);
4558
+ const loaderWithParser = await getLoaderImplementation(loader, strictOptions, context.url);
4559
+ return await parseWithLoaderInBatches(loader, loaderWithParser, data, strictOptions, context);
3394
4560
  }
3395
- async function parseWithLoaderInBatches(loader, data, options, context) {
4561
+ async function parseWithLoaderInBatches(originalLoader, loader, data, options, context) {
3396
4562
  const outputIterator = await parseToOutputIterator(loader, data, options, context);
3397
4563
  if (!options?.core?.metadata) {
3398
4564
  return outputIterator;
@@ -3401,7 +4567,7 @@ var __exports__ = (() => {
3401
4567
  shape: "metadata",
3402
4568
  batchType: "metadata",
3403
4569
  metadata: {
3404
- _loader: loader,
4570
+ _loader: originalLoader,
3405
4571
  _context: context
3406
4572
  },
3407
4573
  // Populate with some default fields to avoid crashing
@@ -3421,6 +4587,9 @@ var __exports__ = (() => {
3421
4587
  options?.core?.transforms || []
3422
4588
  );
3423
4589
  if (loader.parseInBatches) {
4590
+ if (loader.id === "csv" && isBrowser && canParseWithWorker(loader, options)) {
4591
+ return parseWithWorkerInBatches(loader, transformedIterator, options, context, parse);
4592
+ }
3424
4593
  return loader.parseInBatches(transformedIterator, options, context);
3425
4594
  }
3426
4595
  return parseChunkInBatches(transformedIterator, loader, options, context);
@@ -3455,6 +4624,38 @@ var __exports__ = (() => {
3455
4624
  return iteratorChain;
3456
4625
  }
3457
4626
 
4627
+ // src/lib/api/load-in-batches.ts
4628
+ function loadInBatches(files, loaders, options, context) {
4629
+ let loadersArray;
4630
+ if (!Array.isArray(loaders) && !isLoaderObject(loaders)) {
4631
+ context = void 0;
4632
+ options = loaders;
4633
+ loadersArray = void 0;
4634
+ } else {
4635
+ loadersArray = loaders;
4636
+ }
4637
+ if (!Array.isArray(files)) {
4638
+ return loadOneFileInBatches(files, loadersArray, options || {});
4639
+ }
4640
+ const promises = files.map((file) => loadOneFileInBatches(file, loadersArray, options || {}));
4641
+ return promises;
4642
+ }
4643
+ async function loadOneFileInBatches(file, loaders, options) {
4644
+ if (typeof file === "string") {
4645
+ const url = file;
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));
4654
+ return Array.isArray(loaders) ? await parseInBatches(response, loaders, options) : await parseInBatches(response, loaders, options);
4655
+ }
4656
+ return Array.isArray(loaders) ? await parseInBatches(file, loaders, options) : await parseInBatches(file, loaders, options);
4657
+ }
4658
+
3458
4659
  // src/lib/api/load.ts
3459
4660
  async function load(url, loaders, options, context) {
3460
4661
  let resolvedLoaders;
@@ -3467,10 +4668,100 @@ var __exports__ = (() => {
3467
4668
  resolvedLoaders = loaders;
3468
4669
  resolvedOptions = options;
3469
4670
  }
4671
+ resolvedOptions ||= getGlobalLoaderOptions();
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
+ );
4679
+ const runtimeCoreApi = {
4680
+ fetchFile,
4681
+ parse,
4682
+ parseFile,
4683
+ parseSync,
4684
+ parseInBatches,
4685
+ load,
4686
+ loadInBatches
4687
+ };
4688
+ return sourceLoader.createDataSource(
4689
+ url,
4690
+ resolvedOptions || {},
4691
+ runtimeCoreApi
4692
+ );
4693
+ }
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
+ );
4701
+ const runtimeCoreApi = {
4702
+ fetchFile,
4703
+ parse,
4704
+ parseFile,
4705
+ parseSync,
4706
+ parseInBatches,
4707
+ load,
4708
+ loadInBatches
4709
+ };
4710
+ return sourceLoader.createDataSource(
4711
+ url,
4712
+ resolvedOptions || {},
4713
+ runtimeCoreApi
4714
+ );
4715
+ }
4716
+ if (typeof url === "string" || isBlob(url)) {
4717
+ const selectedLoader = await selectLoader(url, resolvedLoaders, {
4718
+ ...resolvedOptions,
4719
+ core: { ...resolvedOptions?.core, nothrow: true }
4720
+ });
4721
+ if (selectedLoader && isSourceLoader(selectedLoader)) {
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(
4729
+ url,
4730
+ resolvedOptions || {},
4731
+ {
4732
+ fetchFile,
4733
+ parse,
4734
+ parseFile,
4735
+ parseSync,
4736
+ parseInBatches,
4737
+ load,
4738
+ loadInBatches
4739
+ }
4740
+ );
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
+ }
4759
+ }
4760
+ if (resolvedOptions) resolvedOptions = resolveAuthenticationOptions(resolvedOptions);
3470
4761
  const fetch2 = getFetchFunction(resolvedOptions);
3471
4762
  let data = url;
3472
4763
  if (typeof url === "string") {
3473
- data = await fetch2(url);
4764
+ data = await fetch2(applySearchParamsToUrl(url, resolvedOptions));
3474
4765
  }
3475
4766
  if (isBlob(url)) {
3476
4767
  data = await fetch2(url);
@@ -3487,35 +4778,151 @@ var __exports__ = (() => {
3487
4778
  };
3488
4779
  }
3489
4780
  }
3490
- return Array.isArray(resolvedLoaders) ? await parse(data, resolvedLoaders, resolvedOptions) : await parse(data, resolvedLoaders, resolvedOptions);
4781
+ return Array.isArray(resolvedLoaders) ? await parse(data, resolvedLoaders, resolvedOptions, context) : await parse(data, resolvedLoaders, resolvedOptions, context);
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;
3491
4792
  }
3492
4793
 
3493
- // src/lib/api/load-in-batches.ts
3494
- function loadInBatches(files, loaders, options, context) {
3495
- let loadersArray;
3496
- if (!Array.isArray(loaders) && !isLoaderObject(loaders)) {
4794
+ // src/lib/api/core-api.ts
4795
+ var coreApi = Object.freeze({
4796
+ fetchFile,
4797
+ parse,
4798
+ parseFile,
4799
+ parseSync,
4800
+ parseInBatches,
4801
+ load,
4802
+ loadInBatches
4803
+ });
4804
+
4805
+ // src/lib/loader-utils/loader-context.ts
4806
+ function getLoaderContext(context, options, parentContext) {
4807
+ if (parentContext) {
4808
+ return {
4809
+ ...parentContext,
4810
+ coreApi: parentContext.coreApi || context.coreApi || coreApi,
4811
+ _parse: parentContext._parse || context._parse,
4812
+ fetch: getFetchFunction(options, parentContext)
4813
+ };
4814
+ }
4815
+ const newContext = {
4816
+ ...context,
4817
+ fetch: getFetchFunction(options, context),
4818
+ coreApi: context.coreApi || coreApi
4819
+ };
4820
+ if (newContext.url) {
4821
+ const baseUrl = stripQueryString(newContext.url);
4822
+ newContext.baseUrl = baseUrl;
4823
+ newContext.queryString = extractQueryString(newContext.url);
4824
+ newContext.filename = path_exports.filename(baseUrl);
4825
+ newContext.baseUrl = path_exports.dirname(baseUrl);
4826
+ }
4827
+ if (!Array.isArray(newContext.loaders)) {
4828
+ newContext.loaders = null;
4829
+ }
4830
+ return newContext;
4831
+ }
4832
+ function getLoadersFromContext(loaders, context) {
4833
+ if (loaders && !Array.isArray(loaders)) {
4834
+ return loaders;
4835
+ }
4836
+ let candidateLoaders;
4837
+ if (loaders) {
4838
+ candidateLoaders = Array.isArray(loaders) ? loaders : [loaders];
4839
+ }
4840
+ if (context && context.loaders) {
4841
+ const contextLoaders = Array.isArray(context.loaders) ? context.loaders : [context.loaders];
4842
+ candidateLoaders = candidateLoaders ? [...candidateLoaders, ...contextLoaders] : contextLoaders;
4843
+ }
4844
+ return candidateLoaders && candidateLoaders.length ? candidateLoaders : void 0;
4845
+ }
4846
+
4847
+ // src/lib/api/parse.ts
4848
+ async function parse(data, loaders, options, context) {
4849
+ if (loaders && !Array.isArray(loaders) && !isLoaderObject(loaders)) {
3497
4850
  context = void 0;
3498
4851
  options = loaders;
3499
- loadersArray = void 0;
3500
- } else {
3501
- loadersArray = loaders;
4852
+ loaders = void 0;
3502
4853
  }
3503
- const fetch2 = getFetchFunction(options || {});
3504
- if (!Array.isArray(files)) {
3505
- return loadOneFileInBatches(files, loadersArray, options || {}, fetch2);
4854
+ data = await data;
4855
+ options = options || {};
4856
+ const url = getResourceUrl(data);
4857
+ const typedLoaders = loaders;
4858
+ const candidateLoaders = getLoadersFromContext(typedLoaders, context);
4859
+ const loader = await selectLoader(data, candidateLoaders, options);
4860
+ if (!loader) {
4861
+ return null;
4862
+ }
4863
+ if (isSourceLoader(loader)) {
4864
+ throw new Error(
4865
+ `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parse().`
4866
+ );
3506
4867
  }
3507
- const promises = files.map(
3508
- (file) => loadOneFileInBatches(file, loadersArray, options || {}, fetch2)
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
3509
4874
  );
3510
- return promises;
4875
+ context = getLoaderContext(
4876
+ // @ts-expect-error
4877
+ { url, _parse: parse, loaders: candidateLoaders },
4878
+ strictOptions,
4879
+ context || null
4880
+ );
4881
+ return await parseWithLoader(loader, data, strictOptions, context);
3511
4882
  }
3512
- async function loadOneFileInBatches(file, loaders, options, fetch2) {
3513
- if (typeof file === "string") {
3514
- const url = file;
3515
- const response = await fetch2(url);
3516
- return Array.isArray(loaders) ? await parseInBatches(response, loaders, options) : await parseInBatches(response, loaders, options);
4883
+ async function parseWithLoader(loader, data, options, context) {
4884
+ validateWorkerVersion(loader);
4885
+ options = mergeOptions(loader.options, options);
4886
+ if (isResponse(data)) {
4887
+ const { ok, redirected, status, statusText, type, url } = data;
4888
+ const headers = Object.fromEntries(data.headers.entries());
4889
+ context.response = { headers, ok, redirected, status, statusText, type, url };
3517
4890
  }
3518
- return Array.isArray(loaders) ? await parseInBatches(file, loaders, options) : await parseInBatches(file, loaders, options);
4891
+ const loaderWithParser = await getLoaderImplementation(loader, options, context.url);
4892
+ if (shouldParseWithWorker(loaderWithParser, data, options, context, loader)) {
4893
+ data = await getArrayBufferFromData(data, options);
4894
+ return await parseWithWorker(loaderWithParser, data, options, context, parse);
4895
+ }
4896
+ if (isBlob(data) && loaderWithParser.parseBlob) {
4897
+ return await loaderWithParser.parseBlob(data, options, context);
4898
+ }
4899
+ data = await getArrayBufferOrStringFromData(data, loader, options);
4900
+ return await parseWithLoaderImplementation(loaderWithParser, data, options, context);
4901
+ }
4902
+ async function parseWithLoaderImplementation(loader, data, options, context) {
4903
+ if (loader.parseText && typeof data === "string") {
4904
+ return await loader.parseText(data, options, context);
4905
+ }
4906
+ if (loader.parseTextSync && typeof data === "string") {
4907
+ return loader.parseTextSync(data, options, context);
4908
+ }
4909
+ if (loader.parse) {
4910
+ return await loader.parse(data, options, context);
4911
+ }
4912
+ if (loader.parseSync) {
4913
+ throw new Error(
4914
+ `${loader.name} loader: 'parse' not available on parser-bearing sync loader. Add an async 'parse' function to this loader, or call preload(loader) before parseSync(). ${context.url || ""}`
4915
+ );
4916
+ }
4917
+ throw new Error(`${loader.id} loader - no parser found and worker is disabled`);
4918
+ }
4919
+
4920
+ // src/lib/api/preload.ts
4921
+ async function preload(loader, options, url) {
4922
+ return loader.subloaders ? await preloadLoaderDependencies(loader, options, url) : await getLoaderImplementation(loader, options, url);
4923
+ }
4924
+ function preloadSync(loader) {
4925
+ return getLoaderImplementationSync(loader);
3519
4926
  }
3520
4927
 
3521
4928
  // src/lib/api/encode-table.ts
@@ -3640,21 +5047,41 @@ var __exports__ = (() => {
3640
5047
  }
3641
5048
 
3642
5049
  // src/lib/api/create-data-source.ts
3643
- function createDataSource(data, sources, options) {
3644
- const type = options?.core?.type || options.type || "auto";
3645
- const source = type === "auto" ? selectSource(data, sources) : getSourceOfType(type, sources);
5050
+ function createDataSource(data, sources, options = {}) {
5051
+ const resolvedOptions = options || {};
5052
+ const type = resolvedOptions?.core?.type || resolvedOptions.type || "auto";
5053
+ const source = sources.length === 1 ? sources[0] : type === "auto" ? selectLoaderSync(data, sources, {
5054
+ // `createDataSource` supports non-fetch inputs such as in-memory tables.
5055
+ // Selection remains best-effort for those cases.
5056
+ ...resolvedOptions,
5057
+ core: { ...resolvedOptions?.core, type: "auto" }
5058
+ }) : getSourceOfType(type, sources);
3646
5059
  if (!source) {
3647
5060
  throw new Error("Not a valid source type");
3648
5061
  }
3649
- return source.createDataSource(data, options);
3650
- }
3651
- function selectSource(url, sources) {
3652
- for (const service of sources) {
3653
- if (service.testURL && service.testURL(url)) {
3654
- return service;
3655
- }
3656
- }
3657
- return null;
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
+ );
3658
5085
  }
3659
5086
  function getSourceOfType(type, sources) {
3660
5087
  for (const service of sources) {
@@ -3666,15 +5093,11 @@ var __exports__ = (() => {
3666
5093
  }
3667
5094
 
3668
5095
  // src/lib/api/select-source.ts
3669
- function selectSource2(url, sources, options) {
5096
+ function selectSource(url, sources, options) {
3670
5097
  const type = options?.type || "auto";
3671
5098
  let selectedSource = null;
3672
5099
  if (type === "auto") {
3673
- for (const source of sources) {
3674
- if (typeof url === "string" && source.testURL && source.testURL(url)) {
3675
- return source;
3676
- }
3677
- }
5100
+ selectedSource = selectLoaderSync(url, sources, { core: { nothrow: true } });
3678
5101
  } else {
3679
5102
  selectedSource = getSourceOfType2(type, sources);
3680
5103
  }
@@ -3849,18 +5272,29 @@ var __exports__ = (() => {
3849
5272
  if (path.includes("://")) {
3850
5273
  return this._fetch(path, options);
3851
5274
  }
3852
- const file = this.files[path];
5275
+ const file = this._getFile(path, true);
3853
5276
  if (!file) {
3854
5277
  return new Response(path, { status: 400, statusText: "NOT FOUND" });
3855
5278
  }
3856
5279
  const headers = new Headers(options?.headers);
3857
5280
  const range = headers.get("Range");
3858
- const bytes = range && /bytes=($1)-($2)/.exec(range);
5281
+ const bytes = range && /bytes=(\d+)-(\d+)/.exec(range);
3859
5282
  if (bytes) {
3860
5283
  const start = parseInt(bytes[1]);
3861
- const end = parseInt(bytes[2]);
3862
- const data = await file.slice(start, end).arrayBuffer();
3863
- 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
+ });
3864
5298
  Object.defineProperty(response2, "url", { value: path });
3865
5299
  return response2;
3866
5300
  }
@@ -3884,7 +5318,7 @@ var __exports__ = (() => {
3884
5318
  * Return information (size) about files in this file system
3885
5319
  */
3886
5320
  async stat(path, options) {
3887
- const file = this.files[path];
5321
+ const file = this._getFile(path, false);
3888
5322
  if (!file) {
3889
5323
  throw new Error(path);
3890
5324
  }
@@ -3894,19 +5328,22 @@ var __exports__ = (() => {
3894
5328
  * Just removes the file from the list
3895
5329
  */
3896
5330
  async unlink(path) {
3897
- delete this.files[path];
3898
- delete this.lowerCaseFiles[path];
3899
- 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
+ }
3900
5337
  }
3901
5338
  // implements IRandomAccessFileSystem
3902
5339
  // RANDOM ACCESS
3903
5340
  async openReadableFile(pathname, flags) {
3904
- return new BlobFile(this.files[pathname]);
5341
+ return new BlobFile(this._getFile(pathname, true));
3905
5342
  }
3906
5343
  // PRIVATE
3907
5344
  // Supports case independent paths, and file usage tracking
3908
5345
  _getFile(path, used) {
3909
- const file = this.files[path] || this.lowerCaseFiles[path];
5346
+ const file = this.files[path] || this.lowerCaseFiles[path.toLowerCase()];
3910
5347
  if (file && used) {
3911
5348
  this.usedFiles[path] = true;
3912
5349
  }