From 846b035c4d1f24bf86fc5f96807e5b21673b9a9b Mon Sep 17 00:00:00 2001 From: Seth Wheeler <23089578+Megapixel99@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:26:28 -0500 Subject: [PATCH] feat: Add support for the regex `*` --- lib/generate-doc.js | 9 ++++- test/_routes.js | 98 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/lib/generate-doc.js b/lib/generate-doc.js index 803f132..4d0790e 100644 --- a/lib/generate-doc.js +++ b/lib/generate-doc.js @@ -29,7 +29,11 @@ module.exports = function generateDocument (baseDocument, router, basePath) { if (routeLayer && routeLayer.keys && routeLayer.keys.length) { const keys = {} - const params = routeLayer.keys.map((k) => { + const params = routeLayer.keys.map((k, i) => { + const prev = routeLayer.keys[i - 1] + if (!Number.isNaN(k.name) && prev?.offset + prev?.name?.length - 2 === k.offset) { + return null + } let param if (schema.parameters) { param = schema.parameters.find((p) => p.name === k.name && p.in === 'path') @@ -45,6 +49,7 @@ module.exports = function generateDocument (baseDocument, router, basePath) { schema: k.schema || { type: 'string' } }, param || {}) }) + .filter((e) => e) if (schema.parameters) { schema.parameters.forEach((p) => { @@ -55,7 +60,7 @@ module.exports = function generateDocument (baseDocument, router, basePath) { } operation.parameters = params - path = pathToRegexp.compile(path)(keys, { encode: (value) => value }) + path = pathToRegexp.compile(path.replace(/\*|\(\*\)/g, '(.*)'))(keys, { encode: (value) => value }) } doc.paths[path] = doc.paths[path] || {} diff --git a/test/_routes.js b/test/_routes.js index 30ed39f..e272c11 100644 --- a/test/_routes.js +++ b/test/_routes.js @@ -125,5 +125,103 @@ module.exports = function () { done() }) }) + + test('serve routes with a * wildcard', function (done) { + const app = express() + + const oapi = openapi() + app.use(oapi) + app.get(['/route/:param*'], oapi.path({ + summary: 'Test route.', + responses: { + 200: { + content: { + 'application/json': { + schema: { + type: 'string' + } + } + } + } + } + })) + + supertest(app) + .get(`${openapi.defaultRoutePrefix}.json`) + .expect(200, (err, res) => { + assert(!err, err) + assert.strictEqual(Object.keys((res.body.paths))[0], '/route/{param}') + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters.length, 1) + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters[0].in, 'path') + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters[0].name, 'param') + done() + }) + }) + + test('serve routes with a * wildcard in parentheses', function (done) { + const app = express() + + const oapi = openapi() + app.use(oapi) + app.get(['/route/:param(*)'], oapi.path({ + summary: 'Test route.', + responses: { + 200: { + content: { + 'application/json': { + schema: { + type: 'string' + } + } + } + } + } + })) + + supertest(app) + .get(`${openapi.defaultRoutePrefix}.json`) + .expect(200, (err, res) => { + assert(!err, err) + assert.strictEqual(Object.keys((res.body.paths))[0], '/route/{param}') + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters.length, 1) + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters[0].in, 'path') + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters[0].name, 'param') + done() + }) + }) + + test('serve routes in an array as different routes when one route has a * wildcard', function (done) { + const app = express() + + const oapi = openapi() + app.use(oapi) + app.get(['/route/:param*', '/route/b', '/routeC'], oapi.path({ + summary: 'Test route.', + responses: { + 200: { + content: { + 'application/json': { + schema: { + type: 'string' + } + } + } + } + } + })) + + supertest(app) + .get(`${openapi.defaultRoutePrefix}.json`) + .expect(200, (err, res) => { + assert(!err, err) + assert.strictEqual(Object.keys((res.body.paths))[0], '/route/{param}') + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters.length, 1) + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters[0].in, 'path') + assert.strictEqual(res.body.paths[Object.keys((res.body.paths))[0]].get.parameters[0].name, 'param') + assert.strictEqual(Object.keys((res.body.paths))[1], '/route/b') + assert.strictEqual(Object.keys((res.body.paths))[2], '/routeC') + done() + }) + }) }) }