Skip to content

Commit ad280f6

Browse files
committed
fix: request query parameter handling
Request parameters are of the type ParsedQs (see @types/qs). Here's the type definition: interface ParsedQs { [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[] } Note that the params aren't converted to JS types by default. Currently, these query params are casted to an interface with boolean values, but TypeScript doesn't convert these string params at runtime (rather, TypeScript is only useful on compile time), so a `string` is used where a `boolean` is expected. To reproduce the error, uncomment the test labelled with FIXME.
1 parent 1f71af3 commit ad280f6

File tree

7 files changed

+70
-77
lines changed

7 files changed

+70
-77
lines changed

src/api/columns.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@ import sql = require('../lib/sql')
55
import { DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants'
66
import { Tables } from '../lib/interfaces'
77

8+
/**
9+
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
10+
*/
11+
interface QueryParams {
12+
includeSystemSchemas?: string
13+
}
14+
815
const router = Router()
916
const { columns, tables } = sql
1017

1118
router.get('/', async (req, res) => {
1219
try {
1320
const { data } = await RunQuery(req.headers.pg, columns)
14-
const query: Fetch.QueryParams = req.query
21+
const query: QueryParams = req.query
22+
const includeSystemSchemas = query?.includeSystemSchemas === 'true'
1523
let payload: Tables.Column[] = data
16-
if (!query?.includeSystemSchemas) payload = removeSystemSchemas(data)
24+
if (!includeSystemSchemas) payload = removeSystemSchemas(data)
1725
return res.status(200).json(payload)
1826
} catch (error) {
1927
console.log('throwing error')
@@ -104,8 +112,6 @@ router.delete('/:id', async (req, res) => {
104112
}
105113
})
106114

107-
export = router
108-
109115
const removeSystemSchemas = (data: Tables.Column[]) => {
110116
return data.filter((x) => !DEFAULT_SYSTEM_SCHEMAS.includes(x.schema))
111117
}
@@ -132,14 +138,4 @@ ${is_nullable ? '' : 'NOT NULL'}
132138
${is_primary_key ? 'PRIMARY KEY' : ''}`
133139
}
134140

135-
/**
136-
* Types
137-
*/
138-
namespace Fetch {
139-
/**
140-
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
141-
*/
142-
export interface QueryParams {
143-
includeSystemSchemas?: boolean
144-
}
145-
}
141+
export = router

src/api/functions.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@ import { RunQuery } from '../lib/connectionPool'
66
import { DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants'
77
import { Functions } from '../lib/interfaces'
88

9+
/**
10+
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
11+
*/
12+
interface QueryParams {
13+
includeSystemSchemas?: string
14+
}
15+
916
const router = Router()
1017
router.get('/', async (req, res) => {
1118
try {
1219
const { data } = await RunQuery(req.headers.pg, functions)
13-
const query: Fetch.QueryParams = req.query
20+
const query: QueryParams = req.query
21+
const includeSystemSchemas = query?.includeSystemSchemas === 'true'
1422
let payload: Functions.Function[] = data
15-
if (!query?.includeSystemSchemas) payload = removeSystemSchemas(data)
23+
if (!includeSystemSchemas) payload = removeSystemSchemas(data)
1624
return res.status(200).json(payload)
1725
} catch (error) {
1826
console.log('throwing error')
@@ -25,16 +33,3 @@ const removeSystemSchemas = (data: Functions.Function[]) => {
2533
}
2634

2735
export = router
28-
29-
/**
30-
* Types
31-
*/
32-
33-
namespace Fetch {
34-
/**
35-
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
36-
*/
37-
export interface QueryParams {
38-
includeSystemSchemas?: boolean
39-
}
40-
}

src/api/roles.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import { Roles } from '../lib/interfaces'
1010
/**
1111
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
1212
*/
13-
interface GetRolesQueryParams {
14-
includeDefaultRoles?: boolean
15-
includeSystemSchemas?: boolean
13+
interface QueryParams {
14+
includeDefaultRoles?: string
15+
includeSystemSchemas?: string
1616
}
1717

1818
const router = Router()
19+
1920
router.get('/', async (req, res) => {
2021
try {
2122
const sql = `
@@ -27,17 +28,20 @@ SELECT
2728
FROM
2829
roles`
2930
const { data } = await RunQuery(req.headers.pg, sql)
30-
const query: GetRolesQueryParams = req.query
31+
const query: QueryParams = req.query
32+
const includeSystemSchemas = query?.includeSystemSchemas === 'true'
33+
const includeDefaultRoles = query?.includeDefaultRoles === 'true'
3134
let payload: Roles.Role[] = data
32-
if (!query?.includeSystemSchemas) payload = removeSystemSchemas(data)
33-
if (!query?.includeDefaultRoles) payload = removeDefaultRoles(payload)
35+
if (!includeSystemSchemas) payload = removeSystemSchemas(data)
36+
if (!includeDefaultRoles) payload = removeDefaultRoles(payload)
3437

3538
return res.status(200).json(payload)
3639
} catch (error) {
3740
console.log('throwing error')
3841
res.status(500).json({ error: 'Database error', status: 500 })
3942
}
4043
})
44+
4145
router.post('/', async (req, res) => {
4246
try {
4347
const {

src/api/schemas.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,19 @@ const { schemas } = sqlTemplates
1010
/**
1111
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
1212
*/
13-
interface GetSchemasQueryParams {
14-
includeSystemSchemas?: boolean
13+
interface QueryParams {
14+
includeSystemSchemas?: string
1515
}
1616

1717
const router = Router()
1818

1919
router.get('/', async (req, res) => {
2020
try {
2121
const { data } = await RunQuery(req.headers.pg, schemas)
22-
const query: GetSchemasQueryParams = req.query
22+
const query: QueryParams = req.query
23+
const includeSystemSchemas = query?.includeSystemSchemas === 'true'
2324
let payload: Schemas.Schema[] = data
24-
if (!query?.includeSystemSchemas) payload = removeSystemSchemas(data)
25+
if (!includeSystemSchemas) payload = removeSystemSchemas(data)
2526

2627
return res.status(200).json(payload)
2728
} catch (error) {

src/api/tables.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ import { RunQuery } from '../lib/connectionPool'
77
import { DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants'
88
import { Tables } from '../lib/interfaces'
99

10+
/**
11+
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
12+
*/
13+
interface QueryParams {
14+
includeSystemSchemas?: string
15+
}
16+
1017
const router = Router()
1118

1219
router.get('/', async (req, res) => {
@@ -40,9 +47,10 @@ SELECT
4047
FROM
4148
tables`
4249
const { data } = await RunQuery(req.headers.pg, sql)
43-
const query: Fetch.QueryParams = req.query
50+
const query: QueryParams = req.query
51+
const includeSystemSchemas = query?.includeSystemSchemas === 'true'
4452
let payload: Tables.Table[] = data
45-
if (!query?.includeSystemSchemas) payload = removeSystemSchemas(data)
53+
if (!includeSystemSchemas) payload = removeSystemSchemas(data)
4654
return res.status(200).json(payload)
4755
} catch (error) {
4856
console.log('throwing error', error)
@@ -119,8 +127,6 @@ router.delete('/:id', async (req, res) => {
119127
}
120128
})
121129

122-
export = router
123-
124130
const selectSingleSql = (id: number) => {
125131
return SQL``.append(tables).append(SQL` and c.oid = ${id}`)
126132
}
@@ -139,14 +145,4 @@ const removeSystemSchemas = (data: Tables.Table[]) => {
139145
return data.filter((x) => !DEFAULT_SYSTEM_SCHEMAS.includes(x.schema))
140146
}
141147

142-
/**
143-
* Types
144-
*/
145-
namespace Fetch {
146-
/**
147-
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
148-
*/
149-
export interface QueryParams {
150-
includeSystemSchemas?: boolean
151-
}
152-
}
148+
export = router

src/api/types.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@ import { RunQuery } from '../lib/connectionPool'
66
import { DEFAULT_SYSTEM_SCHEMAS } from '../lib/constants'
77
import { Types } from '../lib/interfaces'
88

9+
/**
10+
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
11+
*/
12+
interface QueryParams {
13+
includeSystemSchemas?: string
14+
}
15+
916
const router = Router()
17+
1018
router.get('/', async (req, res) => {
1119
try {
1220
const { data } = await RunQuery(req.headers.pg, types)
13-
const query: Fetch.QueryParams = req.query
21+
const query: QueryParams = req.query
22+
const includeSystemSchemas = query?.includeSystemSchemas === 'true'
1423
let payload: Types.Type[] = data
15-
if (!query?.includeSystemSchemas) payload = removeSystemSchemas(data)
24+
if (!includeSystemSchemas) payload = removeSystemSchemas(data)
1625
return res.status(200).json(payload)
1726
} catch (error) {
1827
console.log('throwing error')
@@ -25,16 +34,3 @@ const removeSystemSchemas = (data: Types.Type[]) => {
2534
}
2635

2736
export = router
28-
29-
/**
30-
* Types
31-
*/
32-
33-
namespace Fetch {
34-
/**
35-
* @param {boolean} [includeSystemSchemas=false] - Return system schemas as well as user schemas
36-
*/
37-
export interface QueryParams {
38-
includeSystemSchemas?: boolean
39-
}
40-
}

test/integration/index.spec.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ describe('/schemas', () => {
9999
assert.equal(true, !!datum)
100100
assert.equal(true, !!included)
101101
})
102+
it('GET without system schemas (explicit)', async () => {
103+
const res = await axios.get(`${URL}/schemas?includeSystemSchemas=false`)
104+
const isIncluded = res.data.some((x) => x.name === 'pg_catalog')
105+
assert.equal(res.status, STATUS.SUCCESS)
106+
assert.equal(isIncluded, false)
107+
})
102108
it('POST & PATCH & DELETE', async () => {
103109
const res = await axios.post(`${URL}/schemas`, { name: 'api' })
104110
assert.equal('api', res.data.name)
@@ -201,13 +207,12 @@ describe('/tables', async () => {
201207
assert.equal(res.status, STATUS.SUCCESS)
202208
assert.equal(true, !!included)
203209
})
204-
// FIXME: Bad handling of query param in /tables & /columns & /schemas & /types
205-
// it('GET /tables without system tables (explicit)', async () => {
206-
// const res = await axios.get(`${URL}/tables?includeSystemSchemas=false`)
207-
// const isIncluded = res.data.some((x) => `${x.schema}.${x.name}` === 'pg_catalog.pg_type')
208-
// assert.equal(res.status, STATUS.SUCCESS)
209-
// assert.equal(isIncluded, false)
210-
// })
210+
it('GET /tables without system tables (explicit)', async () => {
211+
const res = await axios.get(`${URL}/tables?includeSystemSchemas=false`)
212+
const isIncluded = res.data.some((x) => `${x.schema}.${x.name}` === 'pg_catalog.pg_type')
213+
assert.equal(res.status, STATUS.SUCCESS)
214+
assert.equal(isIncluded, false)
215+
})
211216
it('GET /columns', async () => {
212217
const res = await axios.get(`${URL}/columns`)
213218
// console.log('res.data', res.data)

0 commit comments

Comments
 (0)