@loaders.gl/core 5.0.0-alpha.7 → 5.0.0-alpha.9

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 (50) hide show
  1. package/dist/dist.dev.js +308 -52
  2. package/dist/dist.min.js +3 -3
  3. package/dist/index.cjs +293 -60
  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/lib/utils/response-utils.js +2 -11
  36. package/dist/lib/utils/response-utils.js.map +1 -1
  37. package/dist/null-loader.js +1 -1
  38. package/dist/null-worker-node.js +1 -1
  39. package/dist/null-worker.js +1 -1
  40. package/package.json +6 -6
  41. package/src/lib/api/create-data-source.ts +31 -2
  42. package/src/lib/api/load-in-batches.ts +18 -11
  43. package/src/lib/api/load.ts +44 -6
  44. package/src/lib/api/parse-file.ts +15 -2
  45. package/src/lib/api/parse-in-batches.ts +11 -1
  46. package/src/lib/api/parse.ts +11 -1
  47. package/src/lib/loader-utils/get-fetch-function.ts +4 -15
  48. package/src/lib/loader-utils/option-defaults.ts +1 -0
  49. package/src/lib/loader-utils/option-utils.ts +34 -0
  50. package/src/lib/utils/response-utils.ts +2 -12
package/dist/dist.dev.js CHANGED
@@ -1700,6 +1700,10 @@ var __exports__ = (() => {
1700
1700
 
1701
1701
  // ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
1702
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;
1703
1707
  const workerOptions = getWorkerOptions(options);
1704
1708
  const nodeWorkers = workerOptions._nodeWorkers;
1705
1709
  if (!isBrowser3 && !nodeWorkers) {
@@ -1794,7 +1798,12 @@ var __exports__ = (() => {
1794
1798
  return parseOnMainThread(input, void 0, options, context);
1795
1799
  }
1796
1800
  function getWorkerOptions(options = {}, loader) {
1797
- 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
+ );
1798
1807
  const workerOptions = {
1799
1808
  ...serializedOptions.core,
1800
1809
  ...serializedOptions
@@ -1867,6 +1876,19 @@ var __exports__ = (() => {
1867
1876
  return result.buffer;
1868
1877
  }
1869
1878
 
1879
+ // ../loader-utils/src/lib/binary-utils/encode-array-buffer-to-base64.ts
1880
+ function encodeArrayBufferToBase64(arrayBuffer) {
1881
+ const bytes = new Uint8Array(arrayBuffer);
1882
+ const encodedChunks = [];
1883
+ const chunkByteLength = 3 * 4096;
1884
+ for (let byteOffset = 0; byteOffset < bytes.length; byteOffset += chunkByteLength) {
1885
+ encodedChunks.push(
1886
+ btoa(String.fromCharCode(...bytes.subarray(byteOffset, byteOffset + chunkByteLength)))
1887
+ );
1888
+ }
1889
+ return encodedChunks.join("");
1890
+ }
1891
+
1870
1892
  // ../loader-utils/src/lib/iterators/text-iterators.ts
1871
1893
  async function* makeTextDecoderIterator(arrayBufferIterator, options = {}) {
1872
1894
  const textDecoder = new TextDecoder(void 0, options);
@@ -2193,6 +2215,7 @@ var __exports__ = (() => {
2193
2215
  /** Tracks the number of active requests and prioritizes/cancels queued requests. */
2194
2216
  requestQueue = [];
2195
2217
  requestMap = /* @__PURE__ */ new Map();
2218
+ /** Pending arrival debounce or next-tick refill; only new arrivals replace this timer. */
2196
2219
  updateTimer = null;
2197
2220
  constructor(props = {}) {
2198
2221
  this.props = { ...DEFAULT_PROPS2, ...props };
@@ -2260,20 +2283,27 @@ var __exports__ = (() => {
2260
2283
  isDone = true;
2261
2284
  this.requestMap.delete(handle);
2262
2285
  this.activeRequestCount--;
2263
- this._issueNewRequests();
2286
+ this.scheduleRefill();
2264
2287
  }
2265
2288
  };
2266
2289
  this.activeRequestCount++;
2267
2290
  return resolve2 ? resolve2({ done }) : Promise.resolve({ done });
2268
2291
  }
2269
- /** We check requests asynchronously, to prevent multiple updates */
2292
+ /** Refills freed slots on the next tick while preserving any pending arrival debounce. */
2293
+ scheduleRefill() {
2294
+ if (this.updateTimer !== null) {
2295
+ return;
2296
+ }
2297
+ this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), 0);
2298
+ }
2299
+ /** Restarts the quiet period when a new request enters the queue. */
2270
2300
  _issueNewRequests() {
2271
2301
  if (this.updateTimer !== null) {
2272
2302
  clearTimeout(this.updateTimer);
2273
2303
  }
2274
2304
  this.updateTimer = setTimeout(() => this._issueNewRequestsAsync(), this.props.debounceTime);
2275
2305
  }
2276
- /** Refresh all requests */
2306
+ /** Clears timer ownership before updating priorities and dispatching queued requests. */
2277
2307
  _issueNewRequestsAsync() {
2278
2308
  if (this.updateTimer !== null) {
2279
2309
  clearTimeout(this.updateTimer);
@@ -2315,23 +2345,103 @@ var __exports__ = (() => {
2315
2345
  }
2316
2346
  };
2317
2347
 
2348
+ // ../loader-utils/src/lib/request-utils/authentication.ts
2349
+ function resolveCredentials(credentials, authentications = []) {
2350
+ if (credentials.every(isAuthentication)) return credentials;
2351
+ return credentials.map((credential, index) => {
2352
+ if (isAuthentication(credential)) return credential;
2353
+ const AuthenticationClass = authentications.find(
2354
+ (authentication2) => authentication2.type === credential?.type
2355
+ );
2356
+ if (!AuthenticationClass) {
2357
+ throw new Error(`No authentication class registered for credential at index ${index}.`);
2358
+ }
2359
+ let authentication;
2360
+ try {
2361
+ authentication = new AuthenticationClass(credential);
2362
+ } catch {
2363
+ throw new Error(`Invalid authentication configuration at index ${index}.`);
2364
+ }
2365
+ if (!isAuthentication(authentication)) {
2366
+ throw new Error(`Authentication class returned an invalid credential at index ${index}.`);
2367
+ }
2368
+ return authentication;
2369
+ });
2370
+ }
2371
+ function resolveAuthenticationOptions(options) {
2372
+ if (!options.core?.credentials?.length) return options;
2373
+ const credentials = resolveCredentials(options.core.credentials, options.core.authentications);
2374
+ if (credentials === options.core.credentials) return options;
2375
+ return { ...options, core: { ...options.core, credentials } };
2376
+ }
2377
+ async function resolveLoaderAuthenticationOptions(loader, url, options) {
2378
+ if (!options.core?.credentials?.length || options.core.credentials.every(isAuthentication)) {
2379
+ return options;
2380
+ }
2381
+ const contributions = await loader?.getAuthentications?.(url, options);
2382
+ if (!contributions?.length) return resolveAuthenticationOptions(options);
2383
+ return resolveAuthenticationOptions({
2384
+ ...options,
2385
+ core: {
2386
+ ...options.core,
2387
+ authentications: [...options.core?.authentications || [], ...contributions]
2388
+ }
2389
+ });
2390
+ }
2391
+ function isAuthentication(credential) {
2392
+ if (!credential || typeof credential !== "object") return false;
2393
+ if (typeof credential.id !== "string" || !Array.isArray(credential.origins)) return false;
2394
+ if (credential.type === "request") return typeof credential.authenticate === "function";
2395
+ return (credential.type === "header" || credential.type === "query-parameter") && typeof credential.name === "string" && (typeof credential.token === "string" || typeof credential.token === "function") && Array.isArray(credential.refreshStatusCodes);
2396
+ }
2397
+
2318
2398
  // ../loader-utils/src/lib/request-utils/request-credentials.ts
2319
2399
  var AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
2320
2400
  var refreshPromises = /* @__PURE__ */ new WeakMap();
2321
2401
  function createAuthenticatedFetch(options) {
2322
- const baseFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
2323
- if (!options.credentials.length) return baseFetch;
2324
- const existingMetadata = baseFetch[AUTHENTICATED_FETCH];
2325
- if (existingMetadata === options.credentials) return baseFetch;
2402
+ const suppliedFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
2403
+ const existingMetadata = suppliedFetch[AUTHENTICATED_FETCH];
2404
+ const credentialResolutions = new Map(existingMetadata?.credentialResolutions);
2405
+ const resolvedCredentials = resolveCredentials(
2406
+ options.credentials.map((credential) => credentialResolutions.get(credential) || credential),
2407
+ options.authentications
2408
+ );
2409
+ options.credentials.forEach((credential, index) => {
2410
+ credentialResolutions.set(credential, resolvedCredentials[index]);
2411
+ });
2412
+ if (!options.fetchOptions && (!resolvedCredentials.length || existingMetadata?.credentials.length === resolvedCredentials.length && resolvedCredentials.every(
2413
+ (credential, index) => credential === existingMetadata.credentials[index]
2414
+ )))
2415
+ return suppliedFetch;
2416
+ const baseFetch = existingMetadata?.fetch || suppliedFetch;
2417
+ const credentials = existingMetadata ? [.../* @__PURE__ */ new Set([...resolvedCredentials, ...existingMetadata.credentials])] : resolvedCredentials;
2418
+ const fetchOptions = mergeFetchOptions(
2419
+ existingMetadata?.fetchOptions || {},
2420
+ options.fetchOptions
2421
+ );
2422
+ const tokenCredentials = credentials.filter(
2423
+ (credential) => credential.type !== "request"
2424
+ );
2425
+ const requestCredentials = credentials.filter(
2426
+ (credential) => credential.type === "request"
2427
+ );
2428
+ for (const credential of requestCredentials) normalizeRequestOrigins(credential.origins);
2326
2429
  const authenticatedFetch = async (url, requestOptions = {}) => {
2430
+ requestOptions = mergeFetchOptions(fetchOptions, requestOptions);
2431
+ if (requestOptions.signal?.aborted) throw createAbortError3();
2432
+ if (!credentials.length) return baseFetch(url, requestOptions);
2327
2433
  const resolvedURL = parseHTTPURL(url);
2328
- if (!resolvedURL) return baseFetch(url, requestOptions);
2329
- const authorization = await authorizeRequest(resolvedURL, requestOptions, options.credentials);
2330
- const response = await baseFetch(authorization.url, authorization.options);
2434
+ const authorization = resolvedURL ? await authorizeRequest(resolvedURL, requestOptions, tokenCredentials) : { url, options: requestOptions, credentials: [] };
2435
+ const signedRequest = await authenticateRequest(authorization, requestCredentials, "request");
2436
+ const response = await baseFetch(signedRequest.url, signedRequest.options);
2331
2437
  const refreshableCredentials = authorization.credentials.filter(
2332
2438
  ({ credential }) => typeof credential.token === "function" && credential.refreshStatusCodes.includes(response.status)
2333
2439
  );
2334
- if (!refreshableCredentials.length || !isReplayableRequest(requestOptions)) return response;
2440
+ const shouldRetrySignature = signedRequest.credentials.some(
2441
+ (credential) => credential.refreshStatusCodes?.includes(response.status)
2442
+ );
2443
+ if (!refreshableCredentials.length && !shouldRetrySignature || !isReplayableRequest(requestOptions) || !isReplayableRequest(signedRequest.options))
2444
+ return response;
2335
2445
  if (requestOptions.signal?.aborted) throw createAbortError3();
2336
2446
  const refreshedTokens = /* @__PURE__ */ new Map();
2337
2447
  await Promise.all(
@@ -2340,24 +2450,95 @@ var __exports__ = (() => {
2340
2450
  if (token) refreshedTokens.set(credential, token);
2341
2451
  })
2342
2452
  );
2343
- if (!refreshedTokens.size) return response;
2453
+ if (!refreshedTokens.size && !shouldRetrySignature) return response;
2344
2454
  await response.body?.cancel().catch(() => {
2345
2455
  });
2346
2456
  if (requestOptions.signal?.aborted) throw createAbortError3();
2347
- const replayAuthorization = await authorizeRequest(
2457
+ const replayAuthorization = resolvedURL ? await authorizeRequest(
2348
2458
  resolvedURL,
2349
2459
  requestOptions,
2350
- options.credentials,
2460
+ tokenCredentials,
2351
2461
  refreshedTokens,
2352
2462
  authorization.credentials
2463
+ ) : { url, options: requestOptions };
2464
+ const replayRequest = await authenticateRequest(
2465
+ replayAuthorization,
2466
+ requestCredentials,
2467
+ "retry",
2468
+ response
2353
2469
  );
2354
- return baseFetch(replayAuthorization.url, replayAuthorization.options);
2470
+ return baseFetch(replayRequest.url, replayRequest.options);
2355
2471
  };
2356
2472
  Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
2357
- value: options.credentials
2473
+ value: {
2474
+ fetch: baseFetch,
2475
+ credentials,
2476
+ credentialResolutions,
2477
+ fetchOptions
2478
+ }
2358
2479
  });
2359
2480
  return authenticatedFetch;
2360
2481
  }
2482
+ function mergeFetchOptions(defaultOptions, requestOptions) {
2483
+ const mergedOptions = { ...defaultOptions, ...requestOptions };
2484
+ if (defaultOptions.headers || requestOptions?.headers) {
2485
+ const headers = new Headers(defaultOptions.headers);
2486
+ new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
2487
+ mergedOptions.headers = headers;
2488
+ }
2489
+ return mergedOptions;
2490
+ }
2491
+ async function authenticateRequest(request, credentials, reason, response) {
2492
+ const appliedCredentials = [];
2493
+ const signal = request.options.signal;
2494
+ for (const credential of credentials) {
2495
+ const origin = getRequestOrigin(request.url);
2496
+ if (!origin || !normalizeRequestOrigins(credential.origins).includes(origin)) continue;
2497
+ if (signal?.aborted) throw createAbortError3();
2498
+ const authenticatedRequest = await credential.authenticate({
2499
+ url: request.url,
2500
+ options: { ...request.options, headers: new Headers(request.options.headers) },
2501
+ reason,
2502
+ response: response ? { status: response.status, headers: new Headers(response.headers) } : void 0
2503
+ });
2504
+ if (!authenticatedRequest || typeof authenticatedRequest.url !== "string" || !authenticatedRequest.options || typeof authenticatedRequest.options !== "object") {
2505
+ throw new Error("Authentication callback returned an invalid request.");
2506
+ }
2507
+ request = {
2508
+ url: authenticatedRequest.url,
2509
+ options: { ...authenticatedRequest.options, ...signal ? { signal } : {} }
2510
+ };
2511
+ appliedCredentials.push(credential);
2512
+ }
2513
+ if (signal?.aborted) throw createAbortError3();
2514
+ return { ...request, credentials: appliedCredentials };
2515
+ }
2516
+ function getRequestOrigin(url) {
2517
+ try {
2518
+ const parsedURL = new URL(url);
2519
+ if (!parsedURL.host || parsedURL.username || parsedURL.password) return null;
2520
+ return parsedURL.origin !== "null" ? parsedURL.origin : `${parsedURL.protocol}//${parsedURL.host}`;
2521
+ } catch {
2522
+ return null;
2523
+ }
2524
+ }
2525
+ function normalizeRequestOrigins(origins) {
2526
+ if (!origins.length)
2527
+ throw new Error("Request authentication requires at least one exact origin.");
2528
+ return origins.map((origin) => {
2529
+ const resolvedOrigin = getRequestOrigin(origin);
2530
+ let url;
2531
+ try {
2532
+ url = new URL(origin);
2533
+ } catch {
2534
+ throw new Error("Invalid request authentication origin.");
2535
+ }
2536
+ if (!resolvedOrigin || url.pathname && url.pathname !== "/" || url.search || url.hash) {
2537
+ throw new Error("Invalid request authentication origin.");
2538
+ }
2539
+ return resolvedOrigin;
2540
+ });
2541
+ }
2361
2542
  async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
2362
2543
  const url = new URL(sourceURL);
2363
2544
  const headers = new Headers(requestOptions.headers);
@@ -2922,19 +3103,11 @@ var __exports__ = (() => {
2922
3103
  }
2923
3104
  if (resource instanceof ArrayBuffer) {
2924
3105
  const slice = resource.slice(0, INITIAL_DATA_LENGTH);
2925
- const base64 = arrayBufferToBase64(slice);
3106
+ const base64 = encodeArrayBufferToBase64(slice);
2926
3107
  return `data:base64,${base64}`;
2927
3108
  }
2928
3109
  return null;
2929
3110
  }
2930
- function arrayBufferToBase64(buffer) {
2931
- let binary = "";
2932
- const bytes = new Uint8Array(buffer);
2933
- for (let i = 0; i < bytes.byteLength; i++) {
2934
- binary += String.fromCharCode(bytes[i]);
2935
- }
2936
- return btoa(binary);
2937
- }
2938
3111
 
2939
3112
  // src/lib/fetch/fetch-file.ts
2940
3113
  function isNodePath(url) {
@@ -3044,6 +3217,7 @@ var __exports__ = (() => {
3044
3217
 
3045
3218
  // src/lib/loader-utils/option-defaults.ts
3046
3219
  var DEFAULT_LOADER_OPTIONS = {
3220
+ searchParams: void 0,
3047
3221
  core: {
3048
3222
  baseUrl: void 0,
3049
3223
  // baseUrl
@@ -3150,6 +3324,27 @@ var __exports__ = (() => {
3150
3324
  "metadata",
3151
3325
  "transforms"
3152
3326
  ];
3327
+ function applySearchParamsToUrl(url, options) {
3328
+ const searchParams = options?.searchParams;
3329
+ if (!searchParams || Object.keys(searchParams).length === 0 || /^(?:data|blob):/i.test(url)) {
3330
+ return url;
3331
+ }
3332
+ const hashIndex = url.indexOf("#");
3333
+ const hash = hashIndex >= 0 ? url.slice(hashIndex) : "";
3334
+ const urlWithoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
3335
+ const queryIndex = urlWithoutHash.indexOf("?");
3336
+ const path = queryIndex >= 0 ? urlWithoutHash.slice(0, queryIndex) : urlWithoutHash;
3337
+ const query = queryIndex >= 0 ? urlWithoutHash.slice(queryIndex + 1) : "";
3338
+ const existingSearchParams = new URLSearchParams(query);
3339
+ const appendedSearchParams = new URLSearchParams();
3340
+ for (const [key, value] of Object.entries(searchParams)) {
3341
+ if (!existingSearchParams.has(key)) {
3342
+ appendedSearchParams.set(key, String(value));
3343
+ }
3344
+ }
3345
+ const serializedAppendedSearchParams = appendedSearchParams.toString();
3346
+ return `${path}${queryIndex >= 0 ? `?${query}` : ""}${serializedAppendedSearchParams ? `${queryIndex >= 0 ? "&" : "?"}${serializedAppendedSearchParams}` : ""}${hash}`;
3347
+ }
3153
3348
  function getGlobalLoaderState() {
3154
3349
  globalThis.loaders = globalThis.loaders || {};
3155
3350
  const { loaders } = globalThis;
@@ -3922,8 +4117,7 @@ var __exports__ = (() => {
3922
4117
  if (typeof fetchOption === "function") {
3923
4118
  fetchFunction = fetchOption;
3924
4119
  } else if (isObject(fetchOption)) {
3925
- const baseFetch = context?.fetch || fetchFile;
3926
- fetchFunction = (url, requestOptions) => baseFetch(url, mergeFetchOptions(fetchOption, requestOptions));
4120
+ fetchFunction = context?.fetch || fetchFile;
3927
4121
  } else if (context?.fetch) {
3928
4122
  fetchFunction = context.fetch;
3929
4123
  } else {
@@ -3931,18 +4125,11 @@ var __exports__ = (() => {
3931
4125
  }
3932
4126
  return createAuthenticatedFetch({
3933
4127
  fetch: fetchFunction,
3934
- credentials: loaderOptions.core?.credentials || []
4128
+ credentials: loaderOptions.core?.credentials || [],
4129
+ authentications: loaderOptions.core?.authentications,
4130
+ fetchOptions: isObject(fetchOption) ? fetchOption : void 0
3935
4131
  });
3936
4132
  }
3937
- function mergeFetchOptions(defaultOptions, requestOptions) {
3938
- const options = { ...defaultOptions, ...requestOptions };
3939
- if (defaultOptions.headers || requestOptions?.headers) {
3940
- const headers = new Headers(defaultOptions.headers);
3941
- new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
3942
- options.headers = headers;
3943
- }
3944
- return options;
3945
- }
3946
4133
 
3947
4134
  // src/lib/api/load-loader.ts
3948
4135
  var loaderImplementationPromises = /* @__PURE__ */ new Map();
@@ -4063,7 +4250,13 @@ var __exports__ = (() => {
4063
4250
  `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parseFile().`
4064
4251
  );
4065
4252
  }
4066
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4253
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
4254
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4255
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4256
+ authenticationLoader,
4257
+ url,
4258
+ normalizedOptions
4259
+ );
4067
4260
  context = getLoaderContext(
4068
4261
  // @ts-expect-error candidateLoaders may be a single forced loader
4069
4262
  { url, _parse: parse, loaders: candidateLoaders },
@@ -4203,7 +4396,13 @@ var __exports__ = (() => {
4203
4396
  if (!loader) {
4204
4397
  return [];
4205
4398
  }
4206
- const strictOptions = normalizeOptions(options, loader, loaderArray, url);
4399
+ const normalizedOptions = normalizeOptions(options, loader, loaderArray, url);
4400
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4401
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4402
+ authenticationLoader,
4403
+ url || "",
4404
+ normalizedOptions
4405
+ );
4207
4406
  context = getLoaderContext(
4208
4407
  { url, _parseInBatches: parseInBatches, _parse: parse, loaders: loaderArray },
4209
4408
  strictOptions,
@@ -4288,19 +4487,23 @@ var __exports__ = (() => {
4288
4487
  } else {
4289
4488
  loadersArray = loaders;
4290
4489
  }
4291
- const fetch2 = getFetchFunction(options || {});
4292
4490
  if (!Array.isArray(files)) {
4293
- return loadOneFileInBatches(files, loadersArray, options || {}, fetch2);
4491
+ return loadOneFileInBatches(files, loadersArray, options || {});
4294
4492
  }
4295
- const promises = files.map(
4296
- (file) => loadOneFileInBatches(file, loadersArray, options || {}, fetch2)
4297
- );
4493
+ const promises = files.map((file) => loadOneFileInBatches(file, loadersArray, options || {}));
4298
4494
  return promises;
4299
4495
  }
4300
- async function loadOneFileInBatches(file, loaders, options, fetch2) {
4496
+ async function loadOneFileInBatches(file, loaders, options) {
4301
4497
  if (typeof file === "string") {
4302
4498
  const url = file;
4303
- const response = await fetch2(url);
4499
+ const loader = await selectLoader(url, loaders, {
4500
+ ...options,
4501
+ core: { ...options.core, nothrow: true }
4502
+ });
4503
+ const authenticationLoader = loader && !loader.getAuthentications && options.core?.credentials?.length ? await getLoaderImplementation(loader, options, url) : loader;
4504
+ options = await resolveLoaderAuthenticationOptions(authenticationLoader, url, options);
4505
+ const fetch2 = getFetchFunction(options);
4506
+ const response = await fetch2(applySearchParamsToUrl(url, options));
4304
4507
  return Array.isArray(loaders) ? await parseInBatches(response, loaders, options) : await parseInBatches(response, loaders, options);
4305
4508
  }
4306
4509
  return Array.isArray(loaders) ? await parseInBatches(file, loaders, options) : await parseInBatches(file, loaders, options);
@@ -4318,8 +4521,14 @@ var __exports__ = (() => {
4318
4521
  resolvedLoaders = loaders;
4319
4522
  resolvedOptions = options;
4320
4523
  }
4524
+ resolvedOptions ||= getGlobalLoaderOptions();
4321
4525
  if (!Array.isArray(resolvedLoaders) && isSourceLoader(resolvedLoaders)) {
4322
4526
  const sourceLoader = await resolveSourceLoader(resolvedLoaders, url, resolvedOptions);
4527
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4528
+ resolvedLoaders.getAuthentications ? resolvedLoaders : sourceLoader,
4529
+ typeof url === "string" ? url : "",
4530
+ resolvedOptions || {}
4531
+ );
4323
4532
  const runtimeCoreApi = {
4324
4533
  fetchFile,
4325
4534
  parse,
@@ -4337,6 +4546,11 @@ var __exports__ = (() => {
4337
4546
  }
4338
4547
  if (Array.isArray(resolvedLoaders) && resolvedLoaders.length === 1 && isSourceLoader(resolvedLoaders[0])) {
4339
4548
  const sourceLoader = await resolveSourceLoader(resolvedLoaders[0], url, resolvedOptions);
4549
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4550
+ resolvedLoaders[0].getAuthentications ? resolvedLoaders[0] : sourceLoader,
4551
+ typeof url === "string" ? url : "",
4552
+ resolvedOptions || {}
4553
+ );
4340
4554
  const runtimeCoreApi = {
4341
4555
  fetchFile,
4342
4556
  parse,
@@ -4359,6 +4573,11 @@ var __exports__ = (() => {
4359
4573
  });
4360
4574
  if (selectedLoader && isSourceLoader(selectedLoader)) {
4361
4575
  const sourceLoader = await resolveSourceLoader(selectedLoader, url, resolvedOptions);
4576
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4577
+ selectedLoader.getAuthentications ? selectedLoader : sourceLoader,
4578
+ typeof url === "string" ? url : "",
4579
+ resolvedOptions || {}
4580
+ );
4362
4581
  return sourceLoader.createDataSource(
4363
4582
  url,
4364
4583
  resolvedOptions || {},
@@ -4379,14 +4598,23 @@ var __exports__ = (() => {
4379
4598
  resolvedOptions,
4380
4599
  url
4381
4600
  );
4601
+ resolvedOptions = await resolveLoaderAuthenticationOptions(
4602
+ selectedLoader.getAuthentications ? selectedLoader : loaderImplementation,
4603
+ url,
4604
+ resolvedOptions || {}
4605
+ );
4382
4606
  const parseUrl = loaderImplementation.parseUrl;
4383
- if (parseUrl) return await parseUrl(url, resolvedOptions, context);
4607
+ if (parseUrl) {
4608
+ const requestUrl = applySearchParamsToUrl(url, resolvedOptions);
4609
+ return await parseUrl(requestUrl, resolvedOptions, context);
4610
+ }
4384
4611
  }
4385
4612
  }
4613
+ if (resolvedOptions) resolvedOptions = resolveAuthenticationOptions(resolvedOptions);
4386
4614
  const fetch2 = getFetchFunction(resolvedOptions);
4387
4615
  let data = url;
4388
4616
  if (typeof url === "string") {
4389
- data = await fetch2(url);
4617
+ data = await fetch2(applySearchParamsToUrl(url, resolvedOptions));
4390
4618
  }
4391
4619
  if (isBlob(url)) {
4392
4620
  data = await fetch2(url);
@@ -4488,7 +4716,13 @@ var __exports__ = (() => {
4488
4716
  `${loader.id} is a SourceLoader. Use load() to create a runtime source object instead of parse().`
4489
4717
  );
4490
4718
  }
4491
- const strictOptions = normalizeOptions(options, loader, candidateLoaders, url);
4719
+ const normalizedOptions = normalizeOptions(options, loader, candidateLoaders, url);
4720
+ const authenticationLoader = !loader.getAuthentications && normalizedOptions.core?.credentials?.length ? await getLoaderImplementation(loader, normalizedOptions, url || context?.url) : loader;
4721
+ const strictOptions = await resolveLoaderAuthenticationOptions(
4722
+ authenticationLoader,
4723
+ url || "",
4724
+ normalizedOptions
4725
+ );
4492
4726
  context = getLoaderContext(
4493
4727
  // @ts-expect-error
4494
4728
  { url, _parse: parse, loaders: candidateLoaders },
@@ -4664,7 +4898,7 @@ var __exports__ = (() => {
4664
4898
  }
4665
4899
 
4666
4900
  // src/lib/api/create-data-source.ts
4667
- function createDataSource(data, sources, options) {
4901
+ function createDataSource(data, sources, options = {}) {
4668
4902
  const resolvedOptions = options || {};
4669
4903
  const type = resolvedOptions?.core?.type || resolvedOptions.type || "auto";
4670
4904
  const source = sources.length === 1 ? sources[0] : type === "auto" ? selectLoaderSync(data, sources, {
@@ -4676,7 +4910,29 @@ var __exports__ = (() => {
4676
4910
  if (!source) {
4677
4911
  throw new Error("Not a valid source type");
4678
4912
  }
4679
- return source.createDataSource(data, resolvedOptions, coreApi);
4913
+ const contributions = resolvedOptions.core?.credentials?.length ? source.getAuthentications?.(typeof data === "string" ? data : "", resolvedOptions) : void 0;
4914
+ if (contributions && "then" in contributions) {
4915
+ void contributions.catch(() => {
4916
+ });
4917
+ throw new Error("Use load() with an asynchronous getAuthentications() hook.");
4918
+ }
4919
+ const authenticatedOptions = resolveAuthenticationOptions(
4920
+ contributions?.length ? {
4921
+ ...resolvedOptions,
4922
+ core: {
4923
+ ...resolvedOptions.core,
4924
+ authentications: [
4925
+ ...resolvedOptions.core?.authentications || [],
4926
+ ...contributions || []
4927
+ ]
4928
+ }
4929
+ } : resolvedOptions
4930
+ );
4931
+ return source.createDataSource(
4932
+ data,
4933
+ authenticatedOptions,
4934
+ coreApi
4935
+ );
4680
4936
  }
4681
4937
  function getSourceOfType(type, sources) {
4682
4938
  for (const service of sources) {