@loaders.gl/scan 5.0.0-alpha.10
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 +52 -0
- package/README.md +219 -0
- package/dist/delta.cjs +25568 -0
- package/dist/delta.cjs.map +6 -0
- package/dist/delta.d.ts +11 -0
- package/dist/delta.d.ts.map +1 -0
- package/dist/delta.js +12 -0
- package/dist/delta.js.map +1 -0
- package/dist/dist.min.js +18535 -0
- package/dist/federated-table-scan-source.d.ts +116 -0
- package/dist/federated-table-scan-source.d.ts.map +1 -0
- package/dist/federated-table-scan-source.js +691 -0
- package/dist/federated-table-scan-source.js.map +1 -0
- package/dist/hudi.cjs +25405 -0
- package/dist/hudi.cjs.map +6 -0
- package/dist/hudi.d.ts +58 -0
- package/dist/hudi.d.ts.map +1 -0
- package/dist/hudi.js +147 -0
- package/dist/hudi.js.map +1 -0
- package/dist/iceberg.cjs +27662 -0
- package/dist/iceberg.cjs.map +6 -0
- package/dist/iceberg.d.ts +12 -0
- package/dist/iceberg.d.ts.map +1 -0
- package/dist/iceberg.js +12 -0
- package/dist/iceberg.js.map +1 -0
- package/dist/index.cjs +3540 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/scan-engine.d.ts +44 -0
- package/dist/scan-engine.d.ts.map +1 -0
- package/dist/scan-engine.js +51 -0
- package/dist/scan-engine.js.map +1 -0
- package/dist/scan-query.d.ts +24 -0
- package/dist/scan-query.d.ts.map +1 -0
- package/dist/scan-query.js +5 -0
- package/dist/scan-query.js.map +1 -0
- package/dist/vector-table-scan-source.d.ts +92 -0
- package/dist/vector-table-scan-source.d.ts.map +1 -0
- package/dist/vector-table-scan-source.js +220 -0
- package/dist/vector-table-scan-source.js.map +1 -0
- package/package.json +66 -0
- package/src/delta.ts +18 -0
- package/src/federated-table-scan-source.ts +991 -0
- package/src/hudi.ts +235 -0
- package/src/iceberg.ts +36 -0
- package/src/index.ts +97 -0
- package/src/scan-engine.ts +100 -0
- package/src/scan-query.ts +27 -0
- package/src/vector-table-scan-source.ts +300 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
loaders.gl is licensed under the MIT license
|
|
2
|
+
|
|
3
|
+
Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Copyright (c) 2015 Uber Technologies, Inc.
|
|
26
|
+
|
|
27
|
+
Portions of modules/images/src/lib/category-api/binary-image-api.ts are based on
|
|
28
|
+
binary-gltf-utils (https://github.com/Qantas94Heavy/binary-gltf-utils) under the
|
|
29
|
+
MIT License reproduced above.
|
|
30
|
+
|
|
31
|
+
Copyright (c) 2016-17 Karl Cheng
|
|
32
|
+
|
|
33
|
+
Portions of modules/schema-utils/src/lib/utils/async-queue.ts are adapted from
|
|
34
|
+
async-iter-demo (https://github.com/rauschma/async-iter-demo) under the MIT
|
|
35
|
+
License reproduced above.
|
|
36
|
+
|
|
37
|
+
Copyright (c) 2016 Axel Rauschmayer
|
|
38
|
+
|
|
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.
|
|
41
|
+
|
|
42
|
+
Copyright 2011-2018 CesiumJS Contributors
|
|
43
|
+
|
|
44
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
45
|
+
you may not use this file except in compliance with the License.
|
|
46
|
+
You may obtain a copy of the License at
|
|
47
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
48
|
+
|
|
49
|
+
Unless required by applicable law or agreed to in writing, software
|
|
50
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
51
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
52
|
+
See the License for the specific language governing permissions and limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# @loaders.gl/scan
|
|
2
|
+
|
|
3
|
+
Optional scan planning and execution for loaders.gl.
|
|
4
|
+
|
|
5
|
+
The package has one public entry point. Arrow is the built-in reference executor and establishes
|
|
6
|
+
the portable query semantics used by future backends.
|
|
7
|
+
|
|
8
|
+
```typescript
|
|
9
|
+
import {createScanEngine, parseSQLPredicate} from '@loaders.gl/scan';
|
|
10
|
+
|
|
11
|
+
const engine = await createScanEngine();
|
|
12
|
+
const result = engine.query(table, {
|
|
13
|
+
predicate: parseSQLPredicate('population >= 1000000'),
|
|
14
|
+
columns: ['name', 'population'],
|
|
15
|
+
limit: 100
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The experimental asynchronous path is available on the same engine. It preserves the result
|
|
20
|
+
semantics while allowing a registered backend to schedule remote or compiled work:
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
const result = await engine.queryAsync(table, {
|
|
24
|
+
predicate: parseSQLPredicate('population >= 1000000'),
|
|
25
|
+
limit: 100
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Synchronous backends are wrapped automatically. GPU backends may use this boundary as a staging
|
|
30
|
+
point, but GPU graph compilation and resource ownership remain backend-specific.
|
|
31
|
+
|
|
32
|
+
Optional backends can register a lazy loader without adding backend-specific imports to application
|
|
33
|
+
code:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import {createScanEngine, registerScanBackend} from '@loaders.gl/scan';
|
|
37
|
+
|
|
38
|
+
registerScanBackend('custom', async () => {
|
|
39
|
+
const {createCustomBackend} = await import('./custom-backend');
|
|
40
|
+
return createCustomBackend();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const engine = await createScanEngine({backend: 'custom'});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Format packages should depend on the lightweight scan contracts in `@loaders.gl/loader-utils` and
|
|
47
|
+
should not import this package merely to expose metadata or a native scan adapter. Applications opt
|
|
48
|
+
into this package when they want the shared planner or Arrow executor.
|
|
49
|
+
|
|
50
|
+
The same boundary applies to table execution. `executeTableScanBatches()` is the reusable residual
|
|
51
|
+
executor for object-row, columnar, GeoJSON, and Arrow-shaped batches. It owns filtering, projection,
|
|
52
|
+
global limits, cancellation, and terminal telemetry; a format adapter only supplies its parser's
|
|
53
|
+
batch reader. The helper is re-exported from `@loaders.gl/scan` for applications building custom
|
|
54
|
+
adapters, while format packages import it from `@loaders.gl/loader-utils`. This keeps the common
|
|
55
|
+
implementation in one place without making a CSV, JSON, or other format root import the optional
|
|
56
|
+
scan runtime (and therefore preserves tree-shaking for users who never scan).
|
|
57
|
+
|
|
58
|
+
Arrow-backed formats use the same layering for materialized queries. `queryArrowTable()` lives in
|
|
59
|
+
`@loaders.gl/schema-utils`, which already owns Arrow schema and vector utilities. ORC, GeoPackage,
|
|
60
|
+
and FlatGeobuf provide only their predicate evaluator and source-specific pruning; projection,
|
|
61
|
+
row-index gathering, vector reconstruction, and limits are shared. This keeps format adapters
|
|
62
|
+
small while avoiding a dependency from those packages on the optional scan runtime.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import {executeTableScanBatches} from '@loaders.gl/scan';
|
|
66
|
+
|
|
67
|
+
const result = executeTableScanBatches(
|
|
68
|
+
(signal, onByteLength) => parser.readBatches({signal, onByteLength}),
|
|
69
|
+
{columns: ['id'], limit: 100}
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The package also provides the application-facing query state and metadata vocabulary used by
|
|
74
|
+
metadata-driven controls. These are deliberately framework-neutral:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import type {ScanQuery, ScanQueryMetadata} from '@loaders.gl/scan';
|
|
78
|
+
|
|
79
|
+
const query: ScanQuery = {columns: ['name'], limit: 25};
|
|
80
|
+
async function discover(source: {getQueryMetadata(): Promise<ScanQueryMetadata>}) {
|
|
81
|
+
return await source.getQueryMetadata();
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`ScanQuery` is a portable control shape. Sources normalize unsupported fields and advertise their
|
|
86
|
+
actual capabilities through `ScanQueryMetadata`; no React, GPU, or database dependency is pulled
|
|
87
|
+
into applications that only use a format loader.
|
|
88
|
+
|
|
89
|
+
Metadata also makes the execution conclusion explicit:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const metadata = await source.getQueryMetadata();
|
|
93
|
+
|
|
94
|
+
if (metadata.execution.status === 'supported') {
|
|
95
|
+
console.log(`Execute with source.${metadata.execution.method}()`);
|
|
96
|
+
} else {
|
|
97
|
+
console.log(`Discovery only: ${metadata.execution.reason}`);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
A supported table source names `read()` or `query()`, a raster source names `getRaster()`, and a
|
|
102
|
+
point-cloud source names `scan()`. Metadata-only sources must supply a user-facing reason. This
|
|
103
|
+
keeps query panels and support documentation from inferring readiness from optimization
|
|
104
|
+
capabilities: a residual operator is fully supported even though it performs more work, while a
|
|
105
|
+
metadata-only source never presents an executable scan.
|
|
106
|
+
|
|
107
|
+
Point-cloud sources implement `PointCloudScanSource` and can share
|
|
108
|
+
`selectPointCloudScanTiles()`. The planner traverses hierarchy nodes in deterministic breadth-first
|
|
109
|
+
order, prunes by bounds, level, and spacing, and leaves exact point bounds and attribute predicates
|
|
110
|
+
to the physical adapter. COPC and Potree use this contract to emit bounded Arrow batches with one
|
|
111
|
+
global limit.
|
|
112
|
+
|
|
113
|
+
Raster sources implement `getRaster()` and publish raster-specific capabilities independently of
|
|
114
|
+
table operators. NetCDF supports numeric variable selection and named dimension index or half-open
|
|
115
|
+
range slices. GeoTIFF, OME-TIFF, GeoZarr, and OME-Zarr retain their format-specific window, level,
|
|
116
|
+
channel, and chunk planners behind the same metadata vocabulary.
|
|
117
|
+
|
|
118
|
+
## Ordered append federation
|
|
119
|
+
|
|
120
|
+
`FederatedTableScanSource` exposes multiple managed table sources as one ordered Arrow stream. It
|
|
121
|
+
uses `DataSourceManager` as the authoritative registry and resource owner; federation does not add
|
|
122
|
+
a second loader registry, cache, or lifecycle system.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import {DataSourceManager} from '@loaders.gl/loader-utils';
|
|
126
|
+
import {FederatedTableScanSource, parseSQLPredicate} from '@loaders.gl/scan';
|
|
127
|
+
|
|
128
|
+
const dataSourceManager = new DataSourceManager();
|
|
129
|
+
dataSourceManager.add({dataSourceId: 'current', dataSource: currentSource});
|
|
130
|
+
dataSourceManager.add({dataSourceId: 'archive', dataSource: archiveSource});
|
|
131
|
+
|
|
132
|
+
const history = new FederatedTableScanSource(dataSourceManager, {
|
|
133
|
+
schemaPolicy: 'union',
|
|
134
|
+
sources: [
|
|
135
|
+
{dataSourceId: 'current'},
|
|
136
|
+
{
|
|
137
|
+
dataSourceId: 'archive',
|
|
138
|
+
query: {predicate: parseSQLPredicate('year >= 2020')},
|
|
139
|
+
columnMapping: {station_id: 'stationId'}
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
for await (const batch of history.read({
|
|
145
|
+
columns: ['stationId', 'temperature'],
|
|
146
|
+
limit: 100
|
|
147
|
+
})) {
|
|
148
|
+
console.log(batch.sourceId, batch.data);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The source list is the stable result order: every surviving row from the first source precedes
|
|
153
|
+
every surviving row from the second. Each source may have a source-local predicate, projection,
|
|
154
|
+
and limit. Explicit `columnMapping` entries rename physical columns before schemas are compared.
|
|
155
|
+
The global predicate and projection run against those mapped names.
|
|
156
|
+
|
|
157
|
+
Two reconciliation policies are available:
|
|
158
|
+
|
|
159
|
+
- `strict` (the default) requires every source to expose the same mapped column names and exact
|
|
160
|
+
portable data types. Physical column order may differ.
|
|
161
|
+
- `union` creates columns in first-seen order and supplies typed nulls where a source lacks a
|
|
162
|
+
column. A column becomes nullable when it is absent from any source.
|
|
163
|
+
|
|
164
|
+
Applications that require a stable output contract can provide `outputSchema`. The executor
|
|
165
|
+
reorders fields and performs only declared lossless normalization: safe numeric widening,
|
|
166
|
+
dictionary-to-value conversion, and Arrow view-to-value conversion. It rejects lossy casts,
|
|
167
|
+
implicit string conversion, removal of nullability, and missing required fields during planning.
|
|
168
|
+
|
|
169
|
+
The caller's limit is global, not per source. Once it is reached, the active iterator is closed and
|
|
170
|
+
later sources are not opened. Cancellation is observed during asynchronous source resolution and
|
|
171
|
+
between physical batches. Every emitted batch carries `sourceId`, `sourceIndex`, and
|
|
172
|
+
`sourceBatchIndex`, while its metadata retains the original physical batch metadata under
|
|
173
|
+
`sourceMetadata`.
|
|
174
|
+
|
|
175
|
+
Metadata discovery, explanation, and reads subscribe to all referenced sources for the duration of
|
|
176
|
+
the operation. Their `DataSourceManager` subscriptions are released on success, error,
|
|
177
|
+
cancellation, a satisfied limit, or an early consumer return. This preserves the manager's existing
|
|
178
|
+
replacement, deferred-id, non-persistent pruning, and lifecycle behavior.
|
|
179
|
+
|
|
180
|
+
`DataSourceManager.discoverDataSources({queryType: 'table'})` provides picker-safe discovery. It
|
|
181
|
+
returns ids, lifecycle state, compatibility, and query metadata, but never exposes the managed
|
|
182
|
+
source object. `read({onTelemetry})` reports terminal aggregate and per-source counters including
|
|
183
|
+
files and tasks opened, bytes fetched, batches decoded, rows tested and retained, pruning, source
|
|
184
|
+
timings, early termination, and cancellation when the physical source can measure them.
|
|
185
|
+
|
|
186
|
+
Append federation is deliberately not a distributed SQL engine. It does not reorder sources,
|
|
187
|
+
parallelize reads, coerce incompatible data types, or join managed sources. It provides one
|
|
188
|
+
predictable `UNION ALL`-style scan over sources that already implement `TableScanSource`.
|
|
189
|
+
|
|
190
|
+
## Addressed vector tables
|
|
191
|
+
|
|
192
|
+
Specialized tile and service controls stay outside the portable relational query. Applications can
|
|
193
|
+
bind one vector tile or one bounded feature request, then expose the resulting Arrow feature table
|
|
194
|
+
through the same metadata, explain, and `read()` surface:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import {VectorTileTableScanSource} from '@loaders.gl/scan';
|
|
198
|
+
|
|
199
|
+
const tileTable = new VectorTileTableScanSource(mvtSource, {
|
|
200
|
+
sourceType: 'mvt-tile-table',
|
|
201
|
+
tile: {x: 2, y: 6, z: 4, layers: ['places']}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const metadata = await tileTable.getQueryMetadata();
|
|
205
|
+
for await (const batch of tileTable.read({
|
|
206
|
+
predicate: parseSQLPredicate('population >= 1000000'),
|
|
207
|
+
columns: ['name', 'population'],
|
|
208
|
+
limit: 25
|
|
209
|
+
})) {
|
|
210
|
+
// Arrow feature table batch
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Configure MVT and vector PMTiles sources with `shape: 'arrow-table'`. The corresponding
|
|
215
|
+
`VectorFeatureTableScanSource` requests Arrow output from bounded vector sources such as WFS and
|
|
216
|
+
ArcGIS FeatureServer. Tile coordinates, selected layers, service bounds, and CRS remain immutable
|
|
217
|
+
source parameters; predicates, projection, ordering, aggregates, and limits remain portable query
|
|
218
|
+
operators. Both adapters cache the addressed result between metadata discovery and execution, so a
|
|
219
|
+
query panel does not repeat the network request.
|