@loaders.gl/core 5.0.0-alpha.6 → 5.0.0-alpha.8

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 (47) hide show
  1. package/dist/dist.dev.js +313 -51
  2. package/dist/dist.min.js +3 -3
  3. package/dist/index.cjs +297 -58
  4. package/dist/index.cjs.map +3 -3
  5. package/dist/lib/api/create-data-source.d.ts +1 -1
  6. package/dist/lib/api/create-data-source.d.ts.map +1 -1
  7. package/dist/lib/api/create-data-source.js +23 -2
  8. package/dist/lib/api/create-data-source.js.map +1 -1
  9. package/dist/lib/api/load-in-batches.d.ts.map +1 -1
  10. package/dist/lib/api/load-in-batches.js +17 -6
  11. package/dist/lib/api/load-in-batches.js.map +1 -1
  12. package/dist/lib/api/load.d.ts +3 -3
  13. package/dist/lib/api/load.d.ts.map +1 -1
  14. package/dist/lib/api/load.js +14 -5
  15. package/dist/lib/api/load.js.map +1 -1
  16. package/dist/lib/api/parse-file.d.ts.map +1 -1
  17. package/dist/lib/api/parse-file.js +6 -2
  18. package/dist/lib/api/parse-file.js.map +1 -1
  19. package/dist/lib/api/parse-in-batches.d.ts.map +1 -1
  20. package/dist/lib/api/parse-in-batches.js +6 -1
  21. package/dist/lib/api/parse-in-batches.js.map +1 -1
  22. package/dist/lib/api/parse.d.ts.map +1 -1
  23. package/dist/lib/api/parse.js +6 -1
  24. package/dist/lib/api/parse.js.map +1 -1
  25. package/dist/lib/init.js +1 -1
  26. package/dist/lib/loader-utils/get-fetch-function.js +4 -13
  27. package/dist/lib/loader-utils/get-fetch-function.js.map +1 -1
  28. package/dist/lib/loader-utils/option-defaults.d.ts.map +1 -1
  29. package/dist/lib/loader-utils/option-defaults.js +1 -0
  30. package/dist/lib/loader-utils/option-defaults.js.map +1 -1
  31. package/dist/lib/loader-utils/option-utils.d.ts +7 -0
  32. package/dist/lib/loader-utils/option-utils.d.ts.map +1 -1
  33. package/dist/lib/loader-utils/option-utils.js +29 -0
  34. package/dist/lib/loader-utils/option-utils.js.map +1 -1
  35. package/dist/null-loader.js +1 -1
  36. package/dist/null-worker-node.js +1 -1
  37. package/dist/null-worker.js +1 -1
  38. package/package.json +6 -6
  39. package/src/lib/api/create-data-source.ts +31 -2
  40. package/src/lib/api/load-in-batches.ts +18 -11
  41. package/src/lib/api/load.ts +44 -6
  42. package/src/lib/api/parse-file.ts +15 -2
  43. package/src/lib/api/parse-in-batches.ts +11 -1
  44. package/src/lib/api/parse.ts +11 -1
  45. package/src/lib/loader-utils/get-fetch-function.ts +4 -15
  46. package/src/lib/loader-utils/option-defaults.ts +1 -0
  47. package/src/lib/loader-utils/option-utils.ts +34 -0
package/dist/index.cjs CHANGED
@@ -561,6 +561,7 @@ var WorkerPool = class {
561
561
  props = {};
562
562
  jobQueue = [];
563
563
  idleQueue = [];
564
+ activeJobs = /* @__PURE__ */ new Set();
564
565
  count = 0;
565
566
  isDestroyed = false;
566
567
  /** Checks if workers are supported on this platform */
@@ -579,10 +580,14 @@ var WorkerPool = class {
579
580
  this.setProps(props);
580
581
  }
581
582
  /**
582
- * Terminates all workers in the pool
583
+ * Terminates all workers in the pool and aborts active jobs.
584
+ * @param reason Optional error delivered to active jobs.
583
585
  * @note Can free up significant memory
584
586
  */
585
- destroy() {
587
+ destroy(reason = new Error("Worker pool was destroyed")) {
588
+ this.activeJobs.forEach((job) => job.abort(reason));
589
+ const queuedJobs = this.jobQueue.splice(0);
590
+ queuedJobs.forEach((queuedJob) => queuedJob.onReject(reason));
586
591
  this.idleQueue.forEach((worker) => worker.destroy());
587
592
  this.isDestroyed = true;
588
593
  }
@@ -605,8 +610,11 @@ var WorkerPool = class {
605
610
  }
606
611
  }
607
612
  async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
608
- const startPromise = new Promise((onStart) => {
609
- this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart });
613
+ if (this.isDestroyed) {
614
+ return Promise.reject(new Error("Worker pool was destroyed"));
615
+ }
616
+ const startPromise = new Promise((onStart, onReject) => {
617
+ this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart, onReject });
610
618
  return this;
611
619
  });
612
620
  this._startQueuedJob();
@@ -634,6 +642,7 @@ var WorkerPool = class {
634
642
  backlog: this.jobQueue.length
635
643
  });
636
644
  const job = new WorkerJob(queuedJob.name, workerThread);
645
+ this.activeJobs.add(job);
637
646
  workerThread.ref();
638
647
  workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
639
648
  workerThread.onError = (error) => queuedJob.onError(job, error);
@@ -642,6 +651,7 @@ var WorkerPool = class {
642
651
  await job.result;
643
652
  } catch {
644
653
  } finally {
654
+ this.activeJobs.delete(job);
645
655
  this.returnWorkerToQueue(workerThread);
646
656
  }
647
657
  }
@@ -732,12 +742,13 @@ var WorkerFarm = class _WorkerFarm {
732
742
  this.workerPools = /* @__PURE__ */ new Map();
733
743
  }
734
744
  /**
735
- * Terminate all workers in the farm
745
+ * Terminate all workers in the farm and abort active jobs.
746
+ * @param reason Optional error delivered to active jobs.
736
747
  * @note Can free up significant memory
737
748
  */
738
- destroy() {
749
+ destroy(reason) {
739
750
  for (const workerPool of this.workerPools.values()) {
740
- workerPool.destroy();
751
+ workerPool.destroy(reason);
741
752
  }
742
753
  this.workerPools = /* @__PURE__ */ new Map();
743
754
  }
@@ -1170,13 +1181,17 @@ function validateWorkerVersion(worker, coreVersion = VERSION2) {
1170
1181
 
1171
1182
  // ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
1172
1183
  function canParseWithWorker(loader, options) {
1173
- var _a, _b;
1184
+ var _a, _b, _c;
1185
+ if ((_b = (_a = options == null ? void 0 : options.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.some(
1186
+ (credential) => credential.type === "request" || "token" in credential && typeof credential.token === "function"
1187
+ ))
1188
+ return false;
1174
1189
  const workerOptions = getWorkerOptions(options);
1175
1190
  const nodeWorkers = workerOptions._nodeWorkers;
1176
1191
  if (!isBrowser2 && !nodeWorkers) {
1177
1192
  return false;
1178
1193
  }
1179
- if (loader.id === "excel" && ((_a = options == null ? void 0 : options.excel) == null ? void 0 : _a.shape) === "arrow-table" || loader.id === "ply" && ((_b = options == null ? void 0 : options.ply) == null ? void 0 : _b.shape) === "arrow-table") {
1194
+ if (loader.id === "las" && (((_c = options == null ? void 0 : options.las) == null ? void 0 : _c.shape) ?? "arrow-table") === "arrow-table") {
1180
1195
  return false;
1181
1196
  }
1182
1197
  if (loader.id === "csv" && !shouldParseCSVWithWorker(options)) {
@@ -1267,7 +1282,12 @@ function callParseOnMainThread(parseOnMainThread, input, options, context) {
1267
1282
  return parseOnMainThread(input, void 0, options, context);
1268
1283
  }
1269
1284
  function getWorkerOptions(options = {}, loader) {
1270
- const serializedOptions = JSON.parse(JSON.stringify(options));
1285
+ const serializedOptions = JSON.parse(
1286
+ JSON.stringify({
1287
+ ...options,
1288
+ ...options.core ? { core: { ...options.core, authentications: void 0 } } : {}
1289
+ })
1290
+ );
1271
1291
  const workerOptions = {
1272
1292
  ...serializedOptions.core,
1273
1293
  ...serializedOptions
@@ -1476,6 +1496,7 @@ var RequestScheduler = class {
1476
1496
  /** Tracks the number of active requests and prioritizes/cancels queued requests. */
1477
1497
  requestQueue = [];
1478
1498
  requestMap = /* @__PURE__ */ new Map();
1499
+ /** Pending arrival debounce or next-tick refill; only new arrivals replace this timer. */
1479
1500
  updateTimer = null;
1480
1501
  constructor(props = {}) {
1481
1502
  this.props = { ...DEFAULT_PROPS2, ...props };
@@ -1543,20 +1564,27 @@ var RequestScheduler = class {
1543
1564
  isDone = true;
1544
1565
  this.requestMap.delete(handle);
1545
1566
  this.activeRequestCount--;
1546
- this._issueNewRequests();
1567
+ this.scheduleRefill();
1547
1568
  }
1548
1569
  };
1549
1570
  this.activeRequestCount++;
1550
1571
  return resolve2 ? resolve2({ done }) : Promise.resolve({ done });
1551
1572
  }
1552
- /** We check requests asynchronously, to prevent multiple updates */
1573
+ /** Refills freed slots on the next tick while preserving any pending arrival debounce. */
1574
+ scheduleRefill() {
1575
+ if (this.updateTimer !== null) {
1576
+ return;
1577
+ }
1578
+ this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), 0);
1579
+ }
1580
+ /** Restarts the quiet period when a new request enters the queue. */
1553
1581
  _issueNewRequests() {
1554
1582
  if (this.updateTimer !== null) {
1555
1583
  clearTimeout(this.updateTimer);
1556
1584
  }
1557
1585
  this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), this.props.debounceTime);
1558
1586
  }
1559
- /** Refresh all requests */
1587
+ /** Clears timer ownership before updating priorities and dispatching queued requests. */
1560
1588
  _issueNewRequestsAsync() {
1561
1589
  if (this.updateTimer !== null) {
1562
1590
  clearTimeout(this.updateTimer);
@@ -1598,25 +1626,110 @@ var RequestScheduler = class {
1598
1626
  }
1599
1627
  };
1600
1628
 
1629
+ // ../loader-utils/src/lib/request-utils/authentication.ts
1630
+ function resolveCredentials(credentials, authentications = []) {
1631
+ if (credentials.every(isAuthentication)) return credentials;
1632
+ return credentials.map((credential, index) => {
1633
+ if (isAuthentication(credential)) return credential;
1634
+ const AuthenticationClass = authentications.find(
1635
+ (authentication2) => authentication2.type === (credential == null ? void 0 : credential.type)
1636
+ );
1637
+ if (!AuthenticationClass) {
1638
+ throw new Error(`No authentication class registered for credential at index ${index}.`);
1639
+ }
1640
+ let authentication;
1641
+ try {
1642
+ authentication = new AuthenticationClass(credential);
1643
+ } catch {
1644
+ throw new Error(`Invalid authentication configuration at index ${index}.`);
1645
+ }
1646
+ if (!isAuthentication(authentication)) {
1647
+ throw new Error(`Authentication class returned an invalid credential at index ${index}.`);
1648
+ }
1649
+ return authentication;
1650
+ });
1651
+ }
1652
+ function resolveAuthenticationOptions(options) {
1653
+ var _a, _b;
1654
+ if (!((_b = (_a = options.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length)) return options;
1655
+ const credentials = resolveCredentials(options.core.credentials, options.core.authentications);
1656
+ if (credentials === options.core.credentials) return options;
1657
+ return { ...options, core: { ...options.core, credentials } };
1658
+ }
1659
+ async function resolveLoaderAuthenticationOptions(loader, url, options) {
1660
+ var _a, _b, _c, _d;
1661
+ if (!((_b = (_a = options.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length) || options.core.credentials.every(isAuthentication)) {
1662
+ return options;
1663
+ }
1664
+ const contributions = await ((_c = loader == null ? void 0 : loader.getAuthentications) == null ? void 0 : _c.call(loader, url, options));
1665
+ if (!(contributions == null ? void 0 : contributions.length)) return resolveAuthenticationOptions(options);
1666
+ return resolveAuthenticationOptions({
1667
+ ...options,
1668
+ core: {
1669
+ ...options.core,
1670
+ authentications: [...((_d = options.core) == null ? void 0 : _d.authentications) || [], ...contributions]
1671
+ }
1672
+ });
1673
+ }
1674
+ function isAuthentication(credential) {
1675
+ if (!credential || typeof credential !== "object") return false;
1676
+ if (typeof credential.id !== "string" || !Array.isArray(credential.origins)) return false;
1677
+ if (credential.type === "request") return typeof credential.authenticate === "function";
1678
+ return (credential.type === "header" || credential.type === "query-parameter") && typeof credential.name === "string" && (typeof credential.token === "string" || typeof credential.token === "function") && Array.isArray(credential.refreshStatusCodes);
1679
+ }
1680
+
1601
1681
  // ../loader-utils/src/lib/request-utils/request-credentials.ts
1602
1682
  var AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
1603
1683
  var refreshPromises = /* @__PURE__ */ new WeakMap();
1604
1684
  function createAuthenticatedFetch(options) {
1605
- const baseFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
1606
- if (!options.credentials.length) return baseFetch;
1607
- const existingMetadata = baseFetch[AUTHENTICATED_FETCH];
1608
- if (existingMetadata === options.credentials) return baseFetch;
1685
+ const suppliedFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
1686
+ const existingMetadata = suppliedFetch[AUTHENTICATED_FETCH];
1687
+ const credentialResolutions = new Map(existingMetadata == null ? void 0 : existingMetadata.credentialResolutions);
1688
+ const resolvedCredentials = resolveCredentials(
1689
+ options.credentials.map((credential) => credentialResolutions.get(credential) || credential),
1690
+ options.authentications
1691
+ );
1692
+ options.credentials.forEach((credential, index) => {
1693
+ credentialResolutions.set(credential, resolvedCredentials[index]);
1694
+ });
1695
+ if (!options.fetchOptions && (!resolvedCredentials.length || (existingMetadata == null ? void 0 : existingMetadata.credentials.length) === resolvedCredentials.length && resolvedCredentials.every(
1696
+ (credential, index) => credential === existingMetadata.credentials[index]
1697
+ )))
1698
+ return suppliedFetch;
1699
+ const baseFetch = (existingMetadata == null ? void 0 : existingMetadata.fetch) || suppliedFetch;
1700
+ const credentials = existingMetadata ? [.../* @__PURE__ */ new Set([...resolvedCredentials, ...existingMetadata.credentials])] : resolvedCredentials;
1701
+ const fetchOptions = mergeFetchOptions(
1702
+ (existingMetadata == null ? void 0 : existingMetadata.fetchOptions) || {},
1703
+ options.fetchOptions
1704
+ );
1705
+ const tokenCredentials = credentials.filter(
1706
+ (credential) => credential.type !== "request"
1707
+ );
1708
+ const requestCredentials = credentials.filter(
1709
+ (credential) => credential.type === "request"
1710
+ );
1711
+ for (const credential of requestCredentials) normalizeRequestOrigins(credential.origins);
1609
1712
  const authenticatedFetch = async (url, requestOptions = {}) => {
1610
- var _a, _b, _c;
1713
+ var _a, _b, _c, _d;
1714
+ requestOptions = mergeFetchOptions(fetchOptions, requestOptions);
1715
+ if ((_a = requestOptions.signal) == null ? void 0 : _a.aborted) throw createAbortError3();
1716
+ if (!credentials.length) return baseFetch(url, requestOptions);
1611
1717
  const resolvedURL = parseHTTPURL(url);
1612
- if (!resolvedURL) return baseFetch(url, requestOptions);
1613
- const authorization = await authorizeRequest(resolvedURL, requestOptions, options.credentials);
1614
- const response = await baseFetch(authorization.url, authorization.options);
1718
+ const authorization = resolvedURL ? await authorizeRequest(resolvedURL, requestOptions, tokenCredentials) : { url, options: requestOptions, credentials: [] };
1719
+ const signedRequest = await authenticateRequest(authorization, requestCredentials, "request");
1720
+ const response = await baseFetch(signedRequest.url, signedRequest.options);
1615
1721
  const refreshableCredentials = authorization.credentials.filter(
1616
1722
  ({ credential }) => typeof credential.token === "function" && credential.refreshStatusCodes.includes(response.status)
1617
1723
  );
1618
- if (!refreshableCredentials.length || !isReplayableRequest(requestOptions)) return response;
1619
- if ((_a = requestOptions.signal) == null ? void 0 : _a.aborted) throw createAbortError3();
1724
+ const shouldRetrySignature = signedRequest.credentials.some(
1725
+ (credential) => {
1726
+ var _a2;
1727
+ return (_a2 = credential.refreshStatusCodes) == null ? void 0 : _a2.includes(response.status);
1728
+ }
1729
+ );
1730
+ if (!refreshableCredentials.length && !shouldRetrySignature || !isReplayableRequest(requestOptions) || !isReplayableRequest(signedRequest.options))
1731
+ return response;
1732
+ if ((_b = requestOptions.signal) == null ? void 0 : _b.aborted) throw createAbortError3();
1620
1733
  const refreshedTokens = /* @__PURE__ */ new Map();
1621
1734
  await Promise.all(
1622
1735
  refreshableCredentials.map(async ({ credential }) => {
@@ -1624,24 +1737,95 @@ function createAuthenticatedFetch(options) {
1624
1737
  if (token) refreshedTokens.set(credential, token);
1625
1738
  })
1626
1739
  );
1627
- if (!refreshedTokens.size) return response;
1628
- await ((_b = response.body) == null ? void 0 : _b.cancel().catch(() => {
1740
+ if (!refreshedTokens.size && !shouldRetrySignature) return response;
1741
+ await ((_c = response.body) == null ? void 0 : _c.cancel().catch(() => {
1629
1742
  }));
1630
- if ((_c = requestOptions.signal) == null ? void 0 : _c.aborted) throw createAbortError3();
1631
- const replayAuthorization = await authorizeRequest(
1743
+ if ((_d = requestOptions.signal) == null ? void 0 : _d.aborted) throw createAbortError3();
1744
+ const replayAuthorization = resolvedURL ? await authorizeRequest(
1632
1745
  resolvedURL,
1633
1746
  requestOptions,
1634
- options.credentials,
1747
+ tokenCredentials,
1635
1748
  refreshedTokens,
1636
1749
  authorization.credentials
1750
+ ) : { url, options: requestOptions };
1751
+ const replayRequest = await authenticateRequest(
1752
+ replayAuthorization,
1753
+ requestCredentials,
1754
+ "retry",
1755
+ response
1637
1756
  );
1638
- return baseFetch(replayAuthorization.url, replayAuthorization.options);
1757
+ return baseFetch(replayRequest.url, replayRequest.options);
1639
1758
  };
1640
1759
  Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
1641
- value: options.credentials
1760
+ value: {
1761
+ fetch: baseFetch,
1762
+ credentials,
1763
+ credentialResolutions,
1764
+ fetchOptions
1765
+ }
1642
1766
  });
1643
1767
  return authenticatedFetch;
1644
1768
  }
1769
+ function mergeFetchOptions(defaultOptions, requestOptions) {
1770
+ const mergedOptions = { ...defaultOptions, ...requestOptions };
1771
+ if (defaultOptions.headers || (requestOptions == null ? void 0 : requestOptions.headers)) {
1772
+ const headers = new Headers(defaultOptions.headers);
1773
+ new Headers(requestOptions == null ? void 0 : requestOptions.headers).forEach((value, key) => headers.set(key, value));
1774
+ mergedOptions.headers = headers;
1775
+ }
1776
+ return mergedOptions;
1777
+ }
1778
+ async function authenticateRequest(request, credentials, reason, response) {
1779
+ const appliedCredentials = [];
1780
+ const signal = request.options.signal;
1781
+ for (const credential of credentials) {
1782
+ const origin = getRequestOrigin(request.url);
1783
+ if (!origin || !normalizeRequestOrigins(credential.origins).includes(origin)) continue;
1784
+ if (signal == null ? void 0 : signal.aborted) throw createAbortError3();
1785
+ const authenticatedRequest = await credential.authenticate({
1786
+ url: request.url,
1787
+ options: { ...request.options, headers: new Headers(request.options.headers) },
1788
+ reason,
1789
+ response: response ? { status: response.status, headers: new Headers(response.headers) } : void 0
1790
+ });
1791
+ if (!authenticatedRequest || typeof authenticatedRequest.url !== "string" || !authenticatedRequest.options || typeof authenticatedRequest.options !== "object") {
1792
+ throw new Error("Authentication callback returned an invalid request.");
1793
+ }
1794
+ request = {
1795
+ url: authenticatedRequest.url,
1796
+ options: { ...authenticatedRequest.options, ...signal ? { signal } : {} }
1797
+ };
1798
+ appliedCredentials.push(credential);
1799
+ }
1800
+ if (signal == null ? void 0 : signal.aborted) throw createAbortError3();
1801
+ return { ...request, credentials: appliedCredentials };
1802
+ }
1803
+ function getRequestOrigin(url) {
1804
+ try {
1805
+ const parsedURL = new URL(url);
1806
+ if (!parsedURL.host || parsedURL.username || parsedURL.password) return null;
1807
+ return parsedURL.origin !== "null" ? parsedURL.origin : `${parsedURL.protocol}//${parsedURL.host}`;
1808
+ } catch {
1809
+ return null;
1810
+ }
1811
+ }
1812
+ function normalizeRequestOrigins(origins) {
1813
+ if (!origins.length)
1814
+ throw new Error("Request authentication requires at least one exact origin.");
1815
+ return origins.map((origin) => {
1816
+ const resolvedOrigin = getRequestOrigin(origin);
1817
+ let url;
1818
+ try {
1819
+ url = new URL(origin);
1820
+ } catch {
1821
+ throw new Error("Invalid request authentication origin.");
1822
+ }
1823
+ if (!resolvedOrigin || url.pathname && url.pathname !== "/" || url.search || url.hash) {
1824
+ throw new Error("Invalid request authentication origin.");
1825
+ }
1826
+ return resolvedOrigin;
1827
+ });
1828
+ }
1645
1829
  async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
1646
1830
  const url = new URL(sourceURL);
1647
1831
  const headers = new Headers(requestOptions.headers);
@@ -2338,6 +2522,7 @@ var ConsoleLog = class {
2338
2522
 
2339
2523
  // dist/lib/loader-utils/option-defaults.js
2340
2524
  var DEFAULT_LOADER_OPTIONS = {
2525
+ searchParams: void 0,
2341
2526
  core: {
2342
2527
  baseUrl: void 0,
2343
2528
  // baseUrl
@@ -2444,6 +2629,27 @@ var CORE_LOADER_OPTION_KEYS = [
2444
2629
  "metadata",
2445
2630
  "transforms"
2446
2631
  ];
2632
+ function applySearchParamsToUrl(url, options) {
2633
+ const searchParams = options == null ? void 0 : options.searchParams;
2634
+ if (!searchParams || Object.keys(searchParams).length === 0 || /^(?:data|blob):/i.test(url)) {
2635
+ return url;
2636
+ }
2637
+ const hashIndex = url.indexOf("#");
2638
+ const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
2639
+ const urlWithoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
2640
+ const queryIndex = urlWithoutHash.indexOf("?");
2641
+ const path = queryIndex >= 0 ? urlWithoutHash.slice(0, queryIndex) : urlWithoutHash;
2642
+ const query = queryIndex >= 0 ? urlWithoutHash.slice(queryIndex + 1) : "";
2643
+ const existingSearchParams = new URLSearchParams(query);
2644
+ const appendedSearchParams = new URLSearchParams();
2645
+ for (const [key, value] of Object.entries(searchParams)) {
2646
+ if (!existingSearchParams.has(key)) {
2647
+ appendedSearchParams.set(key, String(value));
2648
+ }
2649
+ }
2650
+ const serializedAppendedSearchParams = appendedSearchParams.toString();
2651
+ return `${path}${queryIndex >= 0 ? `?${query}` : ""}${serializedAppendedSearchParams ? `${queryIndex >= 0 ? "&" : "?"}${serializedAppendedSearchParams}` : ""}${hash}`;
2652
+ }
2447
2653
  function getGlobalLoaderState() {
2448
2654
  globalThis.loaders = globalThis.loaders || {};
2449
2655
  const { loaders } = globalThis;
@@ -3200,7 +3406,7 @@ function getIterableFromData(data) {
3200
3406
 
3201
3407
  // dist/lib/loader-utils/get-fetch-function.js
3202
3408
  function getFetchFunction(options, context) {
3203
- var _a, _b;
3409
+ var _a, _b, _c;
3204
3410
  const globalOptions = getGlobalLoaderOptions();
3205
3411
  const loaderOptions = options || globalOptions;
3206
3412
  const fetchOption = loaderOptions.fetch ?? ((_a = loaderOptions.core) == null ? void 0 : _a.fetch);
@@ -3208,8 +3414,7 @@ function getFetchFunction(options, context) {
3208
3414
  if (typeof fetchOption === "function") {
3209
3415
  fetchFunction = fetchOption;
3210
3416
  } else if (isObject(fetchOption)) {
3211
- const baseFetch = (context == null ? void 0 : context.fetch) || fetchFile;
3212
- fetchFunction = (url, requestOptions) => baseFetch(url, mergeFetchOptions(fetchOption, requestOptions));
3417
+ fetchFunction = (context == null ? void 0 : context.fetch) || fetchFile;
3213
3418
  } else if (context == null ? void 0 : context.fetch) {
3214
3419
  fetchFunction = context.fetch;
3215
3420
  } else {
@@ -3217,18 +3422,11 @@ function getFetchFunction(options, context) {
3217
3422
  }
3218
3423
  return createAuthenticatedFetch({
3219
3424
  fetch: fetchFunction,
3220
- credentials: ((_b = loaderOptions.core) == null ? void 0 : _b.credentials) || []
3425
+ credentials: ((_b = loaderOptions.core) == null ? void 0 : _b.credentials) || [],
3426
+ authentications: (_c = loaderOptions.core) == null ? void 0 : _c.authentications,
3427
+ fetchOptions: isObject(fetchOption) ? fetchOption : void 0
3221
3428
  });
3222
3429
  }
3223
- function mergeFetchOptions(defaultOptions, requestOptions) {
3224
- const options = { ...defaultOptions, ...requestOptions };
3225
- if (defaultOptions.headers || (requestOptions == null ? void 0 : requestOptions.headers)) {
3226
- const headers = new Headers(defaultOptions.headers);
3227
- new Headers(requestOptions == null ? void 0 : requestOptions.headers).forEach((value, key) => headers.set(key, value));
3228
- options.headers = headers;
3229
- }
3230
- return options;
3231
- }
3232
3430
 
3233
3431
  // dist/lib/api/load-loader.js
3234
3432
  var loaderImplementationPromises = /* @__PURE__ */ new Map();
@@ -3329,6 +3527,7 @@ async function importLoaderImplementation(implementationSpecifier, loaderId) {
3329
3527
 
3330
3528
  // dist/lib/api/parse-file.js
3331
3529
  async function parseFile(file, loaders, options, context) {
3530
+ var _a, _b;
3332
3531
  if (loaders && !Array.isArray(loaders) && !isLoaderObject(loaders)) {
3333
3532
  context = void 0;
3334
3533
  options = loaders;
@@ -3345,7 +3544,9 @@ async function parseFile(file, loaders, options, context) {
3345
3544
  if (isSourceLoader(loader)) {
3346
3545
  throw new Error(`${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parseFile().`);
3347
3546
  }
3348
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
3547
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
3548
+ const authenticationLoader = !loader.getAuthentications && ((_b = (_a = normalizedOptions.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length) ? await getLoaderImplementation(loader, normalizedOptions, url || (context == null ? void 0 : context.url)) : loader;
3549
+ const strictOptions = await resolveLoaderAuthenticationOptions(authenticationLoader, url, normalizedOptions);
3349
3550
  context = getLoaderContext(
3350
3551
  // @ts-expect-error candidateLoaders may be a single forced loader
3351
3552
  { url, _parse: parse, loaders: candidateLoaders },
@@ -3458,6 +3659,7 @@ function makeBatchFromTable(table) {
3458
3659
 
3459
3660
  // dist/lib/api/parse-in-batches.js
3460
3661
  async function parseInBatches(data, loaders, options, context) {
3662
+ var _a, _b;
3461
3663
  const loaderArray = Array.isArray(loaders) ? loaders : void 0;
3462
3664
  if (!Array.isArray(loaders) && !isLoaderObject(loaders)) {
3463
3665
  context = void 0;
@@ -3471,7 +3673,9 @@ async function parseInBatches(data, loaders, options, context) {
3471
3673
  if (!loader) {
3472
3674
  return [];
3473
3675
  }
3474
- const strictOptions = normalizeOptions(options, loader, loaderArray, url);
3676
+ const normalizedOptions = normalizeOptions(options, loader, loaderArray, url);
3677
+ const authenticationLoader = !loader.getAuthentications && ((_b = (_a = normalizedOptions.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length) ? await getLoaderImplementation(loader, normalizedOptions, url || (context == null ? void 0 : context.url)) : loader;
3678
+ const strictOptions = await resolveLoaderAuthenticationOptions(authenticationLoader, url || "", normalizedOptions);
3475
3679
  context = getLoaderContext({ url, _parseInBatches: parseInBatches, _parse: parse, loaders: loaderArray }, strictOptions, context || null);
3476
3680
  const loaderWithParser = await getLoaderImplementation(loader, strictOptions, context.url);
3477
3681
  return await parseWithLoaderInBatches(loader, loaderWithParser, data, strictOptions, context);
@@ -3551,17 +3755,24 @@ function loadInBatches(files, loaders, options, context) {
3551
3755
  } else {
3552
3756
  loadersArray = loaders;
3553
3757
  }
3554
- const fetch2 = getFetchFunction(options || {});
3555
3758
  if (!Array.isArray(files)) {
3556
- return loadOneFileInBatches(files, loadersArray, options || {}, fetch2);
3759
+ return loadOneFileInBatches(files, loadersArray, options || {});
3557
3760
  }
3558
- const promises = files.map((file) => loadOneFileInBatches(file, loadersArray, options || {}, fetch2));
3761
+ const promises = files.map((file) => loadOneFileInBatches(file, loadersArray, options || {}));
3559
3762
  return promises;
3560
3763
  }
3561
- async function loadOneFileInBatches(file, loaders, options, fetch2) {
3764
+ async function loadOneFileInBatches(file, loaders, options) {
3765
+ var _a, _b;
3562
3766
  if (typeof file === "string") {
3563
3767
  const url = file;
3564
- const response = await fetch2(url);
3768
+ const loader = await selectLoader(url, loaders, {
3769
+ ...options,
3770
+ core: { ...options.core, nothrow: true }
3771
+ });
3772
+ const authenticationLoader = loader && !loader.getAuthentications && ((_b = (_a = options.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length) ? await getLoaderImplementation(loader, options, url) : loader;
3773
+ options = await resolveLoaderAuthenticationOptions(authenticationLoader, url, options);
3774
+ const fetch2 = getFetchFunction(options);
3775
+ const response = await fetch2(applySearchParamsToUrl(url, options));
3565
3776
  return Array.isArray(loaders) ? await parseInBatches(response, loaders, options) : await parseInBatches(response, loaders, options);
3566
3777
  }
3567
3778
  return Array.isArray(loaders) ? await parseInBatches(file, loaders, options) : await parseInBatches(file, loaders, options);
@@ -3580,8 +3791,10 @@ async function load(url, loaders, options, context) {
3580
3791
  resolvedLoaders = loaders;
3581
3792
  resolvedOptions = options;
3582
3793
  }
3794
+ resolvedOptions ||= getGlobalLoaderOptions();
3583
3795
  if (!Array.isArray(resolvedLoaders) && isSourceLoader(resolvedLoaders)) {
3584
3796
  const sourceLoader = await resolveSourceLoader(resolvedLoaders, url, resolvedOptions);
3797
+ resolvedOptions = await resolveLoaderAuthenticationOptions(resolvedLoaders.getAuthentications ? resolvedLoaders : sourceLoader, typeof url === "string" ? url : "", resolvedOptions || {});
3585
3798
  const runtimeCoreApi = {
3586
3799
  fetchFile,
3587
3800
  parse,
@@ -3595,6 +3808,7 @@ async function load(url, loaders, options, context) {
3595
3808
  }
3596
3809
  if (Array.isArray(resolvedLoaders) && resolvedLoaders.length === 1 && isSourceLoader(resolvedLoaders[0])) {
3597
3810
  const sourceLoader = await resolveSourceLoader(resolvedLoaders[0], url, resolvedOptions);
3811
+ resolvedOptions = await resolveLoaderAuthenticationOptions(resolvedLoaders[0].getAuthentications ? resolvedLoaders[0] : sourceLoader, typeof url === "string" ? url : "", resolvedOptions || {});
3598
3812
  const runtimeCoreApi = {
3599
3813
  fetchFile,
3600
3814
  parse,
@@ -3613,6 +3827,7 @@ async function load(url, loaders, options, context) {
3613
3827
  });
3614
3828
  if (selectedLoader && isSourceLoader(selectedLoader)) {
3615
3829
  const sourceLoader = await resolveSourceLoader(selectedLoader, url, resolvedOptions);
3830
+ resolvedOptions = await resolveLoaderAuthenticationOptions(selectedLoader.getAuthentications ? selectedLoader : sourceLoader, typeof url === "string" ? url : "", resolvedOptions || {});
3616
3831
  return sourceLoader.createDataSource(url, resolvedOptions || {}, {
3617
3832
  fetchFile,
3618
3833
  parse,
@@ -3625,15 +3840,20 @@ async function load(url, loaders, options, context) {
3625
3840
  }
3626
3841
  if (selectedLoader && typeof url === "string") {
3627
3842
  const loaderImplementation = await getLoaderImplementation(selectedLoader, resolvedOptions, url);
3843
+ resolvedOptions = await resolveLoaderAuthenticationOptions(selectedLoader.getAuthentications ? selectedLoader : loaderImplementation, url, resolvedOptions || {});
3628
3844
  const parseUrl = loaderImplementation.parseUrl;
3629
- if (parseUrl)
3630
- return await parseUrl(url, resolvedOptions, context);
3845
+ if (parseUrl) {
3846
+ const requestUrl = applySearchParamsToUrl(url, resolvedOptions);
3847
+ return await parseUrl(requestUrl, resolvedOptions, context);
3848
+ }
3631
3849
  }
3632
3850
  }
3851
+ if (resolvedOptions)
3852
+ resolvedOptions = resolveAuthenticationOptions(resolvedOptions);
3633
3853
  const fetch2 = getFetchFunction(resolvedOptions);
3634
3854
  let data = url;
3635
3855
  if (typeof url === "string") {
3636
- data = await fetch2(url);
3856
+ data = await fetch2(applySearchParamsToUrl(url, resolvedOptions));
3637
3857
  }
3638
3858
  if (isBlob(url)) {
3639
3859
  data = await fetch2(url);
@@ -3716,6 +3936,7 @@ function getLoadersFromContext(loaders, context) {
3716
3936
 
3717
3937
  // dist/lib/api/parse.js
3718
3938
  async function parse(data, loaders, options, context) {
3939
+ var _a, _b;
3719
3940
  if (loaders && !Array.isArray(loaders) && !isLoaderObject(loaders)) {
3720
3941
  context = void 0;
3721
3942
  options = loaders;
@@ -3733,7 +3954,9 @@ async function parse(data, loaders, options, context) {
3733
3954
  if (isSourceLoader(loader)) {
3734
3955
  throw new Error(`${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parse().`);
3735
3956
  }
3736
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
3957
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
3958
+ const authenticationLoader = !loader.getAuthentications && ((_b = (_a = normalizedOptions.core) == null ? void 0 : _a.credentials) == null ? void 0 : _b.length) ? await getLoaderImplementation(loader, normalizedOptions, url || (context == null ? void 0 : context.url)) : loader;
3959
+ const strictOptions = await resolveLoaderAuthenticationOptions(authenticationLoader, url || "", normalizedOptions);
3737
3960
  context = getLoaderContext(
3738
3961
  // @ts-expect-error
3739
3962
  { url, _parse: parse, loaders: candidateLoaders },
@@ -3907,8 +4130,8 @@ function getTemporaryFilename(filename2) {
3907
4130
  }
3908
4131
 
3909
4132
  // dist/lib/api/create-data-source.js
3910
- function createDataSource(data, sources, options) {
3911
- var _a;
4133
+ function createDataSource(data, sources, options = {}) {
4134
+ var _a, _b, _c, _d, _e;
3912
4135
  const resolvedOptions = options || {};
3913
4136
  const type = ((_a = resolvedOptions == null ? void 0 : resolvedOptions.core) == null ? void 0 : _a.type) || resolvedOptions.type || "auto";
3914
4137
  const source = sources.length === 1 ? sources[0] : type === "auto" ? selectLoaderSync(data, sources, {
@@ -3920,7 +4143,23 @@ function createDataSource(data, sources, options) {
3920
4143
  if (!source) {
3921
4144
  throw new Error("Not a valid source type");
3922
4145
  }
3923
- return source.createDataSource(data, resolvedOptions, coreApi);
4146
+ const contributions = ((_c = (_b = resolvedOptions.core) == null ? void 0 : _b.credentials) == null ? void 0 : _c.length) ? (_d = source.getAuthentications) == null ? void 0 : _d.call(source, typeof data === "string" ? data : "", resolvedOptions) : void 0;
4147
+ if (contributions && "then" in contributions) {
4148
+ void contributions.catch(() => {
4149
+ });
4150
+ throw new Error("Use load() with an asynchronous getAuthentications() hook.");
4151
+ }
4152
+ const authenticatedOptions = resolveAuthenticationOptions((contributions == null ? void 0 : contributions.length) ? {
4153
+ ...resolvedOptions,
4154
+ core: {
4155
+ ...resolvedOptions.core,
4156
+ authentications: [
4157
+ ...((_e = resolvedOptions.core) == null ? void 0 : _e.authentications) || [],
4158
+ ...contributions || []
4159
+ ]
4160
+ }
4161
+ } : resolvedOptions);
4162
+ return source.createDataSource(data, authenticatedOptions, coreApi);
3924
4163
  }
3925
4164
  function getSourceOfType(type, sources) {
3926
4165
  for (const service of sources) {
@@ -3994,7 +4233,7 @@ function makeStream(source, options) {
3994
4233
  }
3995
4234
 
3996
4235
  // dist/null-loader.js
3997
- var VERSION4 = true ? "5.0.0-alpha.6" : "latest";
4236
+ var VERSION4 = true ? "5.0.0-alpha.8" : "latest";
3998
4237
  var NullWorkerLoader = {
3999
4238
  dataType: null,
4000
4239
  batchType: null,