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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +14 -3
  2. package/dist/dist.dev.js +1246 -227
  3. package/dist/dist.min.js +3 -3
  4. package/dist/index.cjs +2695 -270
  5. package/dist/index.cjs.map +3 -4
  6. package/dist/iterators/make-iterator/make-stream-iterator.js +49 -10
  7. package/dist/iterators/make-iterator/make-stream-iterator.js.map +1 -1
  8. package/dist/lib/api/create-data-source.d.ts +1 -1
  9. package/dist/lib/api/create-data-source.d.ts.map +1 -1
  10. package/dist/lib/api/create-data-source.js +23 -2
  11. package/dist/lib/api/create-data-source.js.map +1 -1
  12. package/dist/lib/api/load-in-batches.d.ts.map +1 -1
  13. package/dist/lib/api/load-in-batches.js +17 -6
  14. package/dist/lib/api/load-in-batches.js.map +1 -1
  15. package/dist/lib/api/load-loader.d.ts +2 -0
  16. package/dist/lib/api/load-loader.d.ts.map +1 -1
  17. package/dist/lib/api/load-loader.js +113 -7
  18. package/dist/lib/api/load-loader.js.map +1 -1
  19. package/dist/lib/api/load.d.ts +3 -3
  20. package/dist/lib/api/load.d.ts.map +1 -1
  21. package/dist/lib/api/load.js +36 -6
  22. package/dist/lib/api/load.js.map +1 -1
  23. package/dist/lib/api/parse-file.d.ts.map +1 -1
  24. package/dist/lib/api/parse-file.js +6 -2
  25. package/dist/lib/api/parse-file.js.map +1 -1
  26. package/dist/lib/api/parse-in-batches.d.ts.map +1 -1
  27. package/dist/lib/api/parse-in-batches.js +12 -3
  28. package/dist/lib/api/parse-in-batches.js.map +1 -1
  29. package/dist/lib/api/parse.d.ts.map +1 -1
  30. package/dist/lib/api/parse.js +11 -3
  31. package/dist/lib/api/parse.js.map +1 -1
  32. package/dist/lib/api/preload.d.ts +6 -3
  33. package/dist/lib/api/preload.d.ts.map +1 -1
  34. package/dist/lib/api/preload.js +4 -5
  35. package/dist/lib/api/preload.js.map +1 -1
  36. package/dist/lib/filesystems/browser-filesystem.d.ts.map +1 -1
  37. package/dist/lib/filesystems/browser-filesystem.js +25 -11
  38. package/dist/lib/filesystems/browser-filesystem.js.map +1 -1
  39. package/dist/lib/init.js +1 -1
  40. package/dist/lib/init.js.map +1 -1
  41. package/dist/lib/loader-utils/get-fetch-function.d.ts.map +1 -1
  42. package/dist/lib/loader-utils/get-fetch-function.js +16 -10
  43. package/dist/lib/loader-utils/get-fetch-function.js.map +1 -1
  44. package/dist/lib/loader-utils/loader-context.d.ts +1 -1
  45. package/dist/lib/loader-utils/loader-context.d.ts.map +1 -1
  46. package/dist/lib/loader-utils/loader-context.js +8 -3
  47. package/dist/lib/loader-utils/loader-context.js.map +1 -1
  48. package/dist/lib/loader-utils/option-defaults.d.ts.map +1 -1
  49. package/dist/lib/loader-utils/option-defaults.js +3 -0
  50. package/dist/lib/loader-utils/option-defaults.js.map +1 -1
  51. package/dist/lib/loader-utils/option-utils.d.ts +7 -0
  52. package/dist/lib/loader-utils/option-utils.d.ts.map +1 -1
  53. package/dist/lib/loader-utils/option-utils.js +41 -1
  54. package/dist/lib/loader-utils/option-utils.js.map +1 -1
  55. package/dist/lib/utils/response-utils.js +2 -11
  56. package/dist/lib/utils/response-utils.js.map +1 -1
  57. package/dist/null-loader.js +1 -1
  58. package/dist/null-loader.js.map +1 -1
  59. package/dist/null-worker-node.js +130 -58
  60. package/dist/null-worker.js +130 -58
  61. package/package.json +6 -6
  62. package/src/iterators/make-iterator/make-stream-iterator.ts +48 -10
  63. package/src/lib/api/create-data-source.ts +31 -2
  64. package/src/lib/api/load-in-batches.ts +18 -11
  65. package/src/lib/api/load-loader.ts +157 -14
  66. package/src/lib/api/load.ts +87 -9
  67. package/src/lib/api/parse-file.ts +15 -2
  68. package/src/lib/api/parse-in-batches.ts +22 -3
  69. package/src/lib/api/parse.ts +18 -3
  70. package/src/lib/api/preload.ts +22 -7
  71. package/src/lib/filesystems/browser-filesystem.ts +25 -11
  72. package/src/lib/loader-utils/get-fetch-function.ts +15 -14
  73. package/src/lib/loader-utils/loader-context.ts +8 -3
  74. package/src/lib/loader-utils/option-defaults.ts +3 -0
  75. package/src/lib/loader-utils/option-utils.ts +47 -1
  76. package/src/lib/utils/response-utils.ts +2 -12
@@ -71,18 +71,18 @@
71
71
  static async addEventListener(onMessage) {
72
72
  let onMessageWrapper = onMessageWrapperMap.get(onMessage);
73
73
  if (!onMessageWrapper) {
74
- onMessageWrapper = async (message) => {
75
- if (!isKnownMessage(message)) {
74
+ onMessageWrapper = (message) => {
75
+ const messageData = getWorkerMessageData(message);
76
+ if (!messageData) {
76
77
  return;
77
78
  }
78
- const parentPort3 = await getParentPort();
79
- const { type, payload } = parentPort3 ? message : message.data;
80
- onMessage(type, payload);
79
+ onMessage(messageData.type, messageData.payload);
81
80
  };
81
+ onMessageWrapperMap.set(onMessage, onMessageWrapper);
82
82
  }
83
83
  const parentPort2 = await getParentPort();
84
84
  if (parentPort2) {
85
- console.error("not implemented");
85
+ parentPort2.on("message", onMessageWrapper);
86
86
  } else {
87
87
  globalThis.addEventListener("message", onMessageWrapper);
88
88
  }
@@ -90,9 +90,12 @@
90
90
  static async removeEventListener(onMessage) {
91
91
  const onMessageWrapper = onMessageWrapperMap.get(onMessage);
92
92
  onMessageWrapperMap.delete(onMessage);
93
+ if (!onMessageWrapper) {
94
+ return;
95
+ }
93
96
  const parentPort2 = await getParentPort();
94
97
  if (parentPort2) {
95
- console.error("not implemented");
98
+ parentPort2.off("message", onMessageWrapper);
96
99
  } else {
97
100
  globalThis.removeEventListener("message", onMessageWrapper);
98
101
  }
@@ -113,9 +116,12 @@
113
116
  }
114
117
  }
115
118
  };
116
- function isKnownMessage(message) {
117
- const { type, data } = message;
118
- return type === "message" && data && typeof data.source === "string" && data.source.startsWith("loaders.gl");
119
+ function getWorkerMessageData(message) {
120
+ if (!message || typeof message !== "object") {
121
+ return null;
122
+ }
123
+ const messageData = "data" in message && message.type === "message" ? message.data : message;
124
+ return messageData && typeof messageData.source === "string" && messageData.source.startsWith("loaders.gl") ? messageData : null;
119
125
  }
120
126
 
121
127
  // ../worker-utils/src/lib/async-queue/async-queue.ts
@@ -190,8 +196,8 @@
190
196
 
191
197
  // ../worker-utils/src/lib/worker-api/create-worker.ts
192
198
  var requestId = 0;
193
- var inputBatches;
194
- var options;
199
+ var activeInputBatches = null;
200
+ var activeOutputAcknowledgements = null;
195
201
  async function createWorker(process, processInBatches) {
196
202
  if (!await WorkerBody.inWorkerThread()) {
197
203
  return;
@@ -221,24 +227,44 @@
221
227
  if (!processInBatches) {
222
228
  throw new Error("Worker does not support batched processing");
223
229
  }
224
- inputBatches = new AsyncQueue();
225
- options = payload.options || {};
226
- const resultIterator = processInBatches(
227
- inputBatches,
228
- options,
229
- context,
230
- payload.context || {}
231
- );
232
- for await (const batch of resultIterator) {
233
- WorkerBody.postMessage("output-batch", { result: batch });
230
+ const inputBatches = new AsyncQueue();
231
+ const outputAcknowledgements = new AsyncQueue();
232
+ activeInputBatches = inputBatches;
233
+ activeOutputAcknowledgements = outputAcknowledgements;
234
+ try {
235
+ const resultIterator = processInBatches(
236
+ createDemandDrivenIterator(inputBatches),
237
+ payload.options || {},
238
+ context,
239
+ payload.context || {}
240
+ );
241
+ for await (const batch of resultIterator) {
242
+ await WorkerBody.postMessage("output-batch", { result: batch });
243
+ await outputAcknowledgements.next();
244
+ }
245
+ await WorkerBody.postMessage("done", {});
246
+ } finally {
247
+ activeInputBatches = null;
248
+ activeOutputAcknowledgements = null;
234
249
  }
235
- WorkerBody.postMessage("done", {});
236
250
  break;
237
251
  case "input-batch":
238
- inputBatches.push(payload.input);
252
+ if (!activeInputBatches) {
253
+ throw new Error("Worker has no active batched processing session");
254
+ }
255
+ activeInputBatches.push(payload.input);
239
256
  break;
240
257
  case "input-done":
241
- inputBatches.close();
258
+ if (!activeInputBatches) {
259
+ throw new Error("Worker has no active batched processing session");
260
+ }
261
+ activeInputBatches.close();
262
+ break;
263
+ case "output-ack":
264
+ if (!activeOutputAcknowledgements) {
265
+ throw new Error("Worker has no active batched processing session");
266
+ }
267
+ activeOutputAcknowledgements.push(void 0);
242
268
  break;
243
269
  default:
244
270
  }
@@ -248,7 +274,17 @@
248
274
  }
249
275
  };
250
276
  }
251
- function processOnMainThread(arrayBuffer, options2 = {}, jobContext = {}) {
277
+ async function* createDemandDrivenIterator(inputBatches) {
278
+ while (true) {
279
+ await WorkerBody.postMessage("input-request", {});
280
+ const nextBatch = await inputBatches.next();
281
+ if (nextBatch.done) {
282
+ return;
283
+ }
284
+ yield nextBatch.value;
285
+ }
286
+ }
287
+ function processOnMainThread(arrayBuffer, options = {}, jobContext = {}) {
252
288
  return new Promise((resolve, reject) => {
253
289
  const id = requestId++;
254
290
  const onMessage = (type, payload2) => {
@@ -268,29 +304,56 @@
268
304
  }
269
305
  };
270
306
  WorkerBody.addEventListener(onMessage);
271
- const payload = { id, input: arrayBuffer, options: options2, context: jobContext };
307
+ const payload = { id, input: arrayBuffer, options, context: jobContext };
272
308
  WorkerBody.postMessage("process", payload);
273
309
  });
274
310
  }
275
311
 
276
312
  // ../loader-utils/src/lib/worker-loader-utils/create-loader-worker.ts
277
- async function createLoaderWorker(loader) {
313
+ async function createLoaderWorker(loader, selectLoader = () => loader) {
278
314
  await createWorker(
279
- async (input, options2 = {}, workerContext, loaderContext = {}) => {
280
- const result = await parseData({
281
- loader,
282
- arrayBuffer: input,
283
- options: options2,
284
- context: {
285
- ...loaderContext,
286
- coreApi: createWorkerCoreApi(),
287
- _parse: createParseOnMainThread(workerContext?.process)
288
- }
289
- });
290
- return loader.serializeWorkerResult ? loader.serializeWorkerResult(result, options2, loaderContext) : result;
291
- }
315
+ (input, options, workerContext, loaderContext) => processLoaderWorkerData(
316
+ selectLoader(options || {}),
317
+ input,
318
+ options,
319
+ workerContext,
320
+ loaderContext
321
+ ),
322
+ (inputIterator, options, workerContext, loaderContext) => processLoaderWorkerBatches(
323
+ selectLoader(options || {}),
324
+ inputIterator,
325
+ options,
326
+ workerContext,
327
+ loaderContext
328
+ )
292
329
  );
293
330
  }
331
+ async function processLoaderWorkerData(loader, input, options = {}, workerContext, loaderContext = {}) {
332
+ const result = await parseData({
333
+ loader,
334
+ arrayBuffer: input,
335
+ options,
336
+ context: {
337
+ ...loaderContext,
338
+ coreApi: createWorkerCoreApi(),
339
+ _parse: createParseOnMainThread(workerContext?.process)
340
+ }
341
+ });
342
+ return loader.serializeWorkerResult ? loader.serializeWorkerResult(result, options, loaderContext) : result;
343
+ }
344
+ async function* processLoaderWorkerBatches(loader, inputIterator, options = {}, workerContext, loaderContext = {}) {
345
+ if (!loader.parseInBatches) {
346
+ throw new Error(`${loader.id} loader does not support batched parsing`);
347
+ }
348
+ const resultIterator = loader.parseInBatches(inputIterator, options, {
349
+ ...loaderContext,
350
+ coreApi: createWorkerCoreApi(),
351
+ _parse: createParseOnMainThread(workerContext?.process)
352
+ });
353
+ for await (const batch of resultIterator) {
354
+ yield loader.serializeWorkerBatch ? loader.serializeWorkerBatch(batch, options, loaderContext) : batch;
355
+ }
356
+ }
294
357
  function createWorkerCoreApi() {
295
358
  const unavailable = (methodName) => () => {
296
359
  throw new Error(`context.coreApi.${methodName} is unavailable inside worker loaders.`);
@@ -306,17 +369,23 @@
306
369
  };
307
370
  }
308
371
  function createParseOnMainThread(processOnMainThread2) {
309
- return (arrayBuffer, loaders, options2, context) => {
372
+ return (arrayBuffer, loaders, options, context) => {
310
373
  if (!processOnMainThread2) {
311
374
  throw new Error("Worker not set up to parse on main thread");
312
375
  }
313
- const parseArguments = getMainThreadParseArguments(loaders, options2, context);
314
- return processOnMainThread2(arrayBuffer, parseArguments.options, parseArguments.context);
376
+ const parseArguments = getMainThreadParseArguments(loaders, options, context);
377
+ return processOnMainThread2(arrayBuffer, parseArguments.options, {
378
+ ...parseArguments.context,
379
+ ...Array.isArray(loaders) || loaders && isLoaderObject(loaders) ? {
380
+ _loaderIsArray: Array.isArray(loaders),
381
+ _loaderIds: (Array.isArray(loaders) ? loaders : [loaders]).map((loader) => loader.id)
382
+ } : {}
383
+ });
315
384
  };
316
385
  }
317
- function getMainThreadParseArguments(loaders, options2, context) {
318
- if (options2) {
319
- return { options: options2, context: getSerializableLoaderContext(context) };
386
+ function getMainThreadParseArguments(loaders, options, context) {
387
+ if (options) {
388
+ return { options, context: getSerializableLoaderContext(context) };
320
389
  }
321
390
  if (Array.isArray(loaders) || loaders && isLoaderObject(loaders)) {
322
391
  return { options: void 0, context: getSerializableLoaderContext(context) };
@@ -339,7 +408,7 @@
339
408
  async function parseData({
340
409
  loader,
341
410
  arrayBuffer,
342
- options: options2,
411
+ options,
343
412
  context
344
413
  }) {
345
414
  let data;
@@ -354,19 +423,22 @@
354
423
  } else {
355
424
  throw new Error(`Could not load data with ${loader.name} loader`);
356
425
  }
357
- options2 = {
358
- ...options2,
359
- modules: loader && loader.options && loader.options.modules || {},
426
+ options = {
427
+ ...options,
428
+ modules: {
429
+ ...loader && loader.options && loader.options.modules || {},
430
+ ...options.modules || {}
431
+ },
360
432
  core: {
361
- ...options2.core,
433
+ ...options.core,
362
434
  worker: false
363
435
  }
364
436
  };
365
- return await parser(data, { ...options2 }, context, loader);
437
+ return await parser(data, { ...options }, context, loader);
366
438
  }
367
439
 
368
440
  // src/null-loader.ts
369
- var VERSION = true ? "5.0.0-alpha.1" : "latest";
441
+ var VERSION = true ? "5.0.0-alpha.11" : "latest";
370
442
  var NullLoader = {
371
443
  dataType: null,
372
444
  batchType: null,
@@ -376,11 +448,11 @@
376
448
  version: VERSION,
377
449
  mimeTypes: ["application/x.empty"],
378
450
  extensions: ["null"],
379
- parse: async (arrayBuffer, options2, context) => parseSync(arrayBuffer, options2 || {}, context),
451
+ parse: async (arrayBuffer, options, context) => parseSync(arrayBuffer, options || {}, context),
380
452
  parseSync,
381
- parseInBatches: async function* generator(asyncIterator, options2, context) {
453
+ parseInBatches: async function* generator(asyncIterator, options, context) {
382
454
  for await (const batch of asyncIterator) {
383
- yield parseSync(batch, options2, context);
455
+ yield parseSync(batch, options, context);
384
456
  }
385
457
  },
386
458
  tests: [() => false],
@@ -388,7 +460,7 @@
388
460
  null: {}
389
461
  }
390
462
  };
391
- function parseSync(arrayBuffer, options2, context) {
463
+ function parseSync(arrayBuffer, options, context) {
392
464
  return null;
393
465
  }
394
466
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/core",
3
- "version": "5.0.0-alpha.1",
3
+ "version": "5.0.0-alpha.11",
4
4
  "description": "The core API for working with loaders.gl loaders and writers",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -58,11 +58,11 @@
58
58
  "build-worker-node": "esbuild src/workers/null-worker.ts --outfile=dist/null-worker-node.js --bundle --platform=node --target=node16 --define:__VERSION__=\\\"$npm_package_version\\\""
59
59
  },
60
60
  "dependencies": {
61
- "@loaders.gl/loader-utils": "5.0.0-alpha.1",
62
- "@loaders.gl/schema": "5.0.0-alpha.1",
63
- "@loaders.gl/schema-utils": "5.0.0-alpha.1",
64
- "@loaders.gl/worker-utils": "5.0.0-alpha.1",
61
+ "@loaders.gl/loader-utils": "5.0.0-alpha.11",
62
+ "@loaders.gl/schema": "5.0.0-alpha.11",
63
+ "@loaders.gl/schema-utils": "5.0.0-alpha.11",
64
+ "@loaders.gl/worker-utils": "5.0.0-alpha.11",
65
65
  "@probe.gl/log": "^4.1.1"
66
66
  },
67
- "gitHead": "77a55028e8204e09df1258f10cb61ed35353b258"
67
+ "gitHead": "31449661e98c1c3f97bb4f8a7bcba7f19596ac00"
68
68
  }
@@ -43,30 +43,68 @@ async function* makeBrowserStreamIterator(
43
43
  const reader = stream.getReader();
44
44
 
45
45
  let nextBatchPromise: Promise<{done?: boolean; value?: Uint8Array}> | undefined;
46
+ let streamFinished = false;
47
+ let streamReadFailed = false;
48
+ let iteratorFailed = false;
46
49
 
47
50
  try {
48
51
  // eslint-disable-next-line no-constant-condition
49
52
  while (true) {
50
53
  const currentBatchPromise = nextBatchPromise || reader.read();
51
- // Issue a read for an additional batch, while we await the next batch
52
- // Idea is to make fetching happen in parallel with processing / parsing
53
- if (options?._streamReadAhead) {
54
- nextBatchPromise = reader.read();
55
- }
54
+ nextBatchPromise = undefined;
56
55
  // Read from the stream
57
56
  // value is a Uint8Array
58
- const {done, value} = await currentBatchPromise;
57
+ let batch;
58
+ try {
59
+ batch = await currentBatchPromise;
60
+ } catch (error) {
61
+ streamReadFailed = true;
62
+ throw error;
63
+ }
64
+ const {done, value} = batch;
59
65
  // Exit if we're done
60
66
  if (done) {
67
+ streamFinished = true;
61
68
  return;
62
69
  }
70
+ // Issue a read for an additional batch while the current batch is processed
71
+ if (options?._streamReadAhead) {
72
+ nextBatchPromise = reader.read();
73
+ // Observe a prefetched rejection even if the consumer stops before requesting it
74
+ void nextBatchPromise.catch(() => {});
75
+ }
63
76
  // Else yield the chunk
64
77
  yield toArrayBuffer(value);
65
78
  }
66
- } catch (_error) {
67
- // TODO - examples makes it look like this should always be called,
68
- // but that generates exceptions so only call it if we do not reach the end
69
- reader.releaseLock();
79
+ } catch (error) {
80
+ iteratorFailed = true;
81
+ throw error;
82
+ } finally {
83
+ let cleanupFailed = false;
84
+ let cleanupError: unknown;
85
+
86
+ if (!streamFinished && !streamReadFailed) {
87
+ try {
88
+ await reader.cancel();
89
+ } catch (error) {
90
+ cleanupFailed = true;
91
+ cleanupError = error;
92
+ }
93
+ }
94
+
95
+ try {
96
+ reader.releaseLock();
97
+ } catch (error) {
98
+ if (!cleanupFailed) {
99
+ cleanupFailed = true;
100
+ cleanupError = error;
101
+ }
102
+ }
103
+
104
+ // Preserve errors from iteration instead of replacing them with cleanup errors
105
+ if (!iteratorFailed && cleanupFailed) {
106
+ throw cleanupError;
107
+ }
70
108
  }
71
109
  }
72
110
 
@@ -7,6 +7,7 @@ import {
7
7
  SourceArrayOptionsType,
8
8
  SourceArrayDataSourceType
9
9
  } from '@loaders.gl/loader-utils';
10
+ import {resolveAuthenticationOptions} from '@loaders.gl/loader-utils';
10
11
  import {coreApi} from './core-api';
11
12
  import {selectLoaderSync} from './select-loader';
12
13
 
@@ -22,7 +23,9 @@ import {selectLoaderSync} from './select-loader';
22
23
  export function createDataSource<SourceArrayT extends SourceLoader[]>(
23
24
  data: unknown,
24
25
  sources: Readonly<SourceArrayT>,
25
- options: Readonly<SourceArrayOptionsType<SourceArrayT>>
26
+ options: Readonly<
27
+ SourceArrayOptionsType<SourceArrayT>
28
+ > = {} as SourceArrayOptionsType<SourceArrayT>
26
29
  ): SourceArrayDataSourceType<SourceArrayT> {
27
30
  const resolvedOptions = (options || {}) as SourceArrayOptionsType<SourceArrayT>;
28
31
  const type = resolvedOptions?.core?.type || (resolvedOptions.type as unknown as string) || 'auto';
@@ -41,7 +44,33 @@ export function createDataSource<SourceArrayT extends SourceLoader[]>(
41
44
  if (!source) {
42
45
  throw new Error('Not a valid source type');
43
46
  }
44
- return source.createDataSource(data as string | Blob, resolvedOptions, coreApi);
47
+ const contributions = resolvedOptions.core?.credentials?.length
48
+ ? source.getAuthentications?.(typeof data === 'string' ? data : '', resolvedOptions)
49
+ : undefined;
50
+ if (contributions && 'then' in contributions) {
51
+ // Avoid an unhandled rejection from a hook that cannot be awaited by this sync API.
52
+ void contributions.catch(() => {});
53
+ throw new Error('Use load() with an asynchronous getAuthentications() hook.');
54
+ }
55
+ const authenticatedOptions = resolveAuthenticationOptions(
56
+ contributions?.length
57
+ ? {
58
+ ...resolvedOptions,
59
+ core: {
60
+ ...resolvedOptions.core,
61
+ authentications: [
62
+ ...(resolvedOptions.core?.authentications || []),
63
+ ...(contributions || [])
64
+ ]
65
+ }
66
+ }
67
+ : resolvedOptions
68
+ );
69
+ return source.createDataSource(
70
+ data as string | Blob,
71
+ authenticatedOptions,
72
+ coreApi
73
+ ) as SourceArrayDataSourceType<SourceArrayT>;
45
74
  }
46
75
 
47
76
  /** Guess service type from URL */
@@ -6,17 +6,20 @@ import type {
6
6
  Loader,
7
7
  LoaderOptions,
8
8
  LoaderContext,
9
- FetchLike,
10
9
  BatchableDataType,
11
10
  LoaderBatchType,
12
11
  LoaderOptionsType,
13
12
  LoaderOptionsWithShape,
14
13
  LoaderShapeType
15
14
  } from '@loaders.gl/loader-utils';
15
+ import {resolveLoaderAuthenticationOptions} from '@loaders.gl/loader-utils';
16
16
  import {isLoaderObject} from '../loader-utils/normalize-loader';
17
17
  import {getFetchFunction} from '../loader-utils/get-fetch-function';
18
+ import {applySearchParamsToUrl} from '../loader-utils/option-utils';
18
19
 
19
20
  import {parseInBatches} from './parse-in-batches';
21
+ import {selectLoader} from './select-loader';
22
+ import {getLoaderImplementation} from './load-loader';
20
23
 
21
24
  type FileType = string | File | Blob | Response | (string | File | Blob | Response)[] | FileList;
22
25
 
@@ -73,18 +76,13 @@ export function loadInBatches(
73
76
  loadersArray = loaders as Loader | Loader[] | undefined;
74
77
  }
75
78
 
76
- // Select fetch function
77
- const fetch = getFetchFunction(options || {});
78
-
79
79
  // Single url/file
80
80
  if (!Array.isArray(files)) {
81
- return loadOneFileInBatches(files, loadersArray!, options || {}, fetch);
81
+ return loadOneFileInBatches(files, loadersArray!, options || {});
82
82
  }
83
83
 
84
84
  // Multiple URLs / files
85
- const promises = files.map(file =>
86
- loadOneFileInBatches(file, loadersArray!, options || {}, fetch)
87
- );
85
+ const promises = files.map(file => loadOneFileInBatches(file, loadersArray!, options || {}));
88
86
 
89
87
  // No point in waiting here for all responses before starting to stream individual streams?
90
88
  return promises;
@@ -93,12 +91,21 @@ export function loadInBatches(
93
91
  async function loadOneFileInBatches(
94
92
  file: FileType,
95
93
  loaders: Loader | Loader[],
96
- options: LoaderOptions,
97
- fetch: FetchLike
94
+ options: LoaderOptions
98
95
  ): Promise<AsyncIterable<unknown>> {
99
96
  if (typeof file === 'string') {
100
97
  const url = file;
101
- const response = await fetch(url);
98
+ const loader = await selectLoader(url, loaders, {
99
+ ...options,
100
+ core: {...options.core, nothrow: true}
101
+ });
102
+ const authenticationLoader =
103
+ loader && !loader.getAuthentications && options.core?.credentials?.length
104
+ ? await getLoaderImplementation(loader, options, url)
105
+ : loader;
106
+ options = await resolveLoaderAuthenticationOptions(authenticationLoader, url, options);
107
+ const fetch = getFetchFunction(options);
108
+ const response = await fetch(applySearchParamsToUrl(url, options));
102
109
  // pick right overload
103
110
  return Array.isArray(loaders)
104
111
  ? await parseInBatches(response, loaders, options)