@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.
Files changed (52) hide show
  1. package/LICENSE +52 -0
  2. package/README.md +219 -0
  3. package/dist/delta.cjs +25568 -0
  4. package/dist/delta.cjs.map +6 -0
  5. package/dist/delta.d.ts +11 -0
  6. package/dist/delta.d.ts.map +1 -0
  7. package/dist/delta.js +12 -0
  8. package/dist/delta.js.map +1 -0
  9. package/dist/dist.min.js +18535 -0
  10. package/dist/federated-table-scan-source.d.ts +116 -0
  11. package/dist/federated-table-scan-source.d.ts.map +1 -0
  12. package/dist/federated-table-scan-source.js +691 -0
  13. package/dist/federated-table-scan-source.js.map +1 -0
  14. package/dist/hudi.cjs +25405 -0
  15. package/dist/hudi.cjs.map +6 -0
  16. package/dist/hudi.d.ts +58 -0
  17. package/dist/hudi.d.ts.map +1 -0
  18. package/dist/hudi.js +147 -0
  19. package/dist/hudi.js.map +1 -0
  20. package/dist/iceberg.cjs +27662 -0
  21. package/dist/iceberg.cjs.map +6 -0
  22. package/dist/iceberg.d.ts +12 -0
  23. package/dist/iceberg.d.ts.map +1 -0
  24. package/dist/iceberg.js +12 -0
  25. package/dist/iceberg.js.map +1 -0
  26. package/dist/index.cjs +3540 -0
  27. package/dist/index.cjs.map +6 -0
  28. package/dist/index.d.ts +15 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +14 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/scan-engine.d.ts +44 -0
  33. package/dist/scan-engine.d.ts.map +1 -0
  34. package/dist/scan-engine.js +51 -0
  35. package/dist/scan-engine.js.map +1 -0
  36. package/dist/scan-query.d.ts +24 -0
  37. package/dist/scan-query.d.ts.map +1 -0
  38. package/dist/scan-query.js +5 -0
  39. package/dist/scan-query.js.map +1 -0
  40. package/dist/vector-table-scan-source.d.ts +92 -0
  41. package/dist/vector-table-scan-source.d.ts.map +1 -0
  42. package/dist/vector-table-scan-source.js +220 -0
  43. package/dist/vector-table-scan-source.js.map +1 -0
  44. package/package.json +66 -0
  45. package/src/delta.ts +18 -0
  46. package/src/federated-table-scan-source.ts +991 -0
  47. package/src/hudi.ts +235 -0
  48. package/src/iceberg.ts +36 -0
  49. package/src/index.ts +97 -0
  50. package/src/scan-engine.ts +100 -0
  51. package/src/scan-query.ts +27 -0
  52. 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.