Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fastify-swagger

Package Overview
Dependencies
Maintainers
17
Versions
100
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify-swagger - npm Package Compare versions

Comparing version 4.12.6 to 4.13.0

6

lib/spec/openapi/utils.js

@@ -83,2 +83,8 @@ 'use strict'

if (typeof jsonSchema === 'object' && jsonSchema !== null) {
// Handle patternProperties, that is not part of OpenAPI definitions
if (jsonSchema.patternProperties) {
jsonSchema.additionalProperties = { type: 'string' }
delete jsonSchema.patternProperties
}
Object.keys(jsonSchema).forEach(function (key) {

@@ -85,0 +91,0 @@ if (key === '$ref') {

@@ -158,2 +158,21 @@ 'use strict'

/*
* Map unsupported JSON schema definitions to Swagger definitions
*/
function replaceUnsupported (jsonSchema) {
if (typeof jsonSchema === 'object' && jsonSchema !== null) {
// Handle patternProperties, that is not part of OpenAPI definitions
if (jsonSchema.patternProperties) {
jsonSchema.additionalProperties = { type: 'string' }
delete jsonSchema.patternProperties
}
Object.keys(jsonSchema).forEach(function (key) {
jsonSchema[key] = replaceUnsupported(jsonSchema[key])
})
}
return jsonSchema
}
function isConsumesFormOnly (schema) {

@@ -172,2 +191,4 @@ const consumes = schema.consumes

replaceUnsupported(resolved)
parameters.push({

@@ -229,2 +250,3 @@ name: 'body',

const schema = { ...resolved }
replaceUnsupported(schema)
delete schema[xResponseDescription]

@@ -231,0 +253,0 @@ response.schema = schema

82

lib/util/common.js

@@ -72,12 +72,76 @@ 'use strict'

// custom verbs at the end of a url are okay => /user::watch but should be rendered as /user:watch in swagger
function formatParamUrl (url) {
const regex = /(?<!:):([a-zA-Z0-9_]+)/g
let found = regex.exec(url)
while (found !== null) {
const [full, param] = found
url = url.replace(full, '{' + param + '}')
found = regex.exec(url)
const COLON = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'
function formatParamUrl (str) {
let i, char
let state = 'skip'
let path = ''
let param = ''
let level = 0
// count for regex if no param exist
let regexp = 0
for (i = 0; i < str.length; i++) {
char = str[i]
switch (state) {
case 'colon': {
// we only accept a-zA-Z0-9_ in param
if (COLON.indexOf(char) !== -1) {
param += char
} else if (char === '(') {
state = 'regexp'
level++
} else {
// end
state = 'skip'
path += '{' + param + '}'
path += char
param = ''
}
break
}
case 'regexp': {
if (char === '(') {
level++
} else if (char === ')') {
level--
}
// we end if the level reach zero
if (level === 0) {
state = 'skip'
if (param === '') {
regexp++
param = 'regexp' + String(regexp)
}
path += '{' + param + '}'
param = ''
}
break
}
default: {
// we check if we need to change state
if (char === ':' && str[i + 1] === ':') {
// double colon -> single colon
path += char
// skip one more
i++
} else if (char === ':') {
// single colon -> state colon
state = 'colon'
} else if (char === '(') {
state = 'regexp'
level++
} else if (char === '*') {
// * -> wildcard
// should be exist once only
path += '{wildcard}'
} else {
path += char
}
}
}
}
return url.replace(/::/g, ':')
// clean up
if (state === 'colon' && param !== '') {
path += '{' + param + '}'
}
return path
}

@@ -84,0 +148,0 @@

10

package.json
{
"name": "fastify-swagger",
"version": "4.12.6",
"version": "4.13.0",
"description": "Serve Swagger/OpenAPI documentation for Fastify, supporting dynamic generation",

@@ -38,3 +38,3 @@ "main": "index.js",

"devDependencies": {
"@types/node": "^16.0.0",
"@types/node": "^17.0.0",
"fastify": "^3.7.0",

@@ -51,5 +51,5 @@ "fastify-basic-auth": "^2.1.0",

"swagger-parser": "^10.0.2",
"swagger-ui-dist": "3.52.5",
"swagger-ui-dist": "4.1.3",
"tap": "^15.0.1",
"tsd": "^0.18.0"
"tsd": "^0.19.0"
},

@@ -61,3 +61,3 @@ "dependencies": {

"json-schema-resolver": "^1.3.0",
"openapi-types": "^9.1.0"
"openapi-types": "^10.0.0"
},

@@ -64,0 +64,0 @@ "standard": {

@@ -419,1 +419,58 @@ 'use strict'

})
test('support "patternProperties" parameter', async t => {
const opt = {
schema: {
response: {
200: {
description: 'Expected Response',
type: 'object',
properties: {
foo: {
type: 'object',
patternProperties: {
'^[a-z]{2,3}-[a-zA-Z]{2}$': {
type: 'string'
}
},
additionalProperties: false
}
}
}
}
}
}
const fastify = Fastify()
fastify.register(fastifySwagger, {
openapi: true,
routePrefix: '/docs',
exposeRoute: true
})
fastify.get('/', opt, () => {})
await fastify.ready()
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
const definedPath = api.paths['/'].get
t.same(definedPath.responses[200], {
description: 'Expected Response',
content: {
'application/json': {
schema: {
description: 'Expected Response',
type: 'object',
properties: {
foo: {
type: 'object',
additionalProperties: { type: 'string' }
}
}
}
}
}
})
})

@@ -418,1 +418,67 @@ 'use strict'

})
test('support "patternProperties" in json schema', async t => {
const opt = {
schema: {
body: {
type: 'object',
patternProperties: {
'^[a-z]{2,3}-[a-zA-Z]{2}$': {
type: 'string'
}
}
},
response: {
200: {
description: 'Expected Response',
type: 'object',
properties: {
foo: {
type: 'object',
patternProperties: {
'^[a-z]{2,3}-[a-zA-Z]{2}$': {
type: 'string'
}
},
additionalProperties: false
}
}
}
}
}
}
const fastify = Fastify()
fastify.register(fastifySwagger, {
swagger: true,
routePrefix: '/docs',
exposeRoute: true
})
fastify.get('/', opt, () => {})
await fastify.ready()
const swaggerObject = fastify.swagger()
const api = await Swagger.validate(swaggerObject)
const definedPath = api.paths['/'].get
t.same(definedPath.parameters[0].schema, {
type: 'object',
additionalProperties: { type: 'string' }
})
t.same(definedPath.responses[200], {
description: 'Expected Response',
schema: {
description: 'Expected Response',
type: 'object',
properties: {
foo: {
type: 'object',
additionalProperties: { type: 'string' }
}
}
}
})
})

@@ -6,28 +6,23 @@ 'use strict'

const cases = [
['/example/:userId', '/example/{userId}'],
['/example/:userId/:secretToken', '/example/{userId}/{secretToken}'],
['/example/near/:lat-:lng/radius/:r', '/example/near/{lat}-{lng}/radius/{r}'],
['/example/near/:lat_1-:lng_1/radius/:r_1', '/example/near/{lat_1}-{lng_1}/radius/{r_1}'],
['/example/*', '/example/{wildcard}'],
['/example/:file(^\\d+).png', '/example/{file}.png'],
['/example/at/:hour(^\\d{2})h:minute(^\\d{2})m', '/example/at/{hour}h{minute}m'],
['/example/at/(^\\d{2})h(^\\d{2})m', '/example/at/{regexp1}h{regexp2}m'],
['/example/at/(^([0-9]{2})h$)-(^([0-9]{2})m$)', '/example/at/{regexp1}-{regexp2}'],
['/name::verb', '/name:verb'],
['/api/v1/postalcode-jp/:code(^[0-9]{7}$)', '/api/v1/postalcode-jp/{code}'],
['/api/v1/postalcode-jp/(^[0-9]{7}$)', '/api/v1/postalcode-jp/{regexp1}']
]
test('formatParamUrl', t => {
t.plan(4)
t.plan(cases.length)
t.test('support /example/:userId', t => {
t.plan(1)
const url = formatParamUrl('/example/:userId')
t.equal(url, '/example/{userId}')
})
t.test('support /example/:userId/:secretToken', t => {
t.plan(1)
const url = formatParamUrl('/example/:userId/:secretToken')
t.equal(url, '/example/{userId}/{secretToken}')
})
t.test('support /example/near/:lat-:lng/radius/:r', t => {
t.plan(1)
const url = formatParamUrl('/example/near/:lat-:lng/radius/:r')
t.equal(url, '/example/near/{lat}-{lng}/radius/{r}')
})
t.test('support /example/near/:lat_1-:lng_1/radius/:r_1', t => {
t.plan(1)
const url = formatParamUrl('/example/near/:lat_1-:lng_1/radius/:r_1')
t.equal(url, '/example/near/{lat_1}-{lng_1}/radius/{r_1}')
})
for (const kase of cases) {
t.equal(formatParamUrl(kase[0]), kase[1])
}
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc