Skip to content

Commit

Permalink
fix: added more support for nested routes
Browse files Browse the repository at this point in the history
  • Loading branch information
Megapixel99 committed Nov 3, 2023
1 parent 95285c4 commit ee85eed
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 3 deletions.
28 changes: 25 additions & 3 deletions lib/generate-doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function iterateStack (path, routeLayer, layer, cb) {
if (layer.name === 'router') {
layer.handle.stack.forEach(l => {
path = path || ''
iterateStack(path + split(layer.regexp).join('/'), layer, l, cb)
iterateStack(path + split(layer.regexp, layer.keys).join('/'), layer, l, cb)
})
}
if (!layer.route) {
Expand All @@ -82,8 +82,30 @@ function iterateStack (path, routeLayer, layer, cb) {
layer.route.stack.forEach((l) => iterateStack(path + layer.route.path, layer, l, cb))
}

function processComplexMatch (thing, keys) {
let match = thing.toString()
let i = 0

// This replaces the regex used by Express to match dynamic parameters
// (i.e. /:id, /:name, etc...) with the name(s) of those parameter(s)
// no-useless-escape is disabled since we need three backslashes
while (match.includes('(?:([^\\\/]+?))')) { // eslint-disable-line no-useless-escape
match = match.replace('(?:([^\\\/]+?))', `{${keys[i].name}}`) // eslint-disable-line no-useless-escape
i += 1
}

match
.replace('\\/?', '')
.replace('(?=\\/|$)', '$')
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\/]|[^.*+?^${}()|[\]\\/])*)\$\//)

// The second replace, removes the regex used at the start of the string and
// the regex used to match the query parameters
return cleanUpRegex(match).replace(/\\(.)/g, '$1').replace(/\/\^|\/\?(.*)/g, '').split('/')
}

// https://github.com/expressjs/express/issues/3308#issuecomment-300957572
function split (thing) {
function split (thing, keys) {
if (typeof thing === 'string') {
return thing.split('/')
} else if (thing.fast_slash) {
Expand All @@ -96,6 +118,6 @@ function split (thing) {
.match(/^\/\^((?:\\[.*+?^${}()|[\]\\/]|[^.*+?^${}()|[\]\\/])*)\$\//)
return match
? match[1].replace(/\\(.)/g, '$1').split('/')
: '<complex:' + thing.toString() + '>'
: processComplexMatch(thing, keys)
}
}
37 changes: 37 additions & 0 deletions test/_moreRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const router = require('express').Router({ mergeParams: true })
const openapi = require('..')

const oapi = openapi()
router.use(oapi)

router.get(
'/',
oapi.validPath({
summary: 'Get a user.',
parameters: [
{
in: 'path',
imageId: 'id',
schema: {
type: 'integer'
}
}
],
responses: {
200: {
content: {
'application/json': {
schema: {
type: 'string'
}
}
}
}
}
}),
async (req, res) => {
res.send('done')
}
)

module.exports = router
17 changes: 17 additions & 0 deletions test/_routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const supertest = require('supertest')
const express = require('express')
const SwaggerParser = require('swagger-parser')
const openapi = require('..')
const _moreRoutes = require('./_moreRoutes')

module.exports = function () {
suite('routes', function () {
Expand Down Expand Up @@ -77,5 +78,21 @@ module.exports = function () {
done()
})
})

test('serve routes in a different file', function (done) {
const app = express()

const oapi = openapi()
app.use(oapi)
app.use('/:id', _moreRoutes)

supertest(app)
.get(`${openapi.defaultRoutePrefix}.json`)
.expect(200, (err, res) => {
assert(!err, err)
assert.strictEqual(Object.keys((res.body.paths))[0], '/{id}/')
done()
})
})
})
}

0 comments on commit ee85eed

Please sign in to comment.