@loaders.gl/core 5.0.0-alpha.1 → 5.0.0-alpha.3
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 +14 -3
- package/dist/dist.dev.js +416 -151
- package/dist/dist.min.js +3 -3
- package/dist/index.cjs +1944 -245
- package/dist/index.cjs.map +3 -4
- package/dist/iterators/make-iterator/make-stream-iterator.js +49 -10
- package/dist/iterators/make-iterator/make-stream-iterator.js.map +1 -1
- package/dist/lib/api/load-loader.js +1 -7
- package/dist/lib/api/load-loader.js.map +1 -1
- package/dist/lib/api/load.d.ts.map +1 -1
- package/dist/lib/api/load.js +24 -3
- package/dist/lib/api/load.js.map +1 -1
- package/dist/lib/api/parse.d.ts.map +1 -1
- package/dist/lib/api/parse.js +4 -1
- package/dist/lib/api/parse.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/iterators/make-iterator/make-stream-iterator.ts +48 -10
- package/src/lib/api/load-loader.ts +2 -13
- package/src/lib/api/load.ts +44 -4
- package/src/lib/api/parse.ts +5 -0
- package/src/lib/filesystems/browser-filesystem.ts +25 -11
- package/src/lib/loader-utils/get-fetch-function.ts +23 -12
package/src/lib/api/load.ts
CHANGED
|
@@ -13,7 +13,8 @@ import type {
|
|
|
13
13
|
LoaderReturnType,
|
|
14
14
|
LoaderArrayOptionsType,
|
|
15
15
|
LoaderArrayReturnType,
|
|
16
|
-
SourceLoader
|
|
16
|
+
SourceLoader,
|
|
17
|
+
LoaderWithParser
|
|
17
18
|
} from '@loaders.gl/loader-utils';
|
|
18
19
|
import {isBlob, isSourceLoader} from '@loaders.gl/loader-utils';
|
|
19
20
|
import {isLoaderObject} from '../loader-utils/normalize-loader';
|
|
@@ -27,6 +28,7 @@ import {parseSync} from './parse-sync';
|
|
|
27
28
|
import {parseInBatches} from './parse-in-batches';
|
|
28
29
|
import {loadInBatches} from './load-in-batches';
|
|
29
30
|
import {selectLoader} from './select-loader';
|
|
31
|
+
import {getLoaderImplementation} from './load-loader';
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* Parses `data` using a specified loader
|
|
@@ -94,6 +96,7 @@ export async function load(
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
if (!Array.isArray(resolvedLoaders) && isSourceLoader(resolvedLoaders)) {
|
|
99
|
+
const sourceLoader = await resolveSourceLoader(resolvedLoaders, url, resolvedOptions);
|
|
97
100
|
const runtimeCoreApi = {
|
|
98
101
|
fetchFile,
|
|
99
102
|
parse,
|
|
@@ -103,7 +106,7 @@ export async function load(
|
|
|
103
106
|
load,
|
|
104
107
|
loadInBatches
|
|
105
108
|
};
|
|
106
|
-
return
|
|
109
|
+
return sourceLoader.createDataSource(
|
|
107
110
|
url as string | Blob,
|
|
108
111
|
(resolvedOptions || {}) as LoaderOptionsType<SourceLoader>,
|
|
109
112
|
runtimeCoreApi
|
|
@@ -115,6 +118,7 @@ export async function load(
|
|
|
115
118
|
resolvedLoaders.length === 1 &&
|
|
116
119
|
isSourceLoader(resolvedLoaders[0])
|
|
117
120
|
) {
|
|
121
|
+
const sourceLoader = await resolveSourceLoader(resolvedLoaders[0], url, resolvedOptions);
|
|
118
122
|
const runtimeCoreApi = {
|
|
119
123
|
fetchFile,
|
|
120
124
|
parse,
|
|
@@ -124,7 +128,7 @@ export async function load(
|
|
|
124
128
|
load,
|
|
125
129
|
loadInBatches
|
|
126
130
|
};
|
|
127
|
-
return
|
|
131
|
+
return sourceLoader.createDataSource(
|
|
128
132
|
url as string | Blob,
|
|
129
133
|
(resolvedOptions || {}) as LoaderOptionsType<SourceLoader>,
|
|
130
134
|
runtimeCoreApi
|
|
@@ -138,7 +142,8 @@ export async function load(
|
|
|
138
142
|
});
|
|
139
143
|
|
|
140
144
|
if (selectedLoader && isSourceLoader(selectedLoader)) {
|
|
141
|
-
|
|
145
|
+
const sourceLoader = await resolveSourceLoader(selectedLoader, url, resolvedOptions);
|
|
146
|
+
return sourceLoader.createDataSource(
|
|
142
147
|
url,
|
|
143
148
|
(resolvedOptions || {}) as LoaderOptionsType<SourceLoader>,
|
|
144
149
|
{
|
|
@@ -152,6 +157,24 @@ export async function load(
|
|
|
152
157
|
}
|
|
153
158
|
);
|
|
154
159
|
}
|
|
160
|
+
|
|
161
|
+
if (selectedLoader && typeof url === 'string') {
|
|
162
|
+
const loaderImplementation = await getLoaderImplementation(
|
|
163
|
+
selectedLoader,
|
|
164
|
+
resolvedOptions,
|
|
165
|
+
url
|
|
166
|
+
);
|
|
167
|
+
const parseUrl = (
|
|
168
|
+
loaderImplementation as LoaderWithParser & {
|
|
169
|
+
parseUrl?: (
|
|
170
|
+
url: string,
|
|
171
|
+
options?: LoaderOptions,
|
|
172
|
+
context?: LoaderContext
|
|
173
|
+
) => Promise<unknown>;
|
|
174
|
+
}
|
|
175
|
+
).parseUrl;
|
|
176
|
+
if (parseUrl) return await parseUrl(url, resolvedOptions, context);
|
|
177
|
+
}
|
|
155
178
|
}
|
|
156
179
|
|
|
157
180
|
// Select fetch function
|
|
@@ -190,3 +213,20 @@ export async function load(
|
|
|
190
213
|
? await parse(data, resolvedLoaders, resolvedOptions, context) // loader array overload
|
|
191
214
|
: await parse(data, resolvedLoaders, resolvedOptions, context); // single loader overload
|
|
192
215
|
}
|
|
216
|
+
|
|
217
|
+
/** Resolves a lightweight source loader into its runtime implementation when necessary. */
|
|
218
|
+
async function resolveSourceLoader(
|
|
219
|
+
loader: SourceLoader,
|
|
220
|
+
url: string | DataType,
|
|
221
|
+
options?: LoaderOptions
|
|
222
|
+
): Promise<SourceLoader> {
|
|
223
|
+
if (!loader.preload) {
|
|
224
|
+
return loader;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const sourceLoader = await loader.preload(typeof url === 'string' ? url : '', options);
|
|
228
|
+
if (!isSourceLoader(sourceLoader)) {
|
|
229
|
+
throw new Error(`${loader.id} source loader preload() did not return a runtime source loader`);
|
|
230
|
+
}
|
|
231
|
+
return sourceLoader;
|
|
232
|
+
}
|
package/src/lib/api/parse.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
canParseWithWorker,
|
|
22
22
|
mergeOptions,
|
|
23
23
|
isResponse,
|
|
24
|
+
isBlob,
|
|
24
25
|
isSourceLoader
|
|
25
26
|
} from '@loaders.gl/loader-utils';
|
|
26
27
|
import {validateWorkerVersion} from '@loaders.gl/worker-utils';
|
|
@@ -160,6 +161,10 @@ async function parseWithLoader(
|
|
|
160
161
|
return await parseWithWorker(loaderWithParser, data, options, context, parse);
|
|
161
162
|
}
|
|
162
163
|
|
|
164
|
+
if (isBlob(data) && loaderWithParser.parseBlob) {
|
|
165
|
+
return await loaderWithParser.parseBlob(data, options, context);
|
|
166
|
+
}
|
|
167
|
+
|
|
163
168
|
data = await getArrayBufferOrStringFromData(data, loader, options);
|
|
164
169
|
|
|
165
170
|
return await parseWithLoaderImplementation(loaderWithParser, data, options, context);
|
|
@@ -50,23 +50,34 @@ export class BrowserFileSystem implements FileSystem {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// Local fetches are served from the list of files
|
|
53
|
-
const file = this.
|
|
53
|
+
const file = this._getFile(path, true);
|
|
54
54
|
if (!file) {
|
|
55
55
|
return new Response(path, {status: 400, statusText: 'NOT FOUND'});
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const headers = new Headers(options?.headers);
|
|
59
59
|
const range = headers.get('Range');
|
|
60
|
-
const bytes = range && /bytes=(
|
|
60
|
+
const bytes = range && /bytes=(\d+)-(\d+)/.exec(range);
|
|
61
61
|
|
|
62
62
|
if (bytes) {
|
|
63
63
|
const start = parseInt(bytes[1]);
|
|
64
|
-
const end = parseInt(bytes[2]);
|
|
64
|
+
const end = Math.min(parseInt(bytes[2]), file.size - 1);
|
|
65
|
+
if (start > end) {
|
|
66
|
+
const response = new Response(null, {
|
|
67
|
+
status: 416,
|
|
68
|
+
headers: {'Content-Range': `bytes */${file.size}`}
|
|
69
|
+
});
|
|
70
|
+
Object.defineProperty(response, 'url', {value: path});
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
65
73
|
// The trick when reading File objects is to read successive "slices" of the File
|
|
66
74
|
// Per spec https://w3c.github.io/FileAPI/, slicing a File should only update the start and end fields
|
|
67
75
|
// Actually reading from file should happen in `readAsArrayBuffer` (and as far we can tell it does)
|
|
68
|
-
const data = await file.slice(start, end).arrayBuffer();
|
|
69
|
-
const response = new Response(data
|
|
76
|
+
const data = await file.slice(start, end + 1).arrayBuffer();
|
|
77
|
+
const response = new Response(data, {
|
|
78
|
+
status: 206,
|
|
79
|
+
headers: {'Content-Range': `bytes ${start}-${end}/${file.size}`}
|
|
80
|
+
});
|
|
70
81
|
Object.defineProperty(response, 'url', {value: path});
|
|
71
82
|
return response;
|
|
72
83
|
}
|
|
@@ -95,7 +106,7 @@ export class BrowserFileSystem implements FileSystem {
|
|
|
95
106
|
* Return information (size) about files in this file system
|
|
96
107
|
*/
|
|
97
108
|
async stat(path: string, options?: object): Promise<{size: number}> {
|
|
98
|
-
const file = this.
|
|
109
|
+
const file = this._getFile(path, false);
|
|
99
110
|
if (!file) {
|
|
100
111
|
throw new Error(path);
|
|
101
112
|
}
|
|
@@ -106,16 +117,19 @@ export class BrowserFileSystem implements FileSystem {
|
|
|
106
117
|
* Just removes the file from the list
|
|
107
118
|
*/
|
|
108
119
|
async unlink(path: string): Promise<void> {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
const file = this._getFile(path, false);
|
|
121
|
+
if (file) {
|
|
122
|
+
delete this.files[file.name];
|
|
123
|
+
delete this.lowerCaseFiles[file.name.toLowerCase()];
|
|
124
|
+
this.usedFiles[file.name] = true;
|
|
125
|
+
}
|
|
112
126
|
}
|
|
113
127
|
|
|
114
128
|
// implements IRandomAccessFileSystem
|
|
115
129
|
|
|
116
130
|
// RANDOM ACCESS
|
|
117
131
|
async openReadableFile(pathname: string, flags: unknown): Promise<ReadableFile> {
|
|
118
|
-
return new BlobFile(this.
|
|
132
|
+
return new BlobFile(this._getFile(pathname, true));
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
// PRIVATE
|
|
@@ -123,7 +137,7 @@ export class BrowserFileSystem implements FileSystem {
|
|
|
123
137
|
// Supports case independent paths, and file usage tracking
|
|
124
138
|
_getFile(path: string, used: boolean): File {
|
|
125
139
|
// Prefer case match, but fall back to case independent.
|
|
126
|
-
const file = this.files[path] || this.lowerCaseFiles[path];
|
|
140
|
+
const file = this.files[path] || this.lowerCaseFiles[path.toLowerCase()];
|
|
127
141
|
if (file && used) {
|
|
128
142
|
this.usedFiles[path] = true;
|
|
129
143
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import type {LoaderContext, LoaderOptions, FetchLike} from '@loaders.gl/loader-utils';
|
|
6
|
-
import {isObject} from '@loaders.gl/loader-utils';
|
|
6
|
+
import {createAuthenticatedFetch, isObject} from '@loaders.gl/loader-utils';
|
|
7
7
|
import {fetchFile} from '../fetch/fetch-file';
|
|
8
8
|
import {getGlobalLoaderOptions} from './option-utils';
|
|
9
9
|
|
|
@@ -21,22 +21,33 @@ export function getFetchFunction(
|
|
|
21
21
|
|
|
22
22
|
const loaderOptions = options || globalOptions;
|
|
23
23
|
const fetchOption = loaderOptions.fetch ?? loaderOptions.core?.fetch;
|
|
24
|
+
let fetchFunction: FetchLike;
|
|
24
25
|
|
|
25
26
|
// options.fetch can be a function
|
|
26
27
|
if (typeof fetchOption === 'function') {
|
|
27
|
-
|
|
28
|
+
fetchFunction = fetchOption;
|
|
29
|
+
} else if (isObject(fetchOption)) {
|
|
30
|
+
fetchFunction = (url, requestOptions) =>
|
|
31
|
+
fetchFile(url, mergeFetchOptions(fetchOption as RequestInit, requestOptions));
|
|
32
|
+
} else if (context?.fetch) {
|
|
33
|
+
fetchFunction = context.fetch;
|
|
34
|
+
} else {
|
|
35
|
+
fetchFunction = fetchFile;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
38
|
+
return createAuthenticatedFetch({
|
|
39
|
+
fetch: fetchFunction,
|
|
40
|
+
credentials: loaderOptions.core?.credentials || []
|
|
41
|
+
});
|
|
42
|
+
}
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
/** Combines static and per-request fetch options without replacing either header collection. */
|
|
45
|
+
function mergeFetchOptions(defaultOptions: RequestInit, requestOptions?: RequestInit): RequestInit {
|
|
46
|
+
const options = {...defaultOptions, ...requestOptions};
|
|
47
|
+
if (defaultOptions.headers || requestOptions?.headers) {
|
|
48
|
+
const headers = new Headers(defaultOptions.headers);
|
|
49
|
+
new Headers(requestOptions?.headers).forEach((value, key) => headers.set(key, value));
|
|
50
|
+
options.headers = headers;
|
|
38
51
|
}
|
|
39
|
-
|
|
40
|
-
// else return the default fetch function
|
|
41
|
-
return fetchFile;
|
|
52
|
+
return options;
|
|
42
53
|
}
|