-
Notifications
You must be signed in to change notification settings - Fork 1
/
geojson.js
121 lines (111 loc) · 3.47 KB
/
geojson.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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// based on https://raw.githubusercontent.com/tobinbradley/dirt-simple-postgis-http-api/master/routes/geojson.js
const sqlTableName = require('./utils/sqltablename.js');
const sql = (params, query) => {
let bounds = query.bounds ? query.bounds.split(',').map(Number) : null;
bounds && bounds.length === 3 ? bounds = merc.bbox(bounds[1], bounds[2], bounds[0]) : null;
return `
SELECT
Row_to_json(fc) as geojson
FROM (
SELECT
'FeatureCollection' AS type,
COALESCE(Array_to_json(Array_agg(f)), '[]'::json) AS features
FROM (
SELECT
'Feature' AS type,
St_asgeojson(ST_Transform(lg.${query.geom_column}, 4326))::json AS geometry,
${query.columns ? `
Row_to_json(
(
SELECT
l
FROM
(SELECT ${query.columns}) AS l
)
) AS properties
` : `'{}'::json AS properties`}
FROM
${sqlTableName(params.table)} AS lg
${bounds ? `, (SELECT ST_SRID(${query.geom_column}) as srid FROM ${sqlTableName(params.table)} LIMIT 1) sq` : ''}
-- Optional Filter
${query.filter || bounds ? 'WHERE' : ''}
${query.filter ? `${query.filter}` : '' }
${query.filter && bounds ? 'AND' : ''}
${bounds ? `
${query.geom_column} &&
ST_Transform(
ST_MakeEnvelope(${bounds.join()}, 4326),
srid
)
` : ''}
) AS f
) AS fc;
`
}
module.exports = function(app, pool) {
/**
* @swagger
*
* /data/geojson/{table}:
* get:
* description: return table as geojson
* tags: ['geodata']
* produces:
* - application/json
* parameters:
* - name: table
* description: name of table or view
* in: path
* required: true
* type: string
* - name: geom_column
* description: name of geometry column (default 'geom')
* in: query
* required: false
* - name: columns
* description: optional comma seperated list of attribute columns to be added to the mvt geometries
* in: query
* required: false
* type: string
* - name: filter
* description: 'Optional filter parameters for a SQL WHERE statement.'
* in: query
* type: string
* required: false
* - name: bounds
* description: 'Optionally limit output to features that intersect bounding box. Can be expressed as a bounding box (sw.lng, sw.lat, ne.lng, ne.lat) or a Z/X/Y tile (0,0,0).'
* in: query
* type: string
* pattern: '^-?[0-9]{0,20}.?[0-9]{1,20}?(,-?[0-9]{0,20}.?[0-9]{1,20}?){2,3}$'
* responses:
* 200:
* description: geojson
* 422:
* description: invalid datasource or columnname
*/
app.get('/data/geojson/:table', async (req, res) => {
if (!req.query.geom_column) {
req.query.geom_column = 'geom';
}
const sqlString = sql(req.params, req.query);
try {
const result = await pool.one(sqlString);
res.json(result.geojson)
} catch(err) {
console.log(err);
let status = 500;
switch (err.code) {
case '42P01':
// table does not exist
status = 422;
break;
case '42703':
// column does not exist
status = 422;
break;
default:
}
res.status(status).json({error:err.message})
}
})
}