@loaders.gl/core 5.0.0-alpha.2 → 5.0.0-alpha.4
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.
- package/LICENSE +1 -1
- package/dist/dist.dev.js +187 -30
- package/dist/dist.min.js +3 -3
- package/dist/index.cjs +187 -32
- package/dist/index.cjs.map +3 -3
- package/dist/lib/api/load.d.ts.map +1 -1
- package/dist/lib/api/load.js +7 -0
- package/dist/lib/api/load.js.map +1 -1
- package/dist/lib/filesystems/browser-filesystem.d.ts.map +1 -1
- package/dist/lib/filesystems/browser-filesystem.js +25 -11
- package/dist/lib/filesystems/browser-filesystem.js.map +1 -1
- package/dist/lib/init.js +1 -1
- package/dist/lib/loader-utils/get-fetch-function.js +24 -10
- package/dist/lib/loader-utils/get-fetch-function.js.map +1 -1
- package/dist/null-loader.js +1 -1
- package/dist/null-worker-node.js +96 -56
- package/dist/null-worker.js +96 -56
- package/package.json +6 -6
- package/src/lib/api/load.ts +21 -1
- package/src/lib/filesystems/browser-filesystem.ts +25 -11
- package/src/lib/loader-utils/get-fetch-function.ts +23 -12
package/LICENSE
CHANGED
|
@@ -37,7 +37,7 @@ License reproduced above.
|
|
|
37
37
|
Copyright (c) 2016 Axel Rauschmayer
|
|
38
38
|
|
|
39
39
|
loaders.gl includes certain files from Cesium (https://github.com/CesiumGS/cesium)
|
|
40
|
-
under the Apache 2.0 License, including files in modules/3d-tiles
|
|
40
|
+
under the Apache 2.0 License, including files in modules/3d-tiles.
|
|
41
41
|
|
|
42
42
|
Copyright 2011-2018 CesiumJS Contributors
|
|
43
43
|
|
package/dist/dist.dev.js
CHANGED
|
@@ -795,17 +795,24 @@ var __exports__ = (() => {
|
|
|
795
795
|
this.isRunning = false;
|
|
796
796
|
this._reject(error);
|
|
797
797
|
}
|
|
798
|
-
/**
|
|
799
|
-
|
|
798
|
+
/**
|
|
799
|
+
* Terminates the worker executing this job and rejects its result.
|
|
800
|
+
* @param reason Abort reason supplied by the caller, or a cross-runtime `AbortError`.
|
|
801
|
+
*/
|
|
802
|
+
abort(reason) {
|
|
800
803
|
if (!this.isRunning) {
|
|
801
804
|
return;
|
|
802
805
|
}
|
|
803
|
-
const error =
|
|
804
|
-
error.name = "AbortError";
|
|
806
|
+
const error = reason ?? createAbortError(`Worker job "${this.name}" was aborted`);
|
|
805
807
|
this.workerThread.destroy();
|
|
806
808
|
this.error(error);
|
|
807
809
|
}
|
|
808
810
|
};
|
|
811
|
+
function createAbortError(message) {
|
|
812
|
+
const error = new Error(message);
|
|
813
|
+
error.name = "AbortError";
|
|
814
|
+
return error;
|
|
815
|
+
}
|
|
809
816
|
|
|
810
817
|
// ../worker-utils/src/lib/node/worker_threads-browser.ts
|
|
811
818
|
var NodeWorker = class {
|
|
@@ -1271,7 +1278,7 @@ var __exports__ = (() => {
|
|
|
1271
1278
|
}
|
|
1272
1279
|
function getWorkerURL(worker, options = {}) {
|
|
1273
1280
|
const workerOptions = options[worker.id] || {};
|
|
1274
|
-
const workerFile = isBrowser3 ? `${worker.id}-worker.js` : `${worker.id}-worker-node.js`;
|
|
1281
|
+
const workerFile = isBrowser3 ? `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
|
|
1275
1282
|
let url = workerOptions.workerUrl;
|
|
1276
1283
|
if (!url && typeof worker.worker === "string") {
|
|
1277
1284
|
url = worker.worker;
|
|
@@ -1337,7 +1344,7 @@ var __exports__ = (() => {
|
|
|
1337
1344
|
// eslint-disable-next-line
|
|
1338
1345
|
onMessage.bind(null, context)
|
|
1339
1346
|
);
|
|
1340
|
-
const abortJob = () => job.abort();
|
|
1347
|
+
const abortJob = () => job.abort(getAbortReason(options.signal));
|
|
1341
1348
|
options.signal?.addEventListener("abort", abortJob, { once: true });
|
|
1342
1349
|
if (options.signal?.aborted) {
|
|
1343
1350
|
abortJob();
|
|
@@ -1363,9 +1370,15 @@ var __exports__ = (() => {
|
|
|
1363
1370
|
if (!signal?.aborted) {
|
|
1364
1371
|
return;
|
|
1365
1372
|
}
|
|
1366
|
-
|
|
1373
|
+
throw getAbortReason(signal);
|
|
1374
|
+
}
|
|
1375
|
+
function getAbortReason(signal) {
|
|
1376
|
+
return signal?.reason ?? createAbortError2("Worker job was aborted");
|
|
1377
|
+
}
|
|
1378
|
+
function createAbortError2(message) {
|
|
1379
|
+
const error = new Error(message);
|
|
1367
1380
|
error.name = "AbortError";
|
|
1368
|
-
|
|
1381
|
+
return error;
|
|
1369
1382
|
}
|
|
1370
1383
|
async function onMessage(context, job, type, payload) {
|
|
1371
1384
|
switch (type) {
|
|
@@ -1419,12 +1432,12 @@ var __exports__ = (() => {
|
|
|
1419
1432
|
}
|
|
1420
1433
|
return Boolean(canProcessOnWorker(loader, workerOptions));
|
|
1421
1434
|
}
|
|
1422
|
-
async function parseWithWorker(loader, data, options, context, parseOnMainThread) {
|
|
1423
|
-
const
|
|
1435
|
+
async function parseWithWorker(loader, data, options, context, parseOnMainThread, signal) {
|
|
1436
|
+
const workerSignal = signal || getWorkerAbortSignal(options);
|
|
1424
1437
|
const result = await processOnWorker(
|
|
1425
1438
|
loader,
|
|
1426
1439
|
data,
|
|
1427
|
-
{ ...getWorkerOptions(options), signal },
|
|
1440
|
+
{ ...getWorkerOptions(options), signal: workerSignal },
|
|
1428
1441
|
{
|
|
1429
1442
|
process: async (input, processOptions, _workerContext, parseContext) => {
|
|
1430
1443
|
if (!parseOnMainThread) {
|
|
@@ -1971,6 +1984,114 @@ var __exports__ = (() => {
|
|
|
1971
1984
|
}
|
|
1972
1985
|
};
|
|
1973
1986
|
|
|
1987
|
+
// ../loader-utils/src/lib/request-utils/request-credentials.ts
|
|
1988
|
+
var AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
|
|
1989
|
+
var refreshPromises = /* @__PURE__ */ new WeakMap();
|
|
1990
|
+
function createAuthenticatedFetch(options) {
|
|
1991
|
+
const baseFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
|
|
1992
|
+
if (!options.credentials.length) return baseFetch;
|
|
1993
|
+
const existingMetadata = baseFetch[AUTHENTICATED_FETCH];
|
|
1994
|
+
if (existingMetadata === options.credentials) return baseFetch;
|
|
1995
|
+
const authenticatedFetch = async (url, requestOptions = {}) => {
|
|
1996
|
+
const resolvedURL = parseHTTPURL(url);
|
|
1997
|
+
if (!resolvedURL) return baseFetch(url, requestOptions);
|
|
1998
|
+
const authorization = await authorizeRequest(resolvedURL, requestOptions, options.credentials);
|
|
1999
|
+
const response = await baseFetch(authorization.url, authorization.options);
|
|
2000
|
+
const refreshableCredentials = authorization.credentials.filter(
|
|
2001
|
+
({ credential }) => typeof credential.token === "function" && credential.refreshStatusCodes.includes(response.status)
|
|
2002
|
+
);
|
|
2003
|
+
if (!refreshableCredentials.length || !isReplayableRequest(requestOptions)) return response;
|
|
2004
|
+
if (requestOptions.signal?.aborted) throw createAbortError3();
|
|
2005
|
+
const refreshedTokens = /* @__PURE__ */ new Map();
|
|
2006
|
+
await Promise.all(
|
|
2007
|
+
refreshableCredentials.map(async ({ credential }) => {
|
|
2008
|
+
const token = await refreshCredential(credential, url, response);
|
|
2009
|
+
if (token) refreshedTokens.set(credential, token);
|
|
2010
|
+
})
|
|
2011
|
+
);
|
|
2012
|
+
if (!refreshedTokens.size) return response;
|
|
2013
|
+
await response.body?.cancel().catch(() => {
|
|
2014
|
+
});
|
|
2015
|
+
if (requestOptions.signal?.aborted) throw createAbortError3();
|
|
2016
|
+
const replayAuthorization = await authorizeRequest(
|
|
2017
|
+
resolvedURL,
|
|
2018
|
+
requestOptions,
|
|
2019
|
+
options.credentials,
|
|
2020
|
+
refreshedTokens,
|
|
2021
|
+
authorization.credentials
|
|
2022
|
+
);
|
|
2023
|
+
return baseFetch(replayAuthorization.url, replayAuthorization.options);
|
|
2024
|
+
};
|
|
2025
|
+
Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
|
|
2026
|
+
value: options.credentials
|
|
2027
|
+
});
|
|
2028
|
+
return authenticatedFetch;
|
|
2029
|
+
}
|
|
2030
|
+
async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
|
|
2031
|
+
const url = new URL(sourceURL);
|
|
2032
|
+
const headers = new Headers(requestOptions.headers);
|
|
2033
|
+
const resolvedCredentials = [];
|
|
2034
|
+
const previousTokens = new Map(
|
|
2035
|
+
previousCredentials.map(({ credential, token }) => [credential, token])
|
|
2036
|
+
);
|
|
2037
|
+
for (const credential of credentials) {
|
|
2038
|
+
if (!credential.origins.includes(url.origin)) continue;
|
|
2039
|
+
const overrideToken = tokenOverrides.get(credential);
|
|
2040
|
+
const previousToken = previousTokens.get(credential);
|
|
2041
|
+
const ownsQueryParameter = credential.type === "query-parameter" && previousToken !== void 0;
|
|
2042
|
+
const ownsHeader = credential.type === "header" && previousToken !== void 0;
|
|
2043
|
+
if (credential.type === "query-parameter" && url.searchParams.has(credential.name) && !ownsQueryParameter || credential.type === "header" && headers.has(credential.name) && !ownsHeader) {
|
|
2044
|
+
continue;
|
|
2045
|
+
}
|
|
2046
|
+
const token = overrideToken ?? previousToken ?? await resolveToken(credential.token, { url: sourceURL.toString(), reason: "request" });
|
|
2047
|
+
if (!token) continue;
|
|
2048
|
+
if (credential.type === "query-parameter") {
|
|
2049
|
+
url.searchParams.set(credential.name, token);
|
|
2050
|
+
} else {
|
|
2051
|
+
headers.set(credential.name, `${credential.prefix || ""}${token}`);
|
|
2052
|
+
}
|
|
2053
|
+
resolvedCredentials.push({ credential, token });
|
|
2054
|
+
}
|
|
2055
|
+
return {
|
|
2056
|
+
url: url.toString(),
|
|
2057
|
+
options: { ...requestOptions, headers },
|
|
2058
|
+
credentials: resolvedCredentials
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
async function refreshCredential(credential, url, response) {
|
|
2062
|
+
const existingPromise = refreshPromises.get(credential);
|
|
2063
|
+
if (existingPromise) return existingPromise;
|
|
2064
|
+
const tokenProvider = credential.token;
|
|
2065
|
+
const promise = Promise.resolve(
|
|
2066
|
+
tokenProvider({
|
|
2067
|
+
url,
|
|
2068
|
+
reason: "refresh",
|
|
2069
|
+
response: { status: response.status, headers: response.headers }
|
|
2070
|
+
})
|
|
2071
|
+
).finally(() => refreshPromises.delete(credential));
|
|
2072
|
+
refreshPromises.set(credential, promise);
|
|
2073
|
+
return promise;
|
|
2074
|
+
}
|
|
2075
|
+
async function resolveToken(token, context) {
|
|
2076
|
+
return typeof token === "function" ? token(context) : token;
|
|
2077
|
+
}
|
|
2078
|
+
function parseHTTPURL(url) {
|
|
2079
|
+
try {
|
|
2080
|
+
const parsedURL = new URL(url);
|
|
2081
|
+
return ["http:", "https:"].includes(parsedURL.protocol) ? parsedURL : null;
|
|
2082
|
+
} catch {
|
|
2083
|
+
return null;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
function isReplayableRequest(options) {
|
|
2087
|
+
const method = (options.method || "GET").toUpperCase();
|
|
2088
|
+
if (!["GET", "HEAD", "OPTIONS", "PUT", "DELETE"].includes(method)) return false;
|
|
2089
|
+
return !(options.body && typeof ReadableStream !== "undefined" && options.body instanceof ReadableStream);
|
|
2090
|
+
}
|
|
2091
|
+
function createAbortError3() {
|
|
2092
|
+
return new DOMException("The operation was aborted.", "AbortError");
|
|
2093
|
+
}
|
|
2094
|
+
|
|
1974
2095
|
// ../loader-utils/src/lib/path-utils/file-aliases.ts
|
|
1975
2096
|
var pathPrefix = "";
|
|
1976
2097
|
var fileAliases = {};
|
|
@@ -3455,16 +3576,29 @@ var __exports__ = (() => {
|
|
|
3455
3576
|
const globalOptions = getGlobalLoaderOptions();
|
|
3456
3577
|
const loaderOptions = options || globalOptions;
|
|
3457
3578
|
const fetchOption = loaderOptions.fetch ?? loaderOptions.core?.fetch;
|
|
3579
|
+
let fetchFunction;
|
|
3458
3580
|
if (typeof fetchOption === "function") {
|
|
3459
|
-
|
|
3460
|
-
}
|
|
3461
|
-
|
|
3462
|
-
|
|
3581
|
+
fetchFunction = fetchOption;
|
|
3582
|
+
} else if (isObject(fetchOption)) {
|
|
3583
|
+
fetchFunction = (url, requestOptions) => fetchFile(url, mergeFetchOptions(fetchOption, requestOptions));
|
|
3584
|
+
} else if (context?.fetch) {
|
|
3585
|
+
fetchFunction = context.fetch;
|
|
3586
|
+
} else {
|
|
3587
|
+
fetchFunction = fetchFile;
|
|
3463
3588
|
}
|
|
3464
|
-
|
|
3465
|
-
|
|
3589
|
+
return createAuthenticatedFetch({
|
|
3590
|
+
fetch: fetchFunction,
|
|
3591
|
+
credentials: loaderOptions.core?.credentials || []
|
|
3592
|
+
});
|
|
3593
|
+
}
|
|
3594
|
+
function mergeFetchOptions(defaultOptions, requestOptions) {
|
|
3595
|
+
const options = { ...defaultOptions, ...requestOptions };
|
|
3596
|
+
if (defaultOptions.headers || requestOptions?.headers) {
|
|
3597
|
+
const headers = new Headers(defaultOptions.headers);
|
|
3598
|
+
new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
|
|
3599
|
+
options.headers = headers;
|
|
3466
3600
|
}
|
|
3467
|
-
return
|
|
3601
|
+
return options;
|
|
3468
3602
|
}
|
|
3469
3603
|
|
|
3470
3604
|
// src/lib/api/load-loader.ts
|
|
@@ -3679,7 +3813,7 @@ var __exports__ = (() => {
|
|
|
3679
3813
|
case "geojson-table":
|
|
3680
3814
|
return Array.isArray(table.features);
|
|
3681
3815
|
case "columnar-table":
|
|
3682
|
-
return table.data && typeof table.data === "object";
|
|
3816
|
+
return Boolean(table.data && typeof table.data === "object");
|
|
3683
3817
|
case "arrow-table":
|
|
3684
3818
|
return Boolean(table?.data?.numRows !== void 0);
|
|
3685
3819
|
default:
|
|
@@ -3893,6 +4027,15 @@ var __exports__ = (() => {
|
|
|
3893
4027
|
}
|
|
3894
4028
|
);
|
|
3895
4029
|
}
|
|
4030
|
+
if (selectedLoader && typeof url === "string") {
|
|
4031
|
+
const loaderImplementation = await getLoaderImplementation(
|
|
4032
|
+
selectedLoader,
|
|
4033
|
+
resolvedOptions,
|
|
4034
|
+
url
|
|
4035
|
+
);
|
|
4036
|
+
const parseUrl = loaderImplementation.parseUrl;
|
|
4037
|
+
if (parseUrl) return await parseUrl(url, resolvedOptions, context);
|
|
4038
|
+
}
|
|
3896
4039
|
}
|
|
3897
4040
|
const fetch2 = getFetchFunction(resolvedOptions);
|
|
3898
4041
|
let data = url;
|
|
@@ -4375,18 +4518,29 @@ var __exports__ = (() => {
|
|
|
4375
4518
|
if (path.includes("://")) {
|
|
4376
4519
|
return this._fetch(path, options);
|
|
4377
4520
|
}
|
|
4378
|
-
const file = this.
|
|
4521
|
+
const file = this._getFile(path, true);
|
|
4379
4522
|
if (!file) {
|
|
4380
4523
|
return new Response(path, { status: 400, statusText: "NOT FOUND" });
|
|
4381
4524
|
}
|
|
4382
4525
|
const headers = new Headers(options?.headers);
|
|
4383
4526
|
const range = headers.get("Range");
|
|
4384
|
-
const bytes = range && /bytes=(
|
|
4527
|
+
const bytes = range && /bytes=(\d+)-(\d+)/.exec(range);
|
|
4385
4528
|
if (bytes) {
|
|
4386
4529
|
const start = parseInt(bytes[1]);
|
|
4387
|
-
const end = parseInt(bytes[2]);
|
|
4388
|
-
|
|
4389
|
-
|
|
4530
|
+
const end = Math.min(parseInt(bytes[2]), file.size - 1);
|
|
4531
|
+
if (start > end) {
|
|
4532
|
+
const response3 = new Response(null, {
|
|
4533
|
+
status: 416,
|
|
4534
|
+
headers: { "Content-Range": `bytes */${file.size}` }
|
|
4535
|
+
});
|
|
4536
|
+
Object.defineProperty(response3, "url", { value: path });
|
|
4537
|
+
return response3;
|
|
4538
|
+
}
|
|
4539
|
+
const data = await file.slice(start, end + 1).arrayBuffer();
|
|
4540
|
+
const response2 = new Response(data, {
|
|
4541
|
+
status: 206,
|
|
4542
|
+
headers: { "Content-Range": `bytes ${start}-${end}/${file.size}` }
|
|
4543
|
+
});
|
|
4390
4544
|
Object.defineProperty(response2, "url", { value: path });
|
|
4391
4545
|
return response2;
|
|
4392
4546
|
}
|
|
@@ -4410,7 +4564,7 @@ var __exports__ = (() => {
|
|
|
4410
4564
|
* Return information (size) about files in this file system
|
|
4411
4565
|
*/
|
|
4412
4566
|
async stat(path, options) {
|
|
4413
|
-
const file = this.
|
|
4567
|
+
const file = this._getFile(path, false);
|
|
4414
4568
|
if (!file) {
|
|
4415
4569
|
throw new Error(path);
|
|
4416
4570
|
}
|
|
@@ -4420,19 +4574,22 @@ var __exports__ = (() => {
|
|
|
4420
4574
|
* Just removes the file from the list
|
|
4421
4575
|
*/
|
|
4422
4576
|
async unlink(path) {
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4577
|
+
const file = this._getFile(path, false);
|
|
4578
|
+
if (file) {
|
|
4579
|
+
delete this.files[file.name];
|
|
4580
|
+
delete this.lowerCaseFiles[file.name.toLowerCase()];
|
|
4581
|
+
this.usedFiles[file.name] = true;
|
|
4582
|
+
}
|
|
4426
4583
|
}
|
|
4427
4584
|
// implements IRandomAccessFileSystem
|
|
4428
4585
|
// RANDOM ACCESS
|
|
4429
4586
|
async openReadableFile(pathname, flags) {
|
|
4430
|
-
return new BlobFile(this.
|
|
4587
|
+
return new BlobFile(this._getFile(pathname, true));
|
|
4431
4588
|
}
|
|
4432
4589
|
// PRIVATE
|
|
4433
4590
|
// Supports case independent paths, and file usage tracking
|
|
4434
4591
|
_getFile(path, used) {
|
|
4435
|
-
const file = this.files[path] || this.lowerCaseFiles[path];
|
|
4592
|
+
const file = this.files[path] || this.lowerCaseFiles[path.toLowerCase()];
|
|
4436
4593
|
if (file && used) {
|
|
4437
4594
|
this.usedFiles[path] = true;
|
|
4438
4595
|
}
|