Skip to content

Commit 3207b5d

Browse files
committed
feat: Implement WKT validation in data-type.ts (keplergl#3298)
Signed-off-by: bdjulbic <bdjulbic@foursquare.com>
1 parent e705fc8 commit 3207b5d

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

src/common-utils/src/data-type.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ import {h3IsValid} from './h3-utils';
1111

1212
const H3_ANALYZER_TYPE = 'H3';
1313

14+
// Returns true if the value is likely a WKT geometry string (heuristic check).
15+
const WKT_PREFIX_RE =
16+
/^(?:SRID=\d+\s*;\s*)?(?:POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)(?:\s+(?:Z|M|ZM))?\s*\(/i;
17+
18+
export function isWkt(value: unknown): boolean {
19+
if (typeof value !== 'string') {
20+
return false;
21+
}
22+
23+
const s = value.trim();
24+
if (s.length < 10) {
25+
return false;
26+
}
27+
28+
if (!s.includes('(') || !s.includes(')')) {
29+
return false;
30+
}
31+
32+
return WKT_PREFIX_RE.test(s);
33+
}
34+
1435
export const ACCEPTED_ANALYZER_TYPES = [
1536
AnalyzerDATA_TYPES.DATE,
1637
AnalyzerDATA_TYPES.TIME,
@@ -267,6 +288,11 @@ export function getFieldsFromData(data: RowData, fieldOrder: string[]): Field[]
267288
type = data.some(d => isHexWkb(d[name])) ? AnalyzerDATA_TYPES.GEOMETRY : type;
268289
}
269290

291+
// quick check if string is wkt
292+
if (type === AnalyzerDATA_TYPES.STRING) {
293+
type = data.some(d => isWkt(d[name])) ? AnalyzerDATA_TYPES.GEOMETRY_FROM_STRING : type;
294+
}
295+
270296
return {
271297
name,
272298
id: name,

test/node/utils/dataset-utils-test.js

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

44
import test from 'tape';
55
import {findDefaultColorField, createNewDataEntry} from '@kepler.gl/utils';
6+
import {isHexWkb, isWkt} from '@kepler.gl/common-utils';
67

78
import {processCsvData} from '@kepler.gl/processors';
89

@@ -88,4 +89,42 @@ test('datasetUtils.isHexWkb', t => {
8889

8990
const validEWktNDR = '0020000001000013ff0000000000400000000000000040';
9091
t.ok(isHexWkb(validEWktNDR), 'A valid hex ewkb in NDR should be valid');
92+
t.end();
93+
});
94+
95+
test('datasetUtils.isWkt', t => {
96+
// non-strings
97+
t.notOk(isWkt(null), 'null is not a valid WKT');
98+
t.notOk(isWkt(undefined), 'undefined is not a valid WKT');
99+
t.notOk(isWkt(123), 'number is not a valid WKT');
100+
t.notOk(isWkt({}), 'object is not a valid WKT');
101+
102+
// regular strings / known non-WKT identifiers
103+
t.notOk(isWkt(''), 'empty string is not a valid WKT');
104+
t.notOk(isWkt('hello world'), 'regular string is not a valid WKT');
105+
t.notOk(isWkt('06075'), 'FIPS code should not be a valid WKT');
106+
t.notOk(isWkt('8a2a1072b59ffff'), 'H3 code should not be a valid WKT');
107+
108+
// edge cases (missing coordinates / parentheses)
109+
t.notOk(isWkt('POINT'), 'POINT without coordinates should not be a valid WKT');
110+
t.notOk(isWkt('POINT 1 2'), 'POINT without parentheses should not be a valid WKT');
111+
t.notOk(isWkt('SRID=4326;POINT'), 'SRID prefix without geometry should not be a valid WKT');
112+
t.notOk(isWkt('POINT (1 2'), 'missing closing parenthesis should not be a valid WKT');
113+
t.notOk(isWkt('POINT ( )'), 'empty coordinates should not be a valid WKT');
114+
115+
// valid WKT examples (heuristic)
116+
t.ok(isWkt('POINT (1 2)'), 'POINT should be recognized as WKT');
117+
t.ok(isWkt('POINT(1 2)'), 'POINT without space before parentheses should be recognized as WKT');
118+
t.ok(isWkt('LINESTRING (0 0, 1 1)'), 'LINESTRING should be recognized as WKT');
119+
t.ok(isWkt('POLYGON ((0 0, 1 0, 1 1, 0 0))'), 'POLYGON should be recognized as WKT');
120+
t.ok(
121+
isWkt('SRID=4326;POINT(1 2)'),
122+
'WKT with SRID prefix should be recognized as WKT'
123+
);
124+
t.ok(isWkt('POINT Z (1 2 3)'), 'WKT with Z dimension should be recognized as WKT');
125+
126+
// not WKT but contains parentheses
127+
t.notOk(isWkt('HELLO (1 2)'), 'non-WKT string with parentheses should not be valid WKT');
128+
129+
t.end();
91130
});

0 commit comments

Comments
 (0)