@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/dist.dev.js CHANGED
@@ -1084,6 +1084,7 @@ var __exports__ = (() => {
1084
1084
  props = {};
1085
1085
  jobQueue = [];
1086
1086
  idleQueue = [];
1087
+ activeJobs = /* @__PURE__ */ new Set();
1087
1088
  count = 0;
1088
1089
  isDestroyed = false;
1089
1090
  /** Checks if workers are supported on this platform */
@@ -1102,10 +1103,14 @@ var __exports__ = (() => {
1102
1103
  this.setProps(props);
1103
1104
  }
1104
1105
  /**
1105
- * 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.
1106
1108
  * @note Can free up significant memory
1107
1109
  */
1108
- 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));
1109
1114
  this.idleQueue.forEach((worker) => worker.destroy());
1110
1115
  this.isDestroyed = true;
1111
1116
  }
@@ -1128,8 +1133,11 @@ var __exports__ = (() => {
1128
1133
  }
1129
1134
  }
1130
1135
  async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
1131
- const startPromise = new Promise((onStart) => {
1132
- this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart });
1136
+ if (this.isDestroyed) {
1137
+ return Promise.reject(new Error("Worker pool was destroyed"));
1138
+ }
1139
+ const startPromise = new Promise((onStart, onReject) => {
1140
+ this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart, onReject });
1133
1141
  return this;
1134
1142
  });
1135
1143
  this._startQueuedJob();
@@ -1157,6 +1165,7 @@ var __exports__ = (() => {
1157
1165
  backlog: this.jobQueue.length
1158
1166
  });
1159
1167
  const job = new WorkerJob(queuedJob.name, workerThread);
1168
+ this.activeJobs.add(job);
1160
1169
  workerThread.ref();
1161
1170
  workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
1162
1171
  workerThread.onError = (error) => queuedJob.onError(job, error);
@@ -1165,6 +1174,7 @@ var __exports__ = (() => {
1165
1174
  await job.result;
1166
1175
  } catch {
1167
1176
  } finally {
1177
+ this.activeJobs.delete(job);
1168
1178
  this.returnWorkerToQueue(workerThread);
1169
1179
  }
1170
1180
  }
@@ -1255,12 +1265,13 @@ var __exports__ = (() => {
1255
1265
  this.workerPools = /* @__PURE__ */ new Map();
1256
1266
  }
1257
1267
  /**
1258
- * 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.
1259
1270
  * @note Can free up significant memory
1260
1271
  */
1261
- destroy() {
1272
+ destroy(reason) {
1262
1273
  for (const workerPool of this.workerPools.values()) {
1263
- workerPool.destroy();
1274
+ workerPool.destroy(reason);
1264
1275
  }
1265
1276
  this.workerPools = /* @__PURE__ */ new Map();
1266
1277
  }
@@ -1689,12 +1700,16 @@ var __exports__ = (() => {
1689
1700
 
1690
1701
  // ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
1691
1702
  function canParseWithWorker(loader, options) {
1703
+ if (options?.core?.credentials?.some(
1704
+ (credential) => credential.type === "request" || "token" in credential && typeof credential.token === "function"
1705
+ ))
1706
+ return false;
1692
1707
  const workerOptions = getWorkerOptions(options);
1693
1708
  const nodeWorkers = workerOptions._nodeWorkers;
1694
1709
  if (!isBrowser3 && !nodeWorkers) {
1695
1710
  return false;
1696
1711
  }
1697
- if (loader.id === "excel" && options?.excel?.shape === "arrow-table" || loader.id === "ply" && options?.ply?.shape === "arrow-table") {
1712
+ if (loader.id === "las" && (options?.las?.shape ?? "arrow-table") === "arrow-table") {
1698
1713
  return false;
1699
1714
  }
1700
1715
  if (loader.id === "csv" && !shouldParseCSVWithWorker(options)) {
@@ -1783,7 +1798,12 @@ var __exports__ = (() => {
1783
1798
  return parseOnMainThread(input, void 0, options, context);
1784
1799
  }
1785
1800
  function getWorkerOptions(options = {}, loader) {
1786
- const serializedOptions = JSON.parse(JSON.stringify(options));
1801
+ const serializedOptions = JSON.parse(
1802
+ JSON.stringify({
1803
+ ...options,
1804
+ ...options.core ? { core: { ...options.core, authentications: void 0 } } : {}
1805
+ })
1806
+ );
1787
1807
  const workerOptions = {
1788
1808
  ...serializedOptions.core,
1789
1809
  ...serializedOptions
@@ -2182,6 +2202,7 @@ var __exports__ = (() => {
2182
2202
  /** Tracks the number of active requests and prioritizes/cancels queued requests. */
2183
2203
  requestQueue = [];
2184
2204
  requestMap = /* @__PURE__ */ new Map();
2205
+ /** Pending arrival debounce or next-tick refill; only new arrivals replace this timer. */
2185
2206
  updateTimer = null;
2186
2207
  constructor(props = {}) {
2187
2208
  this.props = { ...DEFAULT_PROPS2, ...props };
@@ -2249,20 +2270,27 @@ var __exports__ = (() => {
2249
2270
  isDone = true;
2250
2271
  this.requestMap.delete(handle);
2251
2272
  this.activeRequestCount--;
2252
- this._issueNewRequests();
2273
+ this.scheduleRefill();
2253
2274
  }
2254
2275
  };
2255
2276
  this.activeRequestCount++;
2256
2277
  return resolve2 ? resolve2({ done }) : Promise.resolve({ done });
2257
2278
  }
2258
- /** We check requests asynchronously, to prevent multiple updates */
2279
+ /** Refills freed slots on the next tick while preserving any pending arrival debounce. */
2280
+ scheduleRefill() {
2281
+ if (this.updateTimer !== null) {
2282
+ return;
2283
+ }
2284
+ this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), 0);
2285
+ }
2286
+ /** Restarts the quiet period when a new request enters the queue. */
2259
2287
  _issueNewRequests() {
2260
2288
  if (this.updateTimer !== null) {
2261
2289
  clearTimeout(this.updateTimer);
2262
2290
  }
2263
2291
  this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), this.props.debounceTime);
2264
2292
  }
2265
- /** Refresh all requests */
2293
+ /** Clears timer ownership before updating priorities and dispatching queued requests. */
2266
2294
  _issueNewRequestsAsync() {
2267
2295
  if (this.updateTimer !== null) {
2268
2296
  clearTimeout(this.updateTimer);
@@ -2304,23 +2332,103 @@ var __exports__ = (() => {
2304
2332
  }
2305
2333
  };
2306
2334
 
2335
+ // ../loader-utils/src/lib/request-utils/authentication.ts
2336
+ function resolveCredentials(credentials, authentications = []) {
2337
+ if (credentials.every(isAuthentication)) return credentials;
2338
+ return credentials.map((credential, index) => {
2339
+ if (isAuthentication(credential)) return credential;
2340
+ const AuthenticationClass = authentications.find(
2341
+ (authentication2) => authentication2.type === credential?.type
2342
+ );
2343
+ if (!AuthenticationClass) {
2344
+ throw new Error(`No authentication class registered for credential at index ${index}.`);
2345
+ }
2346
+ let authentication;
2347
+ try {
2348
+ authentication = new AuthenticationClass(credential);
2349
+ } catch {
2350
+ throw new Error(`Invalid authentication configuration at index ${index}.`);
2351
+ }
2352
+ if (!isAuthentication(authentication)) {
2353
+ throw new Error(`Authentication class returned an invalid credential at index ${index}.`);
2354
+ }
2355
+ return authentication;
2356
+ });
2357
+ }
2358
+ function resolveAuthenticationOptions(options) {
2359
+ if (!options.core?.credentials?.length) return options;
2360
+ const credentials = resolveCredentials(options.core.credentials, options.core.authentications);
2361
+ if (credentials === options.core.credentials) return options;
2362
+ return { ...options, core: { ...options.core, credentials } };
2363
+ }
2364
+ async function resolveLoaderAuthenticationOptions(loader, url, options) {
2365
+ if (!options.core?.credentials?.length || options.core.credentials.every(isAuthentication)) {
2366
+ return options;
2367
+ }
2368
+ const contributions = await loader?.getAuthentications?.(url, options);
2369
+ if (!contributions?.length) return resolveAuthenticationOptions(options);
2370
+ return resolveAuthenticationOptions({
2371
+ ...options,
2372
+ core: {
2373
+ ...options.core,
2374
+ authentications: [...options.core?.authentications || [], ...contributions]
2375
+ }
2376
+ });
2377
+ }
2378
+ function isAuthentication(credential) {
2379
+ if (!credential || typeof credential !== "object") return false;
2380
+ if (typeof credential.id !== "string" || !Array.isArray(credential.origins)) return false;
2381
+ if (credential.type === "request") return typeof credential.authenticate === "function";
2382
+ return (credential.type === "header" || credential.type === "query-parameter") && typeof credential.name === "string" && (typeof credential.token === "string" || typeof credential.token === "function") && Array.isArray(credential.refreshStatusCodes);
2383
+ }
2384
+
2307
2385
  // ../loader-utils/src/lib/request-utils/request-credentials.ts
2308
2386
  var AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
2309
2387
  var refreshPromises = /* @__PURE__ */ new WeakMap();
2310
2388
  function createAuthenticatedFetch(options) {
2311
- const baseFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
2312
- if (!options.credentials.length) return baseFetch;
2313
- const existingMetadata = baseFetch[AUTHENTICATED_FETCH];
2314
- if (existingMetadata === options.credentials) return baseFetch;
2389
+ const suppliedFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
2390
+ const existingMetadata = suppliedFetch[AUTHENTICATED_FETCH];
2391
+ const credentialResolutions = new Map(existingMetadata?.credentialResolutions);
2392
+ const resolvedCredentials = resolveCredentials(
2393
+ options.credentials.map((credential) => credentialResolutions.get(credential) || credential),
2394
+ options.authentications
2395
+ );
2396
+ options.credentials.forEach((credential, index) => {
2397
+ credentialResolutions.set(credential, resolvedCredentials[index]);
2398
+ });
2399
+ if (!options.fetchOptions && (!resolvedCredentials.length || existingMetadata?.credentials.length === resolvedCredentials.length && resolvedCredentials.every(
2400
+ (credential, index) => credential === existingMetadata.credentials[index]
2401
+ )))
2402
+ return suppliedFetch;
2403
+ const baseFetch = existingMetadata?.fetch || suppliedFetch;
2404
+ const credentials = existingMetadata ? [.../* @__PURE__ */ new Set([...resolvedCredentials, ...existingMetadata.credentials])] : resolvedCredentials;
2405
+ const fetchOptions = mergeFetchOptions(
2406
+ existingMetadata?.fetchOptions || {},
2407
+ options.fetchOptions
2408
+ );
2409
+ const tokenCredentials = credentials.filter(
2410
+ (credential) => credential.type !== "request"
2411
+ );
2412
+ const requestCredentials = credentials.filter(
2413
+ (credential) => credential.type === "request"
2414
+ );
2415
+ for (const credential of requestCredentials) normalizeRequestOrigins(credential.origins);
2315
2416
  const authenticatedFetch = async (url, requestOptions = {}) => {
2417
+ requestOptions = mergeFetchOptions(fetchOptions, requestOptions);
2418
+ if (requestOptions.signal?.aborted) throw createAbortError3();
2419
+ if (!credentials.length) return baseFetch(url, requestOptions);
2316
2420
  const resolvedURL = parseHTTPURL(url);
2317
- if (!resolvedURL) return baseFetch(url, requestOptions);
2318
- const authorization = await authorizeRequest(resolvedURL, requestOptions, options.credentials);
2319
- const response = await baseFetch(authorization.url, authorization.options);
2421
+ const authorization = resolvedURL ? await authorizeRequest(resolvedURL, requestOptions, tokenCredentials) : { url, options: requestOptions, credentials: [] };
2422
+ const signedRequest = await authenticateRequest(authorization, requestCredentials, "request");
2423
+ const response = await baseFetch(signedRequest.url, signedRequest.options);
2320
2424
  const refreshableCredentials = authorization.credentials.filter(
2321
2425
  ({ credential }) => typeof credential.token === "function" && credential.refreshStatusCodes.includes(response.status)
2322
2426
  );
2323
- if (!refreshableCredentials.length || !isReplayableRequest(requestOptions)) return response;
2427
+ const shouldRetrySignature = signedRequest.credentials.some(
2428
+ (credential) => credential.refreshStatusCodes?.includes(response.status)
2429
+ );
2430
+ if (!refreshableCredentials.length && !shouldRetrySignature || !isReplayableRequest(requestOptions) || !isReplayableRequest(signedRequest.options))
2431
+ return response;
2324
2432
  if (requestOptions.signal?.aborted) throw createAbortError3();
2325
2433
  const refreshedTokens = /* @__PURE__ */ new Map();
2326
2434
  await Promise.all(
@@ -2329,24 +2437,95 @@ var __exports__ = (() => {
2329
2437
  if (token) refreshedTokens.set(credential, token);
2330
2438
  })
2331
2439
  );
2332
- if (!refreshedTokens.size) return response;
2440
+ if (!refreshedTokens.size && !shouldRetrySignature) return response;
2333
2441
  await response.body?.cancel().catch(() => {
2334
2442
  });
2335
2443
  if (requestOptions.signal?.aborted) throw createAbortError3();
2336
- const replayAuthorization = await authorizeRequest(
2444
+ const replayAuthorization = resolvedURL ? await authorizeRequest(
2337
2445
  resolvedURL,
2338
2446
  requestOptions,
2339
- options.credentials,
2447
+ tokenCredentials,
2340
2448
  refreshedTokens,
2341
2449
  authorization.credentials
2450
+ ) : { url, options: requestOptions };
2451
+ const replayRequest = await authenticateRequest(
2452
+ replayAuthorization,
2453
+ requestCredentials,
2454
+ "retry",
2455
+ response
2342
2456
  );
2343
- return baseFetch(replayAuthorization.url, replayAuthorization.options);
2457
+ return baseFetch(replayRequest.url, replayRequest.options);
2344
2458
  };
2345
2459
  Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
2346
- value: options.credentials
2460
+ value: {
2461
+ fetch: baseFetch,
2462
+ credentials,
2463
+ credentialResolutions,
2464
+ fetchOptions
2465
+ }
2347
2466
  });
2348
2467
  return authenticatedFetch;
2349
2468
  }
2469
+ function mergeFetchOptions(defaultOptions, requestOptions) {
2470
+ const mergedOptions = { ...defaultOptions, ...requestOptions };
2471
+ if (defaultOptions.headers || requestOptions?.headers) {
2472
+ const headers = new Headers(defaultOptions.headers);
2473
+ new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
2474
+ mergedOptions.headers = headers;
2475
+ }
2476
+ return mergedOptions;
2477
+ }
2478
+ async function authenticateRequest(request, credentials, reason, response) {
2479
+ const appliedCredentials = [];
2480
+ const signal = request.options.signal;
2481
+ for (const credential of credentials) {
2482
+ const origin = getRequestOrigin(request.url);
2483
+ if (!origin || !normalizeRequestOrigins(credential.origins).includes(origin)) continue;
2484
+ if (signal?.aborted) throw createAbortError3();
2485
+ const authenticatedRequest = await credential.authenticate({
2486
+ url: request.url,
2487
+ options: { ...request.options, headers: new Headers(request.options.headers) },
2488
+ reason,
2489
+ response: response ? { status: response.status, headers: new Headers(response.headers) } : void 0
2490
+ });
2491
+ if (!authenticatedRequest || typeof authenticatedRequest.url !== "string" || !authenticatedRequest.options || typeof authenticatedRequest.options !== "object") {
2492
+ throw new Error("Authentication callback returned an invalid request.");
2493
+ }
2494
+ request = {
2495
+ url: authenticatedRequest.url,
2496
+ options: { ...authenticatedRequest.options, ...signal ? { signal } : {} }
2497
+ };
2498
+ appliedCredentials.push(credential);
2499
+ }
2500
+ if (signal?.aborted) throw createAbortError3();
2501
+ return { ...request, credentials: appliedCredentials };
2502
+ }
2503
+ function getRequestOrigin(url) {
2504
+ try {
2505
+ const parsedURL = new URL(url);
2506
+ if (!parsedURL.host || parsedURL.username || parsedURL.password) return null;
2507
+ return parsedURL.origin !== "null" ? parsedURL.origin : `${parsedURL.protocol}//${parsedURL.host}`;
2508
+ } catch {
2509
+ return null;
2510
+ }
2511
+ }
2512
+ function normalizeRequestOrigins(origins) {
2513
+ if (!origins.length)
2514
+ throw new Error("Request authentication requires at least one exact origin.");
2515
+ return origins.map((origin) => {
2516
+ const resolvedOrigin = getRequestOrigin(origin);
2517
+ let url;
2518
+ try {
2519
+ url = new URL(origin);
2520
+ } catch {
2521
+ throw new Error("Invalid request authentication origin.");
2522
+ }
2523
+ if (!resolvedOrigin || url.pathname && url.pathname !== "/" || url.search || url.hash) {
2524
+ throw new Error("Invalid request authentication origin.");
2525
+ }
2526
+ return resolvedOrigin;
2527
+ });
2528
+ }
2350
2529
  async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
2351
2530
  const url = new URL(sourceURL);
2352
2531
  const headers = new Headers(requestOptions.headers);
@@ -3033,6 +3212,7 @@ var __exports__ = (() => {
3033
3212
 
3034
3213
  // src/lib/loader-utils/option-defaults.ts
3035
3214
  var DEFAULT_LOADER_OPTIONS = {
3215
+ searchParams: void 0,
3036
3216
  core: {
3037
3217
  baseUrl: void 0,
3038
3218
  // baseUrl
@@ -3139,6 +3319,27 @@ var __exports__ = (() => {
3139
3319
  "metadata",
3140
3320
  "transforms"
3141
3321
  ];
3322
+ function applySearchParamsToUrl(url, options) {
3323
+ const searchParams = options?.searchParams;
3324
+ if (!searchParams || Object.keys(searchParams).length === 0 || /^(?:data|blob):/i.test(url)) {
3325
+ return url;
3326
+ }
3327
+ const hashIndex = url.indexOf("#");
3328
+ const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
3329
+ const urlWithoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
3330
+ const queryIndex = urlWithoutHash.indexOf("?");
3331
+ const path = queryIndex >= 0 ? urlWithoutHash.slice(0, queryIndex) : urlWithoutHash;
3332
+ const query = queryIndex >= 0 ? urlWithoutHash.slice(queryIndex + 1) : "";
3333
+ const existingSearchParams = new URLSearchParams(query);
3334
+ const appendedSearchParams = new URLSearchParams();
3335
+ for (const [key, value] of Object.entries(searchParams)) {
3336
+ if (!existingSearchParams.has(key)) {
3337
+ appendedSearchParams.set(key, String(value));
3338
+ }
3339
+ }
3340
+ const serializedAppendedSearchParams = appendedSearchParams.toString();
3341
+ return `${path}${queryIndex >= 0 ? `?${query}` : ""}${serializedAppendedSearchParams ? `${queryIndex >= 0 ? "&" : "?"}${serializedAppendedSearchParams}` : ""}${hash}`;
3342
+ }
3142
3343
  function getGlobalLoaderState() {
3143
3344
  globalThis.loaders = globalThis.loaders || {};
3144
3345
  const { loaders } = globalThis;
@@ -3911,8 +4112,7 @@ var __exports__ = (() => {
3911
4112
  if (typeof fetchOption === "function") {
3912
4113
  fetchFunction = fetchOption;
3913
4114
  } else if (isObject(fetchOption)) {
3914
- const baseFetch = context?.fetch || fetchFile;
3915
- fetchFunction = (url, requestOptions) => baseFetch(url, mergeFetchOptions(fetchOption, requestOptions));
4115
+ fetchFunction = context?.fetch || fetchFile;
3916
4116
  } else if (context?.fetch) {
3917
4117
  fetchFunction = context.fetch;
3918
4118
  } else {
@@ -3920,18 +4120,11 @@ var __exports__ = (() => {
3920
4120
  }
3921
4121
  return createAuthenticatedFetch({
3922
4122
  fetch: fetchFunction,
3923
- credentials: loaderOptions.core?.credentials || []
4123
+ credentials: loaderOptions.core?.credentials || [],
4124
+ authentications: loaderOptions.core?.authentications,
4125
+ fetchOptions: isObject(fetchOption) ? fetchOption : void 0
3924
4126
  });
3925
4127
  }
3926
- function mergeFetchOptions(defaultOptions, requestOptions) {
3927
- const options = { ...defaultOptions, ...requestOptions };
3928
- if (defaultOptions.headers || requestOptions?.headers) {
3929
- const headers = new Headers(defaultOptions.headers);
3930
- new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
3931
- options.headers = headers;
3932
- }
3933
- return options;
3934
- }
3935
4128
 
3936
4129
  // src/lib/api/load-loader.ts
3937
4130
  var loaderImplementationPromises = /* @__PURE__ */ new Map();
@@ -4052,7 +4245,13 @@ var __exports__ = (() => {
4052
4245
  `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parseFile().`
4053
4246
  );
4054
4247
  }
4055
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4248
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
4249
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4250
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4251
+ authenticationLoader,
4252
+ url,
4253
+ normalizedOptions
4254
+ );
4056
4255
  context = getLoaderContext(
4057
4256
  // @ts-expect-error candidateLoaders may be a single forced loader
4058
4257
  { url, _parse: parse, loaders: candidateLoaders },
@@ -4192,7 +4391,13 @@ var __exports__ = (() => {
4192
4391
  if (!loader) {
4193
4392
  return [];
4194
4393
  }
4195
- const strictOptions = normalizeOptions(options, loader, loaderArray, url);
4394
+ const normalizedOptions = normalizeOptions(options, loader, loaderArray, url);
4395
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4396
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4397
+ authenticationLoader,
4398
+ url || "",
4399
+ normalizedOptions
4400
+ );
4196
4401
  context = getLoaderContext(
4197
4402
  { url, _parseInBatches: parseInBatches, _parse: parse, loaders: loaderArray },
4198
4403
  strictOptions,
@@ -4277,19 +4482,23 @@ var __exports__ = (() => {
4277
4482
  } else {
4278
4483
  loadersArray = loaders;
4279
4484
  }
4280
- const fetch2 = getFetchFunction(options || {});
4281
4485
  if (!Array.isArray(files)) {
4282
- return loadOneFileInBatches(files, loadersArray, options || {}, fetch2);
4486
+ return loadOneFileInBatches(files, loadersArray, options || {});
4283
4487
  }
4284
- const promises = files.map(
4285
- (file) => loadOneFileInBatches(file, loadersArray, options || {}, fetch2)
4286
- );
4488
+ const promises = files.map((file) => loadOneFileInBatches(file, loadersArray, options || {}));
4287
4489
  return promises;
4288
4490
  }
4289
- async function loadOneFileInBatches(file, loaders, options, fetch2) {
4491
+ async function loadOneFileInBatches(file, loaders, options) {
4290
4492
  if (typeof file === "string") {
4291
4493
  const url = file;
4292
- const response = await fetch2(url);
4494
+ const loader = await selectLoader(url, loaders, {
4495
+ ...options,
4496
+ core: { ...options.core, nothrow: true }
4497
+ });
4498
+ const authenticationLoader = loader && !loader.getAuthentications && options.core?.credentials?.length ? await getLoaderImplementation(loader, options, url) : loader;
4499
+ options = await resolveLoaderAuthenticationOptions(authenticationLoader, url, options);
4500
+ const fetch2 = getFetchFunction(options);
4501
+ const response = await fetch2(applySearchParamsToUrl(url, options));
4293
4502
  return Array.isArray(loaders) ? await parseInBatches(response, loaders, options) : await parseInBatches(response, loaders, options);
4294
4503
  }
4295
4504
  return Array.isArray(loaders) ? await parseInBatches(file, loaders, options) : await parseInBatches(file, loaders, options);
@@ -4307,8 +4516,14 @@ var __exports__ = (() => {
4307
4516
  resolvedLoaders = loaders;
4308
4517
  resolvedOptions = options;
4309
4518
  }
4519
+ resolvedOptions ||= getGlobalLoaderOptions();
4310
4520
  if (!Array.isArray(resolvedLoaders) && isSourceLoader(resolvedLoaders)) {
4311
4521
  const sourceLoader = await resolveSourceLoader(resolvedLoaders, url, resolvedOptions);
4522
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4523
+ resolvedLoaders.getAuthentications ? resolvedLoaders : sourceLoader,
4524
+ typeof url === "string" ? url : "",
4525
+ resolvedOptions || {}
4526
+ );
4312
4527
  const runtimeCoreApi = {
4313
4528
  fetchFile,
4314
4529
  parse,
@@ -4326,6 +4541,11 @@ var __exports__ = (() => {
4326
4541
  }
4327
4542
  if (Array.isArray(resolvedLoaders) && resolvedLoaders.length === 1 && isSourceLoader(resolvedLoaders[0])) {
4328
4543
  const sourceLoader = await resolveSourceLoader(resolvedLoaders[0], url, resolvedOptions);
4544
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4545
+ resolvedLoaders[0].getAuthentications ? resolvedLoaders[0] : sourceLoader,
4546
+ typeof url === "string" ? url : "",
4547
+ resolvedOptions || {}
4548
+ );
4329
4549
  const runtimeCoreApi = {
4330
4550
  fetchFile,
4331
4551
  parse,
@@ -4348,6 +4568,11 @@ var __exports__ = (() => {
4348
4568
  });
4349
4569
  if (selectedLoader && isSourceLoader(selectedLoader)) {
4350
4570
  const sourceLoader = await resolveSourceLoader(selectedLoader, url, resolvedOptions);
4571
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4572
+ selectedLoader.getAuthentications ? selectedLoader : sourceLoader,
4573
+ typeof url === "string" ? url : "",
4574
+ resolvedOptions || {}
4575
+ );
4351
4576
  return sourceLoader.createDataSource(
4352
4577
  url,
4353
4578
  resolvedOptions || {},
@@ -4368,14 +4593,23 @@ var __exports__ = (() => {
4368
4593
  resolvedOptions,
4369
4594
  url
4370
4595
  );
4596
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4597
+ selectedLoader.getAuthentications ? selectedLoader : loaderImplementation,
4598
+ url,
4599
+ resolvedOptions || {}
4600
+ );
4371
4601
  const parseUrl = loaderImplementation.parseUrl;
4372
- if (parseUrl) return await parseUrl(url, resolvedOptions, context);
4602
+ if (parseUrl) {
4603
+ const requestUrl = applySearchParamsToUrl(url, resolvedOptions);
4604
+ return await parseUrl(requestUrl, resolvedOptions, context);
4605
+ }
4373
4606
  }
4374
4607
  }
4608
+ if (resolvedOptions) resolvedOptions = resolveAuthenticationOptions(resolvedOptions);
4375
4609
  const fetch2 = getFetchFunction(resolvedOptions);
4376
4610
  let data = url;
4377
4611
  if (typeof url === "string") {
4378
- data = await fetch2(url);
4612
+ data = await fetch2(applySearchParamsToUrl(url, resolvedOptions));
4379
4613
  }
4380
4614
  if (isBlob(url)) {
4381
4615
  data = await fetch2(url);
@@ -4477,7 +4711,13 @@ var __exports__ = (() => {
4477
4711
  `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parse().`
4478
4712
  );
4479
4713
  }
4480
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4714
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
4715
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4716
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4717
+ authenticationLoader,
4718
+ url || "",
4719
+ normalizedOptions
4720
+ );
4481
4721
  context = getLoaderContext(
4482
4722
  // @ts-expect-error
4483
4723
  { url, _parse: parse, loaders: candidateLoaders },
@@ -4653,7 +4893,7 @@ var __exports__ = (() => {
4653
4893
  }
4654
4894
 
4655
4895
  // src/lib/api/create-data-source.ts
4656
- function createDataSource(data, sources, options) {
4896
+ function createDataSource(data, sources, options = {}) {
4657
4897
  const resolvedOptions = options || {};
4658
4898
  const type = resolvedOptions?.core?.type || resolvedOptions.type || "auto";
4659
4899
  const source = sources.length === 1 ? sources[0] : type === "auto" ? selectLoaderSync(data, sources, {
@@ -4665,7 +4905,29 @@ var __exports__ = (() => {
4665
4905
  if (!source) {
4666
4906
  throw new Error("Not a valid source type");
4667
4907
  }
4668
- return source.createDataSource(data, resolvedOptions, coreApi);
4908
+ const contributions = resolvedOptions.core?.credentials?.length ? source.getAuthentications?.(typeof data === "string" ? data : "", resolvedOptions) : void 0;
4909
+ if (contributions && "then" in contributions) {
4910
+ void contributions.catch(() => {
4911
+ });
4912
+ throw new Error("Use load() with an asynchronous getAuthentications() hook.");
4913
+ }
4914
+ const authenticatedOptions = resolveAuthenticationOptions(
4915
+ contributions?.length ? {
4916
+ ...resolvedOptions,
4917
+ core: {
4918
+ ...resolvedOptions.core,
4919
+ authentications: [
4920
+ ...resolvedOptions.core?.authentications || [],
4921
+ ...contributions || []
4922
+ ]
4923
+ }
4924
+ } : resolvedOptions
4925
+ );
4926
+ return source.createDataSource(
4927
+ data,
4928
+ authenticatedOptions,
4929
+ coreApi
4930
+ );
4669
4931
  }
4670
4932
  function getSourceOfType(type, sources) {
4671
4933
  for (const service of sources) {