-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
73 lines (61 loc) · 2.39 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*!
* Bookshelf-PostGIS
*
* Copyright 2017-2018 Josh Swan and contributors
* Released under the MIT license
* https://github.com/joshswan/bookshelf-postgis/blob/master/LICENSE
*/
const get = require('lodash/get');
const omit = require('lodash/omit');
const set = require('lodash/set');
const wkx = require('wkx');
module.exports = (bookshelf) => {
const proto = bookshelf.Model.prototype;
bookshelf.Model = bookshelf.Model.extend({
geography: null,
geometry: null,
format(attributes) {
// Convert geography attributes to raw ST_MakePoint calls with [lon, lat] as bindings
if (this.geography) {
Object.keys(this.geography).forEach((key) => {
const fields = Array.isArray(this.geography[key]) ? this.geography[key] : ['lon', 'lat'];
const values = fields.map(field => get(attributes, field)).filter(value => typeof value === 'number');
attributes = omit(attributes, fields);
if (values.length === 2) {
attributes[key] = bookshelf.knex.raw('ST_SetSRID(ST_MakePoint(?, ?), 4326)::geography', values);
}
});
}
// Convert geometry attributes to raw ST_GeomFromGeoJSON and stringify GeoJSON attributes
if (this.geometry) {
this.geometry.forEach((attr) => {
if (attributes[attr]) attributes[attr] = bookshelf.knex.raw('ST_GeomFromGeoJSON(?)', [JSON.stringify(attributes[attr])]);
});
}
// Call parent format method
return proto.format.call(this, attributes);
},
parse(attributes) {
if (this.geography) {
Object.keys(this.geography).forEach((key) => {
if (attributes[key]) {
const valInHex = attributes[key];
const fields = Array.isArray(this.geography[key]) ? this.geography[key] : ['lon', 'lat'];
delete attributes.key;
wkx.Geometry.parse(Buffer.from(valInHex, 'hex')).toGeoJSON().coordinates.forEach((coordinate, index) => {
set(attributes, fields[index], coordinate);
});
}
});
}
// Parse geometry columns to GeoJSON
if (this.geometry) {
this.geometry.forEach((attr) => {
if (attributes[attr]) attributes[attr] = wkx.Geometry.parse(Buffer.from(attributes[attr], 'hex')).toGeoJSON();
});
}
// Call parent parse method
return proto.parse.call(this, attributes);
},
});
};