diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-04-02 18:55:15 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-04-02 19:06:17 +0200 |
| commit | 267407c69d1c2ce9d32a61622976c28212aa608d (patch) | |
| tree | fa69e81a2ff1978a7bb0abc3306fe83416fcac79 | |
| parent | 3083282da986f3772b58b83a964544b299bfca83 (diff) | |
| download | mullvadvpn-267407c69d1c2ce9d32a61622976c28212aa608d.tar.xz mullvadvpn-267407c69d1c2ce9d32a61622976c28212aa608d.zip | |
Convert and fix prepare-tree.js to TypeScript since we don't have babel-node under the hood anymore
| -rw-r--r-- | gui/geo-data/README.md | 2 | ||||
| -rw-r--r-- | gui/geo-data/prepare-rtree.js | 60 | ||||
| -rw-r--r-- | gui/geo-data/prepare-rtree.ts | 104 | ||||
| -rw-r--r-- | gui/package-lock.json | 9 | ||||
| -rw-r--r-- | gui/package.json | 2 |
5 files changed, 116 insertions, 61 deletions
diff --git a/gui/geo-data/README.md b/gui/geo-data/README.md index 121ac5cdc8..901439fb29 100644 --- a/gui/geo-data/README.md +++ b/gui/geo-data/README.md @@ -58,7 +58,7 @@ python extract-geo-data.py and finally generate the R-Tree cache: ``` -npx babel-node prepare-rtree.js +npx ts-node prepare-rtree.ts ``` At this point all of the data should be saved in `gui/geo-data/out` folder. diff --git a/gui/geo-data/prepare-rtree.js b/gui/geo-data/prepare-rtree.js deleted file mode 100644 index 83b01f10cd..0000000000 --- a/gui/geo-data/prepare-rtree.js +++ /dev/null @@ -1,60 +0,0 @@ -// -// Script that generates r-trees for geo data. -// run with `npx babel-node geo-data/prepare-rtree.js` -// - -import fs from 'fs'; -import path from 'path'; -import rbush from 'rbush'; - -const geometryData = ['geometry', 'states-provinces-lines']; -const pointData = ['countries', 'cities']; - -const output_dir = path.join(__dirname, 'out'); - -for (const name of geometryData) { - const source = path.join(output_dir, `${name}.json`); - const destination = path.join(output_dir, `${name}.rbush.json`); - const collection = JSON.parse(fs.readFileSync(source)); - - const { geometry } = collection.objects; - const treeData = geometry.geometries.map((object) => { - const [minX, minY, maxX, maxY] = object.bbox; - return { - ...object, - minX, - minY, - maxX, - maxY, - }; - }); - - const tree = rbush(); - tree.load(treeData); - fs.writeFileSync(destination, JSON.stringify(tree.toJSON())); - - console.log(`Saved a rbush to ${destination}`); -} - -for (const name of pointData) { - const source = path.join(output_dir, `${name}.json`); - const destination = path.join(output_dir, `${name}.rbush.json`); - const collection = JSON.parse(fs.readFileSync(source)); - - const treeData = collection.features.map((feat) => { - const { coordinates } = feat.geometry; - return { - ...feat, - minX: coordinates[0], - minY: coordinates[1], - maxX: coordinates[0], - maxY: coordinates[1], - }; - }); - - const tree = rbush(); - tree.load(treeData); - fs.writeFileSync(destination, JSON.stringify(tree.toJSON())); - - console.log(`Saved a rbush to ${destination}`); -} diff --git a/gui/geo-data/prepare-rtree.ts b/gui/geo-data/prepare-rtree.ts new file mode 100644 index 0000000000..3f2519d0c0 --- /dev/null +++ b/gui/geo-data/prepare-rtree.ts @@ -0,0 +1,104 @@ +// +// Script that generates r-trees for geo data. +// run with `npx babel-node geo-data/prepare-rtree.js` +// + +import * as fs from 'fs'; +import * as path from 'path'; +import { Topology, GeometryCollection } from 'topojson-specification'; +import { GeoJSON } from 'geojson'; +import rbush from 'rbush'; + +interface GeometryTopologyObjects { + [key: string]: any; + geometry: GeometryCollection; +} + +function main() { + const GEOMETRY_DATA_FILES = ['geometry', 'states-provinces-lines']; + const POINT_DATA_FILES = ['countries', 'cities']; + const OUTPUT_DIR = path.join(__dirname, 'out'); + + for (const name of GEOMETRY_DATA_FILES) { + const source = path.join(OUTPUT_DIR, `${name}.json`); + const destination = path.join(OUTPUT_DIR, `${name}.rbush.json`); + + try { + processGeometry(source, destination); + } catch (error) { + console.error(`Failed to process ${name}: ${error.message}`); + } + } + + for (const name of POINT_DATA_FILES) { + const source = path.join(OUTPUT_DIR, `${name}.json`); + const destination = path.join(OUTPUT_DIR, `${name}.rbush.json`); + + try { + processPoints(source, destination); + } catch (error) { + console.error(`Failed to process ${name}: ${error.message}`); + } + } +} + +function processGeometry(source: string, destination: string) { + const collection = JSON.parse(fs.readFileSync(source, { encoding: 'utf8' })) as Topology< + GeometryTopologyObjects + >; + + const { geometry } = collection.objects; + const treeData = geometry.geometries.map((object, i) => { + if (!object.bbox) { + throw new Error(`Expected a geometry at index ${i} to have a bbox property.`); + } + + const [minX, minY, maxX, maxY] = object.bbox; + return { + ...object, + minX, + minY, + maxX, + maxY, + }; + }); + + const tree = rbush(); + tree.load(treeData); + fs.writeFileSync(destination, JSON.stringify(tree.toJSON())); + + console.log(`Saved a rbush to ${destination}`); +} + +function processPoints(source: string, destination: string) { + const collection = JSON.parse(fs.readFileSync(source, { encoding: 'utf8' })) as GeoJSON; + + if (collection.type !== 'FeatureCollection') { + throw new Error( + `Invalid collection type ${collection.type} in ${source}. Expected FeatureCollection`, + ); + } + + const treeData = collection.features.map((feat) => { + if (feat.geometry.type !== 'Point') { + throw new Error(`Invalid geometry in ${source}. Expected "Point", got ${feat.geometry.type}`); + } + + const { coordinates } = feat.geometry; + return { + ...feat, + minX: coordinates[0], + minY: coordinates[1], + maxX: coordinates[0], + maxY: coordinates[1], + }; + }); + + const tree = rbush(); + tree.load(treeData); + fs.writeFileSync(destination, JSON.stringify(tree.toJSON())); + + console.log(`Saved a rbush to ${destination}`); +} + +main(); diff --git a/gui/package-lock.json b/gui/package-lock.json index 795f48d8bd..1f80b0fe72 100644 --- a/gui/package-lock.json +++ b/gui/package-lock.json @@ -273,6 +273,15 @@ "integrity": "sha512-hkgzYF+qnIl8uTO8rmUSVSfQ8BIfMXC4yJAF4n8BE758YsKBZvFC4NumnAegj7KmylP0liEZNpb9RRGFMbFejA==", "dev": true }, + "@types/topojson-specification": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/topojson-specification/-/topojson-specification-1.0.1.tgz", + "integrity": "sha512-ZZYZUgkmUls9Uhxx2WZNt9f/h2+H3abUUjOVmq+AaaDFckC5oAwd+MDp95kBirk+XCXrYj0hfpI6DSUiJMrpYQ==", + "dev": true, + "requires": { + "@types/geojson": "*" + } + }, "@types/uuid": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", diff --git a/gui/package.json b/gui/package.json index 9fa8203ceb..b42158c123 100644 --- a/gui/package.json +++ b/gui/package.json @@ -44,6 +44,7 @@ "@types/d3-geo": "^1.11.0", "@types/enzyme": "^3.1.15", "@types/enzyme-adapter-react-16": "^1.0.3", + "@types/geojson": "^7946.0.7", "@types/mkdirp": "^0.5.2", "@types/mocha": "^5.2.6", "@types/node": "^10.12.3", @@ -55,6 +56,7 @@ "@types/react-router": "^4.4.3", "@types/sinon": "^7.0.5", "@types/sprintf-js": "^1.1.2", + "@types/topojson-specification": "^1.0.1", "@types/uuid": "^3.4.4", "browser-sync": "^2.26.3", "chai": "^4.2.0", |
