summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2019-04-02 18:55:15 +0200
committerAndrej Mihajlov <and@mullvad.net>2019-04-02 19:06:17 +0200
commit267407c69d1c2ce9d32a61622976c28212aa608d (patch)
treefa69e81a2ff1978a7bb0abc3306fe83416fcac79
parent3083282da986f3772b58b83a964544b299bfca83 (diff)
downloadmullvadvpn-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.md2
-rw-r--r--gui/geo-data/prepare-rtree.js60
-rw-r--r--gui/geo-data/prepare-rtree.ts104
-rw-r--r--gui/package-lock.json9
-rw-r--r--gui/package.json2
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",