From 62c8baf3cccb1259789ceeacb5eaf19de6aa5c76 Mon Sep 17 00:00:00 2001 From: Eric Musyoka Date: Fri, 9 Aug 2024 09:59:57 +0300 Subject: [PATCH 1/4] Add endpoint to get map bounds and handle filters and errors --- routes/bounds.js | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 routes/bounds.js diff --git a/routes/bounds.js b/routes/bounds.js new file mode 100644 index 0000000..d6b33cc --- /dev/null +++ b/routes/bounds.js @@ -0,0 +1,71 @@ +// route query +require("dotenv").config() + +const sql = (params, query) => { + return ` + SELECT + ST_XMin(bbox) AS xMin, + ST_YMin(bbox) AS yMin, + ST_XMax(bbox) AS xMax, + ST_YMax(bbox) AS yMax + FROM ( + SELECT ST_Extent(${process.env.TABLE_COLUMN}) AS bbox + FROM ${process.env.TABLE_NAME} + WHERE ${`xform_id=${query.form_id} AND geom is not null AND deleted_at is null`} + ) AS subquery; + ` + } + + + // route schema +const schema = { + description: + 'Returns forms map bounds', + tags: ['feature'], + summary: 'Return bounds', + querystring: { + form_id: { + type: 'string | number', + description: 'Form is', + } + } +} + +// create route +module.exports = function (fastify, opts, next) { + fastify.route({ + method: 'GET', + url: '/bounds', + schema: schema, + handler: function (request, reply) { + fastify.pg.connect(onConnect) + + function onConnect(err, client, release) { + if (err) { + request.log.error(err) + return reply.code(500).send({ error: "Database connection error." }) + } + + client.query( + sql(request.params, request.query), + function onResult(err, result) { + release() + if (err) { + reply.code(400).send(err) + } else { + if(result.rows > 0) { + reply.send(result.rows[0]) + } else { + reply.code(404).send({error: 'No data found' }); + } + } + } + ) + } + } + }) + next() +} + + module.exports.autoPrefix = '/v1' + \ No newline at end of file From ecd9ef9abada32c01f5a3cb0b8fad311a68681d8 Mon Sep 17 00:00:00 2001 From: Eric Musyoka Date: Mon, 19 Aug 2024 13:06:42 +0300 Subject: [PATCH 2/4] Add limit subquery --- routes/bounds.js | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/routes/bounds.js b/routes/bounds.js index d6b33cc..0436cf0 100644 --- a/routes/bounds.js +++ b/routes/bounds.js @@ -2,21 +2,26 @@ require("dotenv").config() const sql = (params, query) => { - return ` - SELECT - ST_XMin(bbox) AS xMin, - ST_YMin(bbox) AS yMin, - ST_XMax(bbox) AS xMax, - ST_YMax(bbox) AS yMax + return ` + SELECT + ST_XMin(bbox) AS xMin, + ST_YMin(bbox) AS yMin, + ST_XMax(bbox) AS xMax, + ST_YMax(bbox) AS yMax + FROM ( + SELECT ST_Extent(${process.env.TABLE_COLUMN}) AS bbox FROM ( - SELECT ST_Extent(${process.env.TABLE_COLUMN}) AS bbox - FROM ${process.env.TABLE_NAME} - WHERE ${`xform_id=${query.form_id} AND geom is not null AND deleted_at is null`} - ) AS subquery; - ` - } + SELECT ${process.env.TABLE_COLUMN} + FROM ${process.env.TABLE_NAME} + WHERE ${`xform_id=${query.form_id} AND geom is not null AND deleted_at is null`} + + -- Optional row LIMIT + ${query.limit ? `LIMIT ${query.limit}` : '' } + ) As limited_rows + ) AS subquery; + ` +} - // route schema const schema = { description: @@ -27,6 +32,10 @@ const schema = { form_id: { type: 'string | number', description: 'Form is', + }, + limit: { + type: 'string', + description: 'Optional rows limit count.' } } } From 9ddcea8e709778b7150698182c417369bfd2f3e7 Mon Sep 17 00:00:00 2001 From: Eric Musyoka Date: Mon, 19 Aug 2024 13:45:59 +0300 Subject: [PATCH 3/4] Fix schema type --- routes/bounds.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/bounds.js b/routes/bounds.js index 0436cf0..7b21440 100644 --- a/routes/bounds.js +++ b/routes/bounds.js @@ -30,7 +30,7 @@ const schema = { summary: 'Return bounds', querystring: { form_id: { - type: 'string | number', + type: 'string', description: 'Form is', }, limit: { From 1fe50861457ac7f2c56f9bc72bc85934af713ab5 Mon Sep 17 00:00:00 2001 From: Eric Musyoka Date: Mon, 19 Aug 2024 14:22:46 +0300 Subject: [PATCH 4/4] Fix error when temp token not supplied and escape empty rows --- index.js | 2 +- routes/bounds.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 3bfd9c9..a0f019e 100644 --- a/index.js +++ b/index.js @@ -37,7 +37,7 @@ async function build() { } }) .catch((error) => { - req.log.error(err) + req.log.error(error) done(error.detail); }); } else if ("/health-check" == req.url) { diff --git a/routes/bounds.js b/routes/bounds.js index 7b21440..184d725 100644 --- a/routes/bounds.js +++ b/routes/bounds.js @@ -31,7 +31,7 @@ const schema = { querystring: { form_id: { type: 'string', - description: 'Form is', + description: 'Form id', }, limit: { type: 'string', @@ -62,7 +62,7 @@ module.exports = function (fastify, opts, next) { if (err) { reply.code(400).send(err) } else { - if(result.rows > 0) { + if(result.rows?.length > 0) { reply.send(result.rows[0]) } else { reply.code(404).send({error: 'No data found' });