fastify-swagger
Advanced tools
Comparing version 2.0.0 to 2.1.0
@@ -28,2 +28,3 @@ import * as http from 'http'; | ||
postProcessor?: (spec: SwaggerSchema.Spec) => SwaggerSchema.Spec; | ||
baseDir: string; | ||
} | ||
@@ -30,0 +31,0 @@ |
{ | ||
"name": "fastify-swagger", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Generate Swagger files automatically for Fastify.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -146,4 +146,5 @@ # fastify-swagger | ||
return swaggerObject | ||
} | ||
} | ||
}, | ||
baseDir: '/path/to/external/spec/files/location', | ||
}, | ||
} | ||
@@ -155,2 +156,4 @@ ``` | ||
`specification.baseDir` allows specifying the directory where all spec files that are included in the main one using `$ref` will be located. | ||
By default, this is the directory where the main spec file is located. Provided value should be an absolute path **without** trailing slash. | ||
<a name="additional"></a> | ||
@@ -165,2 +168,3 @@ #### additional | ||
|`'/documentation/'` | the swagger ui | | ||
|`'/documentation/*'`| external files which you may use in `$ref`| | ||
@@ -167,0 +171,0 @@ |
'use strict' | ||
const path = require('path') | ||
const fastifyStatic = require('fastify-static') | ||
// URI prefix to separate static assets for swagger UI | ||
const staticPrefix = '/static' | ||
function fastifySwagger (fastify, opts, next) { | ||
@@ -12,5 +16,5 @@ fastify.route({ | ||
if (fastify.prefix === '/') { | ||
reply.redirect('/index.html') | ||
reply.redirect(`${staticPrefix}/index.html`) | ||
} else { | ||
reply.redirect(`${fastify.prefix}/index.html`) | ||
reply.redirect(`${fastify.prefix}${staticPrefix}/index.html`) | ||
} | ||
@@ -41,6 +45,28 @@ } | ||
// serve swagger-ui with the help of fastify-static | ||
fastify.register(require('fastify-static'), { | ||
root: path.join(__dirname, 'static') | ||
fastify.register(fastifyStatic, { | ||
root: path.join(__dirname, 'static'), | ||
prefix: staticPrefix, | ||
decorateReply: false | ||
}) | ||
fastify.register(fastifyStatic, { | ||
root: opts.baseDir || __dirname, | ||
serve: false | ||
}) | ||
// Handler for external documentation files passed via $ref | ||
fastify.route({ | ||
url: '/*', | ||
method: 'GET', | ||
schema: { hide: true }, | ||
handler: function (req, reply) { | ||
const file = req.params['*'] | ||
if (file === '') { | ||
reply.redirect(302, `${fastify.basePath}${staticPrefix}/index.html`) | ||
} else { | ||
reply.sendFile(file) | ||
} | ||
} | ||
}) | ||
next() | ||
@@ -47,0 +73,0 @@ } |
@@ -25,2 +25,12 @@ 'use strict' | ||
if (opts.specification.baseDir && typeof opts.specification.baseDir !== 'string') return next(new Error('specification.baseDir should be string')) | ||
if (!opts.specification.baseDir) { | ||
opts.specification.baseDir = path.resolve(path.dirname(opts.specification.path)) | ||
} else { | ||
while (opts.specification.baseDir.endsWith('/')) { | ||
opts.specification.baseDir = opts.specification.baseDir.slice(0, -1) | ||
} | ||
} | ||
// read | ||
@@ -53,4 +63,8 @@ const source = fs.readFileSync( | ||
if (opts.exposeRoute === true) { | ||
const prefix = opts.routePrefix || '/documentation' | ||
fastify.register(require('./routes'), { prefix }) | ||
const options = { | ||
prefix: opts.routePrefix || '/documentation', | ||
baseDir: opts.specification.baseDir | ||
} | ||
fastify.register(require('./routes'), options) | ||
} | ||
@@ -57,0 +71,0 @@ |
@@ -168,3 +168,3 @@ 'use strict' | ||
test('/documentation should redirect to /documentation/index.html', t => { | ||
test('/documentation should redirect to /documentation/static/index.html', t => { | ||
t.plan(4) | ||
@@ -187,3 +187,3 @@ const fastify = Fastify() | ||
t.strictEqual(res.statusCode, 302) | ||
t.strictEqual(res.headers['location'], '/documentation/index.html') | ||
t.strictEqual(res.headers['location'], '/documentation/static/index.html') | ||
t.is(typeof res.payload, 'string') | ||
@@ -193,3 +193,3 @@ }) | ||
test('/v1/documentation should redirect to /v1/documentation/index.html', t => { | ||
test('/v1/documentation should redirect to /v1/documentation/static/index.html', t => { | ||
t.plan(4) | ||
@@ -214,3 +214,3 @@ const fastify = Fastify() | ||
t.strictEqual(res.statusCode, 302) | ||
t.strictEqual(res.headers['location'], '/v1/documentation/index.html') | ||
t.strictEqual(res.headers['location'], '/v1/documentation/static/index.html') | ||
t.is(typeof res.payload, 'string') | ||
@@ -220,3 +220,3 @@ }) | ||
test('/v1/foobar should redirect to /v1/foobar/index.html - in plugin', t => { | ||
test('/v1/foobar should redirect to /v1/foobar/static/index.html - in plugin', t => { | ||
t.plan(4) | ||
@@ -246,3 +246,3 @@ const fastify = Fastify() | ||
t.strictEqual(res.statusCode, 302) | ||
t.strictEqual(res.headers['location'], '/v1/foobar/index.html') | ||
t.strictEqual(res.headers['location'], '/v1/foobar/static/index.html') | ||
t.is(typeof res.payload, 'string') | ||
@@ -252,3 +252,3 @@ }) | ||
test('with routePrefix: \'/\' should redirect to /index.html', t => { | ||
test('with routePrefix: \'/\' should redirect to /static/index.html', t => { | ||
t.plan(4) | ||
@@ -269,3 +269,3 @@ const fastify = Fastify() | ||
t.strictEqual(res.statusCode, 302) | ||
t.strictEqual(res.headers['location'], '/index.html') | ||
t.strictEqual(res.headers['location'], '/static/index.html') | ||
t.is(typeof res.payload, 'string') | ||
@@ -275,4 +275,4 @@ }) | ||
test('/documentation/:file should send back the correct file', t => { | ||
t.plan(19) | ||
test('/documentation/static/:file should send back the correct file', t => { | ||
t.plan(24) | ||
const fastify = Fastify() | ||
@@ -295,8 +295,27 @@ | ||
t.is(res.statusCode, 302) | ||
t.is(res.headers['location'], '/documentation/index.html') | ||
t.is(res.headers['location'], '/documentation/static/index.html') | ||
}) | ||
fastify.ready(() => { | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/static/' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.is(typeof res.payload, 'string') | ||
t.is(res.headers['content-type'], 'text/html; charset=UTF-8') | ||
t.strictEqual( | ||
readFileSync( | ||
resolve(__dirname, '..', 'static', 'index.html'), | ||
'utf8' | ||
), | ||
res.payload | ||
) | ||
t.ok(res.payload.indexOf('resolveUrl') !== -1) | ||
}) | ||
}) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/oauth2-redirect.html' | ||
url: '/documentation/static/oauth2-redirect.html' | ||
}, (err, res) => { | ||
@@ -317,3 +336,3 @@ t.error(err) | ||
method: 'GET', | ||
url: '/documentation/swagger-ui.css' | ||
url: '/documentation/static/swagger-ui.css' | ||
}, (err, res) => { | ||
@@ -334,3 +353,3 @@ t.error(err) | ||
method: 'GET', | ||
url: '/documentation/swagger-ui-bundle.js' | ||
url: '/documentation/static/swagger-ui-bundle.js' | ||
}, (err, res) => { | ||
@@ -351,3 +370,3 @@ t.error(err) | ||
method: 'GET', | ||
url: '/documentation/swagger-ui-standalone-preset.js' | ||
url: '/documentation/static/swagger-ui-standalone-preset.js' | ||
}, (err, res) => { | ||
@@ -367,3 +386,3 @@ t.error(err) | ||
test('/documentation/:file 404', t => { | ||
test('/documentation/static/:file 404', t => { | ||
t.plan(3) | ||
@@ -383,3 +402,3 @@ const fastify = Fastify() | ||
method: 'GET', | ||
url: '/documentation/stuff.css' | ||
url: '/documentation/static/stuff.css' | ||
}, (err, res) => { | ||
@@ -428,1 +447,48 @@ t.error(err) | ||
}) | ||
test('/documentation/:myfile should return 404 in dynamic mode', t => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
fastify.register(fastifySwagger, swaggerInfo) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/swagger-ui.js' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 404) | ||
}) | ||
}) | ||
test('/documentation/:myfile should run custom NotFoundHandler in dynamic mode', t => { | ||
t.plan(2) | ||
const fastify = Fastify() | ||
const notFoundHandler = function (req, reply) { | ||
reply.code(410).send() | ||
} | ||
fastify.setNotFoundHandler(notFoundHandler) | ||
fastify.register(fastifySwagger, swaggerInfo) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/swagger-ui.js' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 410) | ||
}) | ||
}) | ||
test('/documentation/ should redirect to documentation/static/index.html', t => { | ||
t.plan(3) | ||
const fastify = Fastify() | ||
fastify.register(fastifySwagger, swaggerInfo) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 302) | ||
t.strictEqual(res.headers.location, '/documentation/static/index.html') | ||
}) | ||
}) |
@@ -9,2 +9,5 @@ 'use strict' | ||
const resolve = require('path').resolve | ||
const readFileSync = require('fs').readFileSync | ||
test('specification validation check works', t => { | ||
@@ -97,3 +100,2 @@ const specifications = [ | ||
// console.log(res.payload) | ||
try { | ||
@@ -183,1 +185,125 @@ var payload = JSON.parse(res.payload) | ||
}) | ||
test('/documentation/:file should serve static file from the location of main specification file', t => { | ||
t.plan(7) | ||
const config = { | ||
exposeRoute: true, | ||
mode: 'static', | ||
specification: { | ||
path: './examples/example-static-specification.yaml' | ||
} | ||
} | ||
const fastify = new Fastify() | ||
fastify.register(fastifySwagger, config) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/non-existing-file' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 404) | ||
}) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/example-static-specification.yaml' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 200) | ||
t.strictEqual( | ||
readFileSync( | ||
resolve(__dirname, '..', 'examples', 'example-static-specification.yaml'), | ||
'utf8' | ||
), | ||
res.payload | ||
) | ||
}) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/dynamic.js' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 200) | ||
}) | ||
}) | ||
test('/documentation/non-existing-file calls custom NotFoundHandler', t => { | ||
t.plan(2) | ||
const config = { | ||
exposeRoute: true, | ||
mode: 'static', | ||
specification: { | ||
path: './examples/example-static-specification.yaml' | ||
} | ||
} | ||
const fastify = new Fastify() | ||
fastify.register(fastifySwagger, config) | ||
fastify.setNotFoundHandler((request, reply) => { | ||
reply.code(410).send() | ||
}) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/some-file-that-does-not-exist.js' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 410) | ||
}) | ||
}) | ||
test('/documentation/:file should be served from custom location', t => { | ||
t.plan(3) | ||
const config = { | ||
exposeRoute: true, | ||
mode: 'static', | ||
specification: { | ||
path: './examples/example-static-specification.yaml', | ||
baseDir: resolve(__dirname, '..', 'static') | ||
} | ||
} | ||
const fastify = new Fastify() | ||
fastify.register(fastifySwagger, config) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/oauth2-redirect.html' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 200) | ||
t.strictEqual( | ||
readFileSync(resolve(__dirname, '..', 'static', 'oauth2-redirect.html'), 'utf8'), | ||
res.payload | ||
) | ||
}) | ||
}) | ||
test('/documentation/:file should be served from custom location with trailing slash(es)', t => { | ||
t.plan(3) | ||
const config = { | ||
exposeRoute: true, | ||
mode: 'static', | ||
specification: { | ||
path: './examples/example-static-specification.yaml', | ||
baseDir: resolve(__dirname, '..', 'static') + '/' | ||
} | ||
} | ||
const fastify = new Fastify() | ||
fastify.register(fastifySwagger, config) | ||
fastify.inject({ | ||
method: 'GET', | ||
url: '/documentation/oauth2-redirect.html' | ||
}, (err, res) => { | ||
t.error(err) | ||
t.strictEqual(res.statusCode, 200) | ||
t.strictEqual( | ||
readFileSync(resolve(__dirname, '..', 'static', 'oauth2-redirect.html'), 'utf8'), | ||
res.payload | ||
) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
9215941
10509
224
8