Skip to content

Commit d83e9d6

Browse files
committed
Replace instanceof arrow.* with isArrow* type guards
Signed-off-by: Ilya Boyandin <ilyabo@gmail.com>
1 parent 06dc43a commit d83e9d6

10 files changed

Lines changed: 89 additions & 17 deletions

File tree

src/deckgl-arrow-layers/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"dependencies": {
3333
"@geoarrow/geoarrow-js": "^0.3.0",
3434
"@kepler.gl/constants": "^3.2.2",
35+
"@kepler.gl/utils": "^3.2.2",
3536
"@math.gl/core": "^4.0.0",
3637
"@math.gl/polygon": "^4.0.0",
3738
"@math.gl/types": "^4.0.0",

src/deckgl-arrow-layers/src/utils/utils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {assert} from '@deck.gl/core/typed';
99
import * as arrow from 'apache-arrow';
1010
import * as ga from '@geoarrow/geoarrow-js';
1111
import {AccessorContext, AccessorFunction, _InternalAccessorContext} from '../types';
12+
import {isArrowFixedSizeList, isArrowStruct, isArrowVector} from '@kepler.gl/utils';
1213

1314
export type TypedArray =
1415
| Uint8Array
@@ -45,14 +46,14 @@ function isDataInterleavedCoords(
4546
data: arrow.Data
4647
): data is arrow.Data<arrow.FixedSizeList<arrow.Float64>> {
4748
// TODO: also check 2 or 3d? Float64?
48-
return data.type instanceof arrow.FixedSizeList;
49+
return isArrowFixedSizeList(data.type);
4950
}
5051

5152
function isDataSeparatedCoords(
5253
data: arrow.Data
5354
): data is arrow.Data<arrow.Struct<{x: arrow.Float64; y: arrow.Float64}>> {
5455
// TODO: also check child names? Float64?
55-
return data.type instanceof arrow.Struct;
56+
return isArrowStruct(data.type);
5657
}
5758

5859
/**
@@ -162,7 +163,7 @@ export function assignAccessor(args: AssignAccessorProps) {
162163
return;
163164
}
164165

165-
if (propInput instanceof arrow.Vector) {
166+
if (isArrowVector(propInput)) {
166167
const columnData = propInput.data[chunkIdx];
167168

168169
if (arrow.DataType.isFixedSizeList(columnData)) {

src/deckgl-arrow-layers/src/utils/validate.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// Copyright (c) vis.gl contributors
77

88
import {assert} from '@deck.gl/core/typed';
9+
import {isArrowVector} from '@kepler.gl/utils';
910
import * as arrow from 'apache-arrow';
1011

1112
export function validateAccessors(props: Record<string, any>, table: arrow.Table): void {
@@ -15,7 +16,7 @@ export function validateAccessors(props: Record<string, any>, table: arrow.Table
1516
// Is it an accessor
1617
if (accessorName.startsWith('get')) {
1718
// Is it a vector accessor
18-
if (accessorValue instanceof arrow.Vector) {
19+
if (isArrowVector(accessorValue)) {
1920
vectorAccessors.push(accessorValue);
2021

2122
// Is it a color vector accessor

src/duckdb/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"@kepler.gl/processors": "3.2.2",
3232
"@kepler.gl/table": "3.2.2",
3333
"@kepler.gl/types": "3.2.2",
34+
"@kepler.gl/utils": "3.2.2",
3435
"@monaco-editor/react": "^4.6.0",
3536
"@radix-ui/react-collapsible": "^1.1.0",
3637
"apache-arrow": ">=15.0.0",

src/duckdb/src/table/duckdb-table.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ import {
1919
} from '@kepler.gl/processors';
2020
import {KeplerTable} from '@kepler.gl/table';
2121
import {Field} from '@kepler.gl/types';
22-
import {getApplicationConfig, DatabaseAdapter, DatabaseConnection} from '@kepler.gl/utils';
22+
import {
23+
getApplicationConfig,
24+
DatabaseAdapter,
25+
DatabaseConnection,
26+
isArrowTable,
27+
isArrowVector
28+
} from '@kepler.gl/utils';
2329

2430
import {
2531
processCsvRowObject,
@@ -161,10 +167,9 @@ export class KeplerGlDuckDbTable extends KeplerTable {
161167
try {
162168
// 1) data.rows contains an arrow table created by Add to Map data from DuckDb query.
163169
// 2) arrow table is in cols & fields when a file is dragged & dropped into Add Data To Map dialog.
164-
const arrowTable =
165-
data.rows instanceof arrow.Table
166-
? data.rows
167-
: restoreArrowTable(data.cols || [], data.fields, data.arrowSchema);
170+
const arrowTable = isArrowTable(data.rows)
171+
? data.rows
172+
: restoreArrowTable(data.cols || [], data.fields, data.arrowSchema);
168173

169174
// remove unsupported extensions from an arrow table that throw exceptions in DuckDB.
170175
adjustedMetadata = removeUnsupportedExtensions(arrowTable);
@@ -215,7 +220,7 @@ export class KeplerGlDuckDbTable extends KeplerTable {
215220
format = DATASET_FORMATS.row;
216221
} else if (data.rows?.type === 'FeatureCollection') {
217222
format = DATASET_FORMATS.geojson;
218-
} else if (data.cols?.[0] instanceof arrow.Vector) {
223+
} else if (isArrowVector(data.cols?.[0])) {
219224
format = DATASET_FORMATS.arrow;
220225
}
221226
}

src/layers/src/base-layer.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ import {
4141
hexToRgb,
4242
isPlainObject,
4343
isDomainStops,
44-
updateColorRangeByMatchingPalette
44+
updateColorRangeByMatchingPalette,
45+
isArrowTable
4546
} from '@kepler.gl/utils';
4647
import {generateHashId, toArray, notNullorUndefined} from '@kepler.gl/common-utils';
4748
import {Datasets, GpuFilter, KeplerTable} from '@kepler.gl/table';
@@ -1585,7 +1586,7 @@ class Layer implements KeplerLayer {
15851586
const {data, mapState} = renderOpts;
15861587
const {textLabel} = this.config;
15871588

1588-
const TextLayerClass = data.data instanceof arrow.Table ? GeoArrowTextLayer : TextLayer;
1589+
const TextLayerClass = isArrowTable(data.data) ? GeoArrowTextLayer : TextLayer;
15891590

15901591
return data.textLabels.reduce((accu, d, i) => {
15911592
if (d.getText) {

src/layers/src/layer-text-label.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import * as arrow from 'apache-arrow';
55
import {getDistanceScales} from 'viewport-mercator-project';
6-
import {DataContainerInterface, ArrowDataContainer} from '@kepler.gl/utils';
6+
import {DataContainerInterface, ArrowDataContainer, isArrowTable} from '@kepler.gl/utils';
77
import {notNullorUndefined} from '@kepler.gl/common-utils';
88
import uniq from 'lodash/uniq';
99

@@ -82,7 +82,7 @@ export const formatTextLabelData = ({
8282
getText = oldLayerData.textLabels[i].getText;
8383
rebuildArrowTextVector = false;
8484
} else {
85-
if (data instanceof arrow.Table) {
85+
if (isArrowTable(data)) {
8686
// we don't filter out arrow tables,
8787
// so we use filteredIndex array instead
8888
const allLabels: string[] = [];
@@ -108,7 +108,7 @@ export const formatTextLabelData = ({
108108
// For now check here for ArrowTable, not ArrowDataContainer.
109109
if (
110110
rebuildArrowTextVector &&
111-
data instanceof arrow.Table &&
111+
isArrowTable(data) &&
112112
dataContainer instanceof ArrowDataContainer
113113
) {
114114
getText = dataContainer.getColumn(tl.field.fieldIdx);

src/utils/src/arrow-data-container.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,64 @@ export function isArrowTable(data: any): data is arrow.Table {
4040
);
4141
}
4242

43+
/**
44+
* Check if data is an ArrowVector object.
45+
* Uses duck-typing instead of `instanceof` to handle DuckDB's bundled Arrow version.
46+
*
47+
* @param data - object to check
48+
* @returns true if data is an ArrowVector object (type guarded)
49+
*/
50+
export function isArrowVector(data: any): data is arrow.Vector {
51+
return (
52+
typeof data === 'object' &&
53+
data !== null &&
54+
'type' in data &&
55+
'length' in data &&
56+
typeof data.length === 'number' &&
57+
'get' in data &&
58+
typeof data.get === 'function' &&
59+
'data' in data &&
60+
Array.isArray(data.data)
61+
);
62+
}
63+
64+
/**
65+
* Check if data is an Arrow FixedSizeList DataType.
66+
* Uses duck-typing instead of `instanceof` to handle DuckDB's bundled Arrow version.
67+
*
68+
* @param data - object to check
69+
* @returns true if data is an Arrow FixedSizeList DataType (type guarded)
70+
*/
71+
export function isArrowFixedSizeList(data: any): data is arrow.FixedSizeList {
72+
return (
73+
typeof data === 'object' &&
74+
data !== null &&
75+
'typeId' in data &&
76+
'listSize' in data &&
77+
typeof data.listSize === 'number' &&
78+
'children' in data &&
79+
Array.isArray(data.children)
80+
);
81+
}
82+
83+
/**
84+
* Check if data is an Arrow Struct DataType.
85+
* Uses duck-typing instead of `instanceof` to handle DuckDB's bundled Arrow version.
86+
*
87+
* @param data - object to check
88+
* @returns true if data is an Arrow Struct DataType (type guarded)
89+
*/
90+
export function isArrowStruct(data: any): data is arrow.Struct {
91+
return (
92+
typeof data === 'object' &&
93+
data !== null &&
94+
'typeId' in data &&
95+
'children' in data &&
96+
Array.isArray(data.children) &&
97+
!('listSize' in data)
98+
);
99+
}
100+
43101
/**
44102
* @param dataContainer
45103
* @param sharedRow

src/utils/src/data-utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {Field, Millisecond, ProtoDatasetField} from '@kepler.gl/types';
2020

2121
import {snapToMarks} from './plot';
2222
import {isPlainObject} from './utils';
23+
import {isArrowVector} from './arrow-data-container';
2324

2425
export type FieldFormatter = (value: any, field?: ProtoDatasetField) => string;
2526

@@ -317,7 +318,7 @@ export const FIELD_DISPLAY_FORMAT: {
317318
? `[${String(d)}]`
318319
: '',
319320
[ALL_FIELD_TYPES.geoarrow]: (data, field) => {
320-
if (data instanceof arrow.Vector) {
321+
if (isArrowVector(data)) {
321322
try {
322323
const encoding = field?.metadata?.get('ARROW:extension:name');
323324
if (encoding) {

src/utils/src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ export {
128128
ArrowDataContainer,
129129
arrowDataTypeToAnalyzerDataType,
130130
arrowDataTypeToFieldType,
131-
isArrowTable
131+
isArrowTable,
132+
isArrowFixedSizeList,
133+
isArrowStruct,
134+
isArrowVector
132135
} from './arrow-data-container';
133136
export type {DataContainerInterface} from './data-container-interface';
134137
export {

0 commit comments

Comments
 (0)