@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/dist/index.cjs
CHANGED
|
@@ -270,17 +270,24 @@ var WorkerJob = class {
|
|
|
270
270
|
this.isRunning = false;
|
|
271
271
|
this._reject(error);
|
|
272
272
|
}
|
|
273
|
-
/**
|
|
274
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Terminates the worker executing this job and rejects its result.
|
|
275
|
+
* @param reason Abort reason supplied by the caller, or a cross-runtime `AbortError`.
|
|
276
|
+
*/
|
|
277
|
+
abort(reason) {
|
|
275
278
|
if (!this.isRunning) {
|
|
276
279
|
return;
|
|
277
280
|
}
|
|
278
|
-
const error =
|
|
279
|
-
error.name = "AbortError";
|
|
281
|
+
const error = reason ?? createAbortError(`Worker job "${this.name}" was aborted`);
|
|
280
282
|
this.workerThread.destroy();
|
|
281
283
|
this.error(error);
|
|
282
284
|
}
|
|
283
285
|
};
|
|
286
|
+
function createAbortError(message) {
|
|
287
|
+
const error = new Error(message);
|
|
288
|
+
error.name = "AbortError";
|
|
289
|
+
return error;
|
|
290
|
+
}
|
|
284
291
|
|
|
285
292
|
// ../worker-utils/src/lib/node/worker_threads-browser.ts
|
|
286
293
|
var NodeWorker = class {
|
|
@@ -748,7 +755,7 @@ function getWorkerName(worker) {
|
|
|
748
755
|
function getWorkerURL(worker, options = {}) {
|
|
749
756
|
var _a;
|
|
750
757
|
const workerOptions = options[worker.id] || {};
|
|
751
|
-
const workerFile = isBrowser2 ? `${worker.id}-worker.js` : `${worker.id}-worker-node.js`;
|
|
758
|
+
const workerFile = isBrowser2 ? `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
|
|
752
759
|
let url = workerOptions.workerUrl;
|
|
753
760
|
if (!url && typeof worker.worker === "string") {
|
|
754
761
|
url = worker.worker;
|
|
@@ -815,7 +822,7 @@ async function processOnWorker(worker, data, options = {}, context = {}, jobCont
|
|
|
815
822
|
// eslint-disable-next-line
|
|
816
823
|
onMessage.bind(null, context)
|
|
817
824
|
);
|
|
818
|
-
const abortJob = () => job.abort();
|
|
825
|
+
const abortJob = () => job.abort(getAbortReason(options.signal));
|
|
819
826
|
(_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abortJob, { once: true });
|
|
820
827
|
if ((_b = options.signal) == null ? void 0 : _b.aborted) {
|
|
821
828
|
abortJob();
|
|
@@ -841,9 +848,15 @@ function throwIfAborted(signal) {
|
|
|
841
848
|
if (!(signal == null ? void 0 : signal.aborted)) {
|
|
842
849
|
return;
|
|
843
850
|
}
|
|
844
|
-
|
|
851
|
+
throw getAbortReason(signal);
|
|
852
|
+
}
|
|
853
|
+
function getAbortReason(signal) {
|
|
854
|
+
return (signal == null ? void 0 : signal.reason) ?? createAbortError2("Worker job was aborted");
|
|
855
|
+
}
|
|
856
|
+
function createAbortError2(message) {
|
|
857
|
+
const error = new Error(message);
|
|
845
858
|
error.name = "AbortError";
|
|
846
|
-
|
|
859
|
+
return error;
|
|
847
860
|
}
|
|
848
861
|
async function onMessage(context, job, type, payload) {
|
|
849
862
|
switch (type) {
|
|
@@ -898,12 +911,12 @@ function canParseWithWorker(loader, options) {
|
|
|
898
911
|
}
|
|
899
912
|
return Boolean(canProcessOnWorker(loader, workerOptions));
|
|
900
913
|
}
|
|
901
|
-
async function parseWithWorker(loader, data, options, context, parseOnMainThread) {
|
|
902
|
-
const
|
|
914
|
+
async function parseWithWorker(loader, data, options, context, parseOnMainThread, signal) {
|
|
915
|
+
const workerSignal = signal || getWorkerAbortSignal(options);
|
|
903
916
|
const result = await processOnWorker(
|
|
904
917
|
loader,
|
|
905
918
|
data,
|
|
906
|
-
{ ...getWorkerOptions(options), signal },
|
|
919
|
+
{ ...getWorkerOptions(options), signal: workerSignal },
|
|
907
920
|
{
|
|
908
921
|
process: async (input, processOptions, _workerContext, parseContext) => {
|
|
909
922
|
if (!parseOnMainThread) {
|
|
@@ -1261,6 +1274,115 @@ var RequestScheduler = class {
|
|
|
1261
1274
|
}
|
|
1262
1275
|
};
|
|
1263
1276
|
|
|
1277
|
+
// ../loader-utils/src/lib/request-utils/request-credentials.ts
|
|
1278
|
+
var AUTHENTICATED_FETCH = /* @__PURE__ */ Symbol("loaders.gl.authenticated-fetch");
|
|
1279
|
+
var refreshPromises = /* @__PURE__ */ new WeakMap();
|
|
1280
|
+
function createAuthenticatedFetch(options) {
|
|
1281
|
+
const baseFetch = options.fetch || ((url, requestOptions) => fetch(url, requestOptions));
|
|
1282
|
+
if (!options.credentials.length) return baseFetch;
|
|
1283
|
+
const existingMetadata = baseFetch[AUTHENTICATED_FETCH];
|
|
1284
|
+
if (existingMetadata === options.credentials) return baseFetch;
|
|
1285
|
+
const authenticatedFetch = async (url, requestOptions = {}) => {
|
|
1286
|
+
var _a, _b, _c;
|
|
1287
|
+
const resolvedURL = parseHTTPURL(url);
|
|
1288
|
+
if (!resolvedURL) return baseFetch(url, requestOptions);
|
|
1289
|
+
const authorization = await authorizeRequest(resolvedURL, requestOptions, options.credentials);
|
|
1290
|
+
const response = await baseFetch(authorization.url, authorization.options);
|
|
1291
|
+
const refreshableCredentials = authorization.credentials.filter(
|
|
1292
|
+
({ credential }) => typeof credential.token === "function" && credential.refreshStatusCodes.includes(response.status)
|
|
1293
|
+
);
|
|
1294
|
+
if (!refreshableCredentials.length || !isReplayableRequest(requestOptions)) return response;
|
|
1295
|
+
if ((_a = requestOptions.signal) == null ? void 0 : _a.aborted) throw createAbortError3();
|
|
1296
|
+
const refreshedTokens = /* @__PURE__ */ new Map();
|
|
1297
|
+
await Promise.all(
|
|
1298
|
+
refreshableCredentials.map(async ({ credential }) => {
|
|
1299
|
+
const token = await refreshCredential(credential, url, response);
|
|
1300
|
+
if (token) refreshedTokens.set(credential, token);
|
|
1301
|
+
})
|
|
1302
|
+
);
|
|
1303
|
+
if (!refreshedTokens.size) return response;
|
|
1304
|
+
await ((_b = response.body) == null ? void 0 : _b.cancel().catch(() => {
|
|
1305
|
+
}));
|
|
1306
|
+
if ((_c = requestOptions.signal) == null ? void 0 : _c.aborted) throw createAbortError3();
|
|
1307
|
+
const replayAuthorization = await authorizeRequest(
|
|
1308
|
+
resolvedURL,
|
|
1309
|
+
requestOptions,
|
|
1310
|
+
options.credentials,
|
|
1311
|
+
refreshedTokens,
|
|
1312
|
+
authorization.credentials
|
|
1313
|
+
);
|
|
1314
|
+
return baseFetch(replayAuthorization.url, replayAuthorization.options);
|
|
1315
|
+
};
|
|
1316
|
+
Object.defineProperty(authenticatedFetch, AUTHENTICATED_FETCH, {
|
|
1317
|
+
value: options.credentials
|
|
1318
|
+
});
|
|
1319
|
+
return authenticatedFetch;
|
|
1320
|
+
}
|
|
1321
|
+
async function authorizeRequest(sourceURL, requestOptions, credentials, tokenOverrides = /* @__PURE__ */ new Map(), previousCredentials = []) {
|
|
1322
|
+
const url = new URL(sourceURL);
|
|
1323
|
+
const headers = new Headers(requestOptions.headers);
|
|
1324
|
+
const resolvedCredentials = [];
|
|
1325
|
+
const previousTokens = new Map(
|
|
1326
|
+
previousCredentials.map(({ credential, token }) => [credential, token])
|
|
1327
|
+
);
|
|
1328
|
+
for (const credential of credentials) {
|
|
1329
|
+
if (!credential.origins.includes(url.origin)) continue;
|
|
1330
|
+
const overrideToken = tokenOverrides.get(credential);
|
|
1331
|
+
const previousToken = previousTokens.get(credential);
|
|
1332
|
+
const ownsQueryParameter = credential.type === "query-parameter" && previousToken !== void 0;
|
|
1333
|
+
const ownsHeader = credential.type === "header" && previousToken !== void 0;
|
|
1334
|
+
if (credential.type === "query-parameter" && url.searchParams.has(credential.name) && !ownsQueryParameter || credential.type === "header" && headers.has(credential.name) && !ownsHeader) {
|
|
1335
|
+
continue;
|
|
1336
|
+
}
|
|
1337
|
+
const token = overrideToken ?? previousToken ?? await resolveToken(credential.token, { url: sourceURL.toString(), reason: "request" });
|
|
1338
|
+
if (!token) continue;
|
|
1339
|
+
if (credential.type === "query-parameter") {
|
|
1340
|
+
url.searchParams.set(credential.name, token);
|
|
1341
|
+
} else {
|
|
1342
|
+
headers.set(credential.name, `${credential.prefix || ""}${token}`);
|
|
1343
|
+
}
|
|
1344
|
+
resolvedCredentials.push({ credential, token });
|
|
1345
|
+
}
|
|
1346
|
+
return {
|
|
1347
|
+
url: url.toString(),
|
|
1348
|
+
options: { ...requestOptions, headers },
|
|
1349
|
+
credentials: resolvedCredentials
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
async function refreshCredential(credential, url, response) {
|
|
1353
|
+
const existingPromise = refreshPromises.get(credential);
|
|
1354
|
+
if (existingPromise) return existingPromise;
|
|
1355
|
+
const tokenProvider = credential.token;
|
|
1356
|
+
const promise = Promise.resolve(
|
|
1357
|
+
tokenProvider({
|
|
1358
|
+
url,
|
|
1359
|
+
reason: "refresh",
|
|
1360
|
+
response: { status: response.status, headers: response.headers }
|
|
1361
|
+
})
|
|
1362
|
+
).finally(() => refreshPromises.delete(credential));
|
|
1363
|
+
refreshPromises.set(credential, promise);
|
|
1364
|
+
return promise;
|
|
1365
|
+
}
|
|
1366
|
+
async function resolveToken(token, context) {
|
|
1367
|
+
return typeof token === "function" ? token(context) : token;
|
|
1368
|
+
}
|
|
1369
|
+
function parseHTTPURL(url) {
|
|
1370
|
+
try {
|
|
1371
|
+
const parsedURL = new URL(url);
|
|
1372
|
+
return ["http:", "https:"].includes(parsedURL.protocol) ? parsedURL : null;
|
|
1373
|
+
} catch {
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
function isReplayableRequest(options) {
|
|
1378
|
+
const method = (options.method || "GET").toUpperCase();
|
|
1379
|
+
if (!["GET", "HEAD", "OPTIONS", "PUT", "DELETE"].includes(method)) return false;
|
|
1380
|
+
return !(options.body && typeof ReadableStream !== "undefined" && options.body instanceof ReadableStream);
|
|
1381
|
+
}
|
|
1382
|
+
function createAbortError3() {
|
|
1383
|
+
return new DOMException("The operation was aborted.", "AbortError");
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1264
1386
|
// ../loader-utils/src/lib/path-utils/file-aliases.ts
|
|
1265
1387
|
var pathPrefix = "";
|
|
1266
1388
|
var fileAliases = {};
|
|
@@ -2742,20 +2864,33 @@ function getIterableFromData(data) {
|
|
|
2742
2864
|
|
|
2743
2865
|
// dist/lib/loader-utils/get-fetch-function.js
|
|
2744
2866
|
function getFetchFunction(options, context) {
|
|
2745
|
-
var _a;
|
|
2867
|
+
var _a, _b;
|
|
2746
2868
|
const globalOptions = getGlobalLoaderOptions();
|
|
2747
2869
|
const loaderOptions = options || globalOptions;
|
|
2748
2870
|
const fetchOption = loaderOptions.fetch ?? ((_a = loaderOptions.core) == null ? void 0 : _a.fetch);
|
|
2871
|
+
let fetchFunction;
|
|
2749
2872
|
if (typeof fetchOption === "function") {
|
|
2750
|
-
|
|
2751
|
-
}
|
|
2752
|
-
|
|
2753
|
-
|
|
2873
|
+
fetchFunction = fetchOption;
|
|
2874
|
+
} else if (isObject(fetchOption)) {
|
|
2875
|
+
fetchFunction = (url, requestOptions) => fetchFile(url, mergeFetchOptions(fetchOption, requestOptions));
|
|
2876
|
+
} else if (context == null ? void 0 : context.fetch) {
|
|
2877
|
+
fetchFunction = context.fetch;
|
|
2878
|
+
} else {
|
|
2879
|
+
fetchFunction = fetchFile;
|
|
2754
2880
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2881
|
+
return createAuthenticatedFetch({
|
|
2882
|
+
fetch: fetchFunction,
|
|
2883
|
+
credentials: ((_b = loaderOptions.core) == null ? void 0 : _b.credentials) || []
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2886
|
+
function mergeFetchOptions(defaultOptions, requestOptions) {
|
|
2887
|
+
const options = { ...defaultOptions, ...requestOptions };
|
|
2888
|
+
if (defaultOptions.headers || (requestOptions == null ? void 0 : requestOptions.headers)) {
|
|
2889
|
+
const headers = new Headers(defaultOptions.headers);
|
|
2890
|
+
new Headers(requestOptions == null ? void 0 : requestOptions.headers).forEach((value, key) => headers.set(key, value));
|
|
2891
|
+
options.headers = headers;
|
|
2757
2892
|
}
|
|
2758
|
-
return
|
|
2893
|
+
return options;
|
|
2759
2894
|
}
|
|
2760
2895
|
|
|
2761
2896
|
// dist/lib/api/load-loader.js
|
|
@@ -2952,7 +3087,7 @@ function isTable(table) {
|
|
|
2952
3087
|
case "geojson-table":
|
|
2953
3088
|
return Array.isArray(table.features);
|
|
2954
3089
|
case "columnar-table":
|
|
2955
|
-
return table.data && typeof table.data === "object";
|
|
3090
|
+
return Boolean(table.data && typeof table.data === "object");
|
|
2956
3091
|
case "arrow-table":
|
|
2957
3092
|
return Boolean(((_a = table == null ? void 0 : table.data) == null ? void 0 : _a.numRows) !== void 0);
|
|
2958
3093
|
default:
|
|
@@ -3148,6 +3283,12 @@ async function load(url, loaders, options, context) {
|
|
|
3148
3283
|
loadInBatches
|
|
3149
3284
|
});
|
|
3150
3285
|
}
|
|
3286
|
+
if (selectedLoader && typeof url === "string") {
|
|
3287
|
+
const loaderImplementation = await getLoaderImplementation(selectedLoader, resolvedOptions, url);
|
|
3288
|
+
const parseUrl = loaderImplementation.parseUrl;
|
|
3289
|
+
if (parseUrl)
|
|
3290
|
+
return await parseUrl(url, resolvedOptions, context);
|
|
3291
|
+
}
|
|
3151
3292
|
}
|
|
3152
3293
|
const fetch2 = getFetchFunction(resolvedOptions);
|
|
3153
3294
|
let data = url;
|
|
@@ -3510,7 +3651,7 @@ function makeStream(source, options) {
|
|
|
3510
3651
|
}
|
|
3511
3652
|
|
|
3512
3653
|
// dist/null-loader.js
|
|
3513
|
-
var VERSION4 = true ? "5.0.0-alpha.
|
|
3654
|
+
var VERSION4 = true ? "5.0.0-alpha.4" : "latest";
|
|
3514
3655
|
var NullWorkerLoader = {
|
|
3515
3656
|
dataType: null,
|
|
3516
3657
|
batchType: null,
|
|
@@ -3628,18 +3769,29 @@ var BrowserFileSystem = class {
|
|
|
3628
3769
|
if (path.includes("://")) {
|
|
3629
3770
|
return this._fetch(path, options);
|
|
3630
3771
|
}
|
|
3631
|
-
const file = this.
|
|
3772
|
+
const file = this._getFile(path, true);
|
|
3632
3773
|
if (!file) {
|
|
3633
3774
|
return new Response(path, { status: 400, statusText: "NOT FOUND" });
|
|
3634
3775
|
}
|
|
3635
3776
|
const headers = new Headers(options == null ? void 0 : options.headers);
|
|
3636
3777
|
const range = headers.get("Range");
|
|
3637
|
-
const bytes = range && /bytes=(
|
|
3778
|
+
const bytes = range && /bytes=(\d+)-(\d+)/.exec(range);
|
|
3638
3779
|
if (bytes) {
|
|
3639
3780
|
const start = parseInt(bytes[1]);
|
|
3640
|
-
const end = parseInt(bytes[2]);
|
|
3641
|
-
|
|
3642
|
-
|
|
3781
|
+
const end = Math.min(parseInt(bytes[2]), file.size - 1);
|
|
3782
|
+
if (start > end) {
|
|
3783
|
+
const response3 = new Response(null, {
|
|
3784
|
+
status: 416,
|
|
3785
|
+
headers: { "Content-Range": `bytes */${file.size}` }
|
|
3786
|
+
});
|
|
3787
|
+
Object.defineProperty(response3, "url", { value: path });
|
|
3788
|
+
return response3;
|
|
3789
|
+
}
|
|
3790
|
+
const data = await file.slice(start, end + 1).arrayBuffer();
|
|
3791
|
+
const response2 = new Response(data, {
|
|
3792
|
+
status: 206,
|
|
3793
|
+
headers: { "Content-Range": `bytes ${start}-${end}/${file.size}` }
|
|
3794
|
+
});
|
|
3643
3795
|
Object.defineProperty(response2, "url", { value: path });
|
|
3644
3796
|
return response2;
|
|
3645
3797
|
}
|
|
@@ -3663,7 +3815,7 @@ var BrowserFileSystem = class {
|
|
|
3663
3815
|
* Return information (size) about files in this file system
|
|
3664
3816
|
*/
|
|
3665
3817
|
async stat(path, options) {
|
|
3666
|
-
const file = this.
|
|
3818
|
+
const file = this._getFile(path, false);
|
|
3667
3819
|
if (!file) {
|
|
3668
3820
|
throw new Error(path);
|
|
3669
3821
|
}
|
|
@@ -3673,19 +3825,22 @@ var BrowserFileSystem = class {
|
|
|
3673
3825
|
* Just removes the file from the list
|
|
3674
3826
|
*/
|
|
3675
3827
|
async unlink(path) {
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3828
|
+
const file = this._getFile(path, false);
|
|
3829
|
+
if (file) {
|
|
3830
|
+
delete this.files[file.name];
|
|
3831
|
+
delete this.lowerCaseFiles[file.name.toLowerCase()];
|
|
3832
|
+
this.usedFiles[file.name] = true;
|
|
3833
|
+
}
|
|
3679
3834
|
}
|
|
3680
3835
|
// implements IRandomAccessFileSystem
|
|
3681
3836
|
// RANDOM ACCESS
|
|
3682
3837
|
async openReadableFile(pathname, flags) {
|
|
3683
|
-
return new BlobFile(this.
|
|
3838
|
+
return new BlobFile(this._getFile(pathname, true));
|
|
3684
3839
|
}
|
|
3685
3840
|
// PRIVATE
|
|
3686
3841
|
// Supports case independent paths, and file usage tracking
|
|
3687
3842
|
_getFile(path, used) {
|
|
3688
|
-
const file = this.files[path] || this.lowerCaseFiles[path];
|
|
3843
|
+
const file = this.files[path] || this.lowerCaseFiles[path.toLowerCase()];
|
|
3689
3844
|
if (file && used) {
|
|
3690
3845
|
this.usedFiles[path] = true;
|
|
3691
3846
|
}
|