Projektstart
This commit is contained in:
5
backend/node_modules/@fastify/swagger/.gitattributes
generated
vendored
Normal file
5
backend/node_modules/@fastify/swagger/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set
|
||||
* text=auto
|
||||
|
||||
# Require Unix line endings
|
||||
* text eol=lf
|
||||
13
backend/node_modules/@fastify/swagger/.github/dependabot.yml
generated
vendored
Normal file
13
backend/node_modules/@fastify/swagger/.github/dependabot.yml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
21
backend/node_modules/@fastify/swagger/.github/stale.yml
generated
vendored
Normal file
21
backend/node_modules/@fastify/swagger/.github/stale.yml
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 15
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- "discussion"
|
||||
- "feature request"
|
||||
- "bug"
|
||||
- "help wanted"
|
||||
- "plugin suggestion"
|
||||
- "good first issue"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
3
backend/node_modules/@fastify/swagger/.github/tests_checker.yml
generated
vendored
Normal file
3
backend/node_modules/@fastify/swagger/.github/tests_checker.yml
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
comment: 'Could you please add tests to make sure this change works as expected?',
|
||||
fileExtensions: ['.php', '.ts', '.js', '.c', '.cs', '.cpp', '.rb', '.java']
|
||||
testDir: 'test'
|
||||
33
backend/node_modules/@fastify/swagger/.github/workflows/ci.yml
generated
vendored
Normal file
33
backend/node_modules/@fastify/swagger/.github/workflows/ci.yml
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- next
|
||||
- 'v*'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
|
||||
with:
|
||||
license-check: true
|
||||
lint: true
|
||||
23
backend/node_modules/@fastify/swagger/LICENSE
generated
vendored
Normal file
23
backend/node_modules/@fastify/swagger/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-present The Fastify team
|
||||
|
||||
The Fastify team members are listed at https://github.com/fastify/fastify#team.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
177
backend/node_modules/@fastify/swagger/MIGRATION.md
generated
vendored
Normal file
177
backend/node_modules/@fastify/swagger/MIGRATION.md
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
# Migration
|
||||
|
||||
## Migrating from version 7 to 8
|
||||
|
||||
As of version 8 `@fastify/swagger` is only responsible for generating valid
|
||||
swagger/openapi-specifications. The new `@fastify/swagger-ui` plugin is
|
||||
responsible for serving the swagger-ui frontend.
|
||||
|
||||
Options in version 7 of `@fastify/swagger` related to the configuration
|
||||
of the swagger-ui frontend are now options of `@fastify/swagger-ui`.
|
||||
|
||||
The `exposeRoute` option is removed.
|
||||
|
||||
Following are the `@fastify/swagger-ui` options:
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| baseDir | undefined | Only relevant if `@fastify/swagger` used in static-mode and additional schema-files contain referenced schemas. Specify 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. |
|
||||
| initOAuth | {} | Configuration options for [Swagger UI initOAuth](https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/). |
|
||||
| routePrefix | '/documentation' | Overwrite the default Swagger UI route prefix. |
|
||||
| staticCSP | false | Enable CSP header for static resources. |
|
||||
| transformStaticCSP | undefined | Synchronous function to transform CSP header for static resources if the header has been previously set. |
|
||||
| uiConfig | {} | Configuration options for [Swagger UI](https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md). Must be literal values, see [#5710](https://github.com/swagger-api/swagger-ui/issues/5710).|
|
||||
| uiHooks | {} | Additional hooks for the documentation's routes. You can provide the `onRequest` and `preHandler` hooks with the same [route's options](https://fastify.dev/docs/latest/Reference/Routes/#options) interface.|
|
||||
|
||||
The `baseDir` option is new and is only needed if external spec files should be
|
||||
exposed. `baseDir` option of `@fastify/swagger-ui` should be set to the same
|
||||
value as the `specification.baseDir` option of `@fastify/swagger`.
|
||||
|
||||
### Example (static-mode):
|
||||
|
||||
before:
|
||||
```js
|
||||
import Fastify from 'fastify'
|
||||
import fastifySwagger from '@fastify/swagger'
|
||||
|
||||
const fastify = new Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml',
|
||||
postProcessor: function(swaggerObject) {
|
||||
return swaggerObject
|
||||
},
|
||||
baseDir: '/path/to/external/spec/files/location',
|
||||
},
|
||||
exposeRoute: true,
|
||||
routePrefix: '/documentation',
|
||||
initOAuth: { },
|
||||
uiConfig: {
|
||||
docExpansion: 'full',
|
||||
deepLinking: false
|
||||
},
|
||||
uiHooks: {
|
||||
onRequest: function (request, reply, next) { next() },
|
||||
preHandler: function (request, reply, next) { next() }
|
||||
},
|
||||
staticCSP: true,
|
||||
transformStaticCSP: (header) => header
|
||||
})
|
||||
```
|
||||
|
||||
after:
|
||||
```js
|
||||
import Fastify from 'fastify'
|
||||
import fastifySwagger from '@fastify/swagger'
|
||||
import fastifySwaggerUi from '@fastify/swagger-ui'
|
||||
|
||||
const fastify = new Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml',
|
||||
postProcessor: function(swaggerObject) {
|
||||
return swaggerObject
|
||||
},
|
||||
baseDir: '/path/to/external/spec/files/location'
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.register(fastifySwaggerUi, {
|
||||
baseDir: '/path/to/external/spec/files/location',
|
||||
routePrefix: '/documentation',
|
||||
initOAuth: { },
|
||||
uiConfig: {
|
||||
docExpansion: 'full',
|
||||
deepLinking: false
|
||||
},
|
||||
uiHooks: {
|
||||
onRequest: function (request, reply, next) { next() },
|
||||
preHandler: function (request, reply, next) { next() }
|
||||
},
|
||||
staticCSP: true,
|
||||
transformStaticCSP: (header) => header
|
||||
})
|
||||
```
|
||||
|
||||
### Example (dynamic-mode):
|
||||
|
||||
before:
|
||||
```js
|
||||
import Fastify from 'fastify'
|
||||
import fastifySwagger from '@fastify/swagger'
|
||||
|
||||
const fastify = new Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
mode: 'dynamic',
|
||||
openapi: {
|
||||
info: {
|
||||
title: String,
|
||||
description: String,
|
||||
version: String,
|
||||
},
|
||||
externalDocs: Object,
|
||||
servers: [ Object ],
|
||||
components: Object,
|
||||
security: [ Object ],
|
||||
tags: [ Object ]
|
||||
},
|
||||
exposeRoute: true,
|
||||
routePrefix: '/documentation',
|
||||
initOAuth: { },
|
||||
uiConfig: {
|
||||
docExpansion: 'full',
|
||||
deepLinking: false
|
||||
},
|
||||
uiHooks: {
|
||||
onRequest: function (request, reply, next) { next() },
|
||||
preHandler: function (request, reply, next) { next() }
|
||||
},
|
||||
staticCSP: true,
|
||||
transformStaticCSP: (header) => header
|
||||
})
|
||||
```
|
||||
|
||||
after:
|
||||
```js
|
||||
import Fastify from 'fastify'
|
||||
import fastifySwagger from '@fastify/swagger'
|
||||
import fastifySwaggerUi from '@fastify/swagger-ui'
|
||||
|
||||
const fastify = new Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
mode: 'dynamic',
|
||||
openapi: {
|
||||
info: {
|
||||
title: String,
|
||||
description: String,
|
||||
version: String,
|
||||
},
|
||||
externalDocs: Object,
|
||||
servers: [ Object ],
|
||||
components: Object,
|
||||
security: [ Object ],
|
||||
tags: [ Object ]
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.register(fastifySwaggerUi, {
|
||||
routePrefix: '/documentation',
|
||||
initOAuth: { },
|
||||
uiConfig: {
|
||||
docExpansion: 'full',
|
||||
deepLinking: false
|
||||
},
|
||||
uiHooks: {
|
||||
onRequest: function (request, reply, next) { next() },
|
||||
preHandler: function (request, reply, next) { next() }
|
||||
},
|
||||
staticCSP: true,
|
||||
transformStaticCSP: (header) => header
|
||||
})
|
||||
```
|
||||
1156
backend/node_modules/@fastify/swagger/README.md
generated
vendored
Normal file
1156
backend/node_modules/@fastify/swagger/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
backend/node_modules/@fastify/swagger/eslint.config.js
generated
vendored
Normal file
9
backend/node_modules/@fastify/swagger/eslint.config.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('neostandard')({
|
||||
ignores: [
|
||||
...require('neostandard').resolveIgnoresFromGitignore(),
|
||||
'static'
|
||||
],
|
||||
ts: true
|
||||
})
|
||||
52
backend/node_modules/@fastify/swagger/examples/collection-format.js
generated
vendored
Normal file
52
backend/node_modules/@fastify/swagger/examples/collection-format.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')({
|
||||
// Need to add a collectionFormat keyword to ajv in fastify instance
|
||||
ajv: {
|
||||
customOptions: {
|
||||
keywords: ['collectionFormat']
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fastify.register(require('../index'), {
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
required: ['fields'],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
fields: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
},
|
||||
minItems: 1,
|
||||
//
|
||||
// Note that this is an Open API version 2 configuration option. The
|
||||
// options changed in version 3. The plugin currently only supports
|
||||
// version 2 of Open API.
|
||||
//
|
||||
// Put `collectionFormat` on the same property which you are defining
|
||||
// as an array of values. (i.e. `collectionFormat` should be a sibling
|
||||
// of the `type: "array"` specification.)
|
||||
collectionFormat: 'multi'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
handler (request, reply) {
|
||||
reply.send(request.query.fields)
|
||||
}
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, (err, addr) => {
|
||||
if (err) throw err
|
||||
console.log(`listening on ${addr}`)
|
||||
})
|
||||
170
backend/node_modules/@fastify/swagger/examples/dynamic-openapi.js
generated
vendored
Normal file
170
backend/node_modules/@fastify/swagger/examples/dynamic-openapi.js
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')()
|
||||
|
||||
fastify.register(require('../index'), {
|
||||
openapi: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
servers: [{
|
||||
url: 'http://localhost'
|
||||
}],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
hideUntagged: true,
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.register(async function (fastify) {
|
||||
fastify.put('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'post some data',
|
||||
tags: ['user', 'code'],
|
||||
summary: 'qwerty',
|
||||
security: [{ apiKey: [] }],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'user id'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
response: {
|
||||
201: {
|
||||
description: 'Succesful response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
},
|
||||
default: {
|
||||
description: 'Default response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (req, reply) => { reply.send({ hello: `Hello ${req.body.hello}` }) })
|
||||
|
||||
fastify.post('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'post some data',
|
||||
summary: 'qwerty',
|
||||
security: [{ apiKey: [] }],
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'user id'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
response: {
|
||||
201: {
|
||||
description: 'Succesful response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (req, reply) => { reply.send({ hello: `Hello ${req.body.hello}` }) })
|
||||
})
|
||||
|
||||
fastify.post('/subscribe', {
|
||||
schema: {
|
||||
description: 'subscribe for webhooks',
|
||||
summary: 'webhook example',
|
||||
security: [],
|
||||
response: {
|
||||
201: {
|
||||
description: 'Succesful response'
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
callbackUrl: {
|
||||
type: 'string',
|
||||
examples: ['https://example.com']
|
||||
}
|
||||
}
|
||||
},
|
||||
callbacks: {
|
||||
myEvent: {
|
||||
'{$request.body#/callbackUrl}': {
|
||||
post: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
message: {
|
||||
type: 'string',
|
||||
example: 'Some event happened'
|
||||
}
|
||||
},
|
||||
required: [
|
||||
'message'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Success'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, err => {
|
||||
if (err) throw err
|
||||
})
|
||||
63
backend/node_modules/@fastify/swagger/examples/dynamic-overwrite-endpoint.js
generated
vendored
Normal file
63
backend/node_modules/@fastify/swagger/examples/dynamic-overwrite-endpoint.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')()
|
||||
|
||||
fastify.register(require('../index'), {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
host: 'localhost',
|
||||
schemes: ['http'],
|
||||
consumes: ['application/json'],
|
||||
produces: ['application/json']
|
||||
},
|
||||
exposeRoute: true,
|
||||
routePrefix: '/swagger-docs'
|
||||
})
|
||||
|
||||
fastify.register(async function (fastify) {
|
||||
fastify.put('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'post some data',
|
||||
tags: ['user', 'code'],
|
||||
summary: 'qwerty',
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'user id'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
response: {
|
||||
201: {
|
||||
description: 'Succesful response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, err => {
|
||||
if (err) throw err
|
||||
})
|
||||
109
backend/node_modules/@fastify/swagger/examples/dynamic-swagger.js
generated
vendored
Normal file
109
backend/node_modules/@fastify/swagger/examples/dynamic-swagger.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')()
|
||||
|
||||
fastify.register(require('../index'), {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
securityDefinitions: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
},
|
||||
host: 'localhost:3000',
|
||||
schemes: ['http'],
|
||||
consumes: ['application/json'],
|
||||
produces: ['application/json']
|
||||
},
|
||||
hideUntagged: true,
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.addSchema({
|
||||
$id: 'user',
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'user id'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fastify.addSchema({
|
||||
$id: 'some',
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
})
|
||||
|
||||
fastify.register(async function (fastify) {
|
||||
fastify.put('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'post some data',
|
||||
tags: ['user', 'code'],
|
||||
summary: 'qwerty',
|
||||
security: [{ apiKey: [] }],
|
||||
params: { $ref: 'user#' },
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: { $ref: 'some#' }
|
||||
}
|
||||
},
|
||||
response: {
|
||||
201: {
|
||||
description: 'Succesful response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
},
|
||||
default: {
|
||||
description: 'Default response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (req, reply) => { reply.send({ hello: `Hello ${req.body.hello}` }) })
|
||||
|
||||
fastify.post('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'post some data',
|
||||
summary: 'qwerty',
|
||||
security: [{ apiKey: [] }],
|
||||
params: { $ref: 'user#' },
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: { $ref: 'some#' }
|
||||
}
|
||||
},
|
||||
response: {
|
||||
201: {
|
||||
description: 'Succesful response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (req, reply) => { reply.send({ hello: `Hello ${req.body.hello}` }) })
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, err => {
|
||||
if (err) throw err
|
||||
})
|
||||
0
backend/node_modules/@fastify/swagger/examples/example-static-specification.js
generated
vendored
Normal file
0
backend/node_modules/@fastify/swagger/examples/example-static-specification.js
generated
vendored
Normal file
51
backend/node_modules/@fastify/swagger/examples/example-static-specification.json
generated
vendored
Normal file
51
backend/node_modules/@fastify/swagger/examples/example-static-specification.json
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"description": "Test swagger specification",
|
||||
"version": "1.0.0",
|
||||
"title": "Test swagger specification",
|
||||
"contact": {
|
||||
"email": "super.developer@gmail.com"
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://localhost:3000/",
|
||||
"description": "Localhost (uses test data)"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/status": {
|
||||
"get": {
|
||||
"description": "Status route, so we can check if server is alive",
|
||||
"tags": [
|
||||
"Status"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Server is alive",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"health": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"health": true,
|
||||
"date": "2018-02-19T15:36:46.758Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
backend/node_modules/@fastify/swagger/examples/example-static-specification.yaml
generated
vendored
Normal file
31
backend/node_modules/@fastify/swagger/examples/example-static-specification.yaml
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
description: Test swagger specification
|
||||
version: 1.0.0
|
||||
title: Test swagger specification
|
||||
contact:
|
||||
email: super.developer@gmail.com
|
||||
servers:
|
||||
- url: http://localhost:3000/
|
||||
description: Localhost (uses test data)
|
||||
paths:
|
||||
/status:
|
||||
get:
|
||||
description: Status route, so we can check if server is alive
|
||||
tags:
|
||||
- Status
|
||||
responses:
|
||||
"200":
|
||||
description: Server is alive
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
health:
|
||||
type: boolean
|
||||
date:
|
||||
type: string
|
||||
example:
|
||||
health: true
|
||||
date: 2018-02-19T15:36:46.758Z
|
||||
72
backend/node_modules/@fastify/swagger/examples/json-in-querystring.js
generated
vendored
Normal file
72
backend/node_modules/@fastify/swagger/examples/json-in-querystring.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
'use strict'
|
||||
|
||||
const qs = require('qs')
|
||||
const Ajv = require('ajv')
|
||||
|
||||
const ajv = new Ajv({
|
||||
removeAdditional: true,
|
||||
useDefaults: true,
|
||||
coerceTypes: true
|
||||
})
|
||||
|
||||
const fastify = require('fastify')({
|
||||
querystringParser: (str) => {
|
||||
const result = qs.parse(str)
|
||||
|
||||
if (result.filter && typeof result.filter === 'string') {
|
||||
result.filter = JSON.parse(result.filter)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
})
|
||||
|
||||
ajv.addKeyword({
|
||||
keyword: 'x-consume',
|
||||
code: () => Promise.resolve(true)
|
||||
})
|
||||
|
||||
fastify.setValidatorCompiler(({ schema }) => ajv.compile(schema))
|
||||
|
||||
fastify.register(require('../index'), {
|
||||
openapi: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
}
|
||||
},
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.register(async function (fastify) {
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
required: ['filter'],
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
filter: {
|
||||
type: 'object',
|
||||
required: ['foo'],
|
||||
properties: {
|
||||
foo: { type: 'string' },
|
||||
bar: { type: 'string' }
|
||||
},
|
||||
'x-consume': 'application/json'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
handler (request, reply) {
|
||||
reply.send(request.query.filter)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, (err) => {
|
||||
if (err) throw err
|
||||
})
|
||||
388
backend/node_modules/@fastify/swagger/examples/options.js
generated
vendored
Normal file
388
backend/node_modules/@fastify/swagger/examples/options.js
generated
vendored
Normal file
@@ -0,0 +1,388 @@
|
||||
'use strict'
|
||||
|
||||
const swaggerOption = {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
host: 'localhost',
|
||||
schemes: ['http'],
|
||||
consumes: ['application/json'],
|
||||
produces: ['application/json'],
|
||||
tags: [
|
||||
{ name: 'tag' }
|
||||
],
|
||||
externalDocs: {
|
||||
description: 'Find more info here',
|
||||
url: 'https://swagger.io'
|
||||
},
|
||||
securityDefinitions: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
},
|
||||
security: [{
|
||||
apiKey: []
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
const openapiOption = {
|
||||
openapi: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: 'http://localhost'
|
||||
}
|
||||
],
|
||||
tags: [
|
||||
{ name: 'tag' }
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
},
|
||||
bearerAuth: {
|
||||
type: 'http',
|
||||
scheme: 'bearer'
|
||||
}
|
||||
}
|
||||
},
|
||||
security: [{
|
||||
apiKey: [],
|
||||
bearerAuth: []
|
||||
}],
|
||||
externalDocs: {
|
||||
description: 'Find more info here',
|
||||
url: 'https://swagger.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const openapiWebHookOption = {
|
||||
openapi: {
|
||||
openapi: '3.1.0',
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: 'http://localhost'
|
||||
}
|
||||
],
|
||||
tags: [{ name: 'tag' }],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
},
|
||||
schemas: {
|
||||
Pet: {
|
||||
require: ['id', 'name'],
|
||||
properties: {
|
||||
id: {
|
||||
type: 'integer',
|
||||
format: 'int64'
|
||||
},
|
||||
name: {
|
||||
type: 'string'
|
||||
},
|
||||
tag: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
security: [
|
||||
{
|
||||
apiKey: []
|
||||
}
|
||||
],
|
||||
externalDocs: {
|
||||
description: 'Find more info here',
|
||||
url: 'https://swagger.io'
|
||||
},
|
||||
webhooks: {
|
||||
newPet: {
|
||||
post: {
|
||||
requestBody: {
|
||||
description: 'Information about a new pet in the system',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
$ref: '#/components/schemas/Pet'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description:
|
||||
'Return a 200 status to indicate that the data was received successfully'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const openapiRelativeOptions = {
|
||||
openapi: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: '/test'
|
||||
}
|
||||
],
|
||||
tags: [
|
||||
{ name: 'tag' }
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
}
|
||||
},
|
||||
security: [{
|
||||
apiKey: []
|
||||
}],
|
||||
externalDocs: {
|
||||
description: 'Find more info here',
|
||||
url: 'https://swagger.io'
|
||||
}
|
||||
},
|
||||
stripBasePath: false
|
||||
}
|
||||
|
||||
const schemaQuerystring = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
world: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaBody = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' },
|
||||
constantProp: { const: 'my-const' }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaParams = {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'user id'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaHeaders = {
|
||||
schema: {
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authorization: {
|
||||
type: 'string',
|
||||
description: 'api token'
|
||||
}
|
||||
},
|
||||
required: ['authorization']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaHeadersParams = {
|
||||
schema: {
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
'x-api-token': {
|
||||
type: 'string',
|
||||
description: 'optional api token'
|
||||
},
|
||||
'x-api-version': {
|
||||
type: 'string',
|
||||
description: 'optional api version'
|
||||
}
|
||||
}
|
||||
},
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'user id'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaSecurity = {
|
||||
schema: {
|
||||
security: [
|
||||
{
|
||||
apiKey: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const schemaConsumes = {
|
||||
schema: {
|
||||
consumes: ['application/x-www-form-urlencoded'],
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
description: 'hello',
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaProduces = {
|
||||
schema: {
|
||||
produces: ['*/*'],
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
description: 'hello',
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaCookies = {
|
||||
schema: {
|
||||
cookies: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bar: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaAllOf = {
|
||||
schema: {
|
||||
querystring: {
|
||||
allOf: [
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const schemaExtension = {
|
||||
schema: {
|
||||
'x-tension': true
|
||||
}
|
||||
}
|
||||
|
||||
const schemaOperationId = {
|
||||
schema: {
|
||||
operationId: 'helloWorld',
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
description: 'hello',
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
openapiOption,
|
||||
openapiRelativeOptions,
|
||||
openapiWebHookOption,
|
||||
swaggerOption,
|
||||
schemaQuerystring,
|
||||
schemaBody,
|
||||
schemaParams,
|
||||
schemaHeaders,
|
||||
schemaHeadersParams,
|
||||
schemaSecurity,
|
||||
schemaConsumes,
|
||||
schemaProduces,
|
||||
schemaCookies,
|
||||
schemaAllOf,
|
||||
schemaExtension,
|
||||
schemaOperationId
|
||||
}
|
||||
17
backend/node_modules/@fastify/swagger/examples/static-json-file.js
generated
vendored
Normal file
17
backend/node_modules/@fastify/swagger/examples/static-json-file.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')({ logger: true })
|
||||
// const swagger = require('@fastify/swagger')
|
||||
const swagger = require('..')
|
||||
|
||||
fastify.register(swagger, {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
},
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, (err) => {
|
||||
if (err) throw err
|
||||
})
|
||||
17
backend/node_modules/@fastify/swagger/examples/static-yaml-file.js
generated
vendored
Normal file
17
backend/node_modules/@fastify/swagger/examples/static-yaml-file.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')({ logger: true })
|
||||
// const swagger = require('@fastify/swagger')
|
||||
const swagger = require('..')
|
||||
|
||||
fastify.register(swagger, {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml'
|
||||
},
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, (err) => {
|
||||
if (err) throw err
|
||||
})
|
||||
3
backend/node_modules/@fastify/swagger/examples/test-package.json
generated
vendored
Normal file
3
backend/node_modules/@fastify/swagger/examples/test-package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "test"
|
||||
}
|
||||
197
backend/node_modules/@fastify/swagger/index.d.ts
generated
vendored
Normal file
197
backend/node_modules/@fastify/swagger/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
import { FastifyPluginCallback, FastifySchema, RouteOptions } from 'fastify'
|
||||
import {
|
||||
OpenAPI,
|
||||
OpenAPIV2,
|
||||
OpenAPIV3,
|
||||
// eslint-disable-next-line camelcase
|
||||
OpenAPIV3_1
|
||||
} from 'openapi-types'
|
||||
|
||||
/**
|
||||
* Swagger-UI Vendor Extensions
|
||||
* @see https://support.smartbear.com/swaggerhub/docs/apis/vendor-extensions.html#api-docs-x-tokenname
|
||||
*/
|
||||
declare module 'openapi-types' {
|
||||
namespace OpenAPIV3 {
|
||||
interface OAuth2SecurityScheme {
|
||||
'x-tokenName'?: string;
|
||||
}
|
||||
}
|
||||
namespace OpenAPIV2 {
|
||||
interface SecuritySchemeOauth2Base {
|
||||
'x-tokenName'?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'fastify' {
|
||||
interface FastifyInstance {
|
||||
swagger:
|
||||
((opts?: { yaml?: false }) => OpenAPI.Document) &
|
||||
((opts: { yaml: true }) => string) &
|
||||
((opts: { yaml: boolean }) => OpenAPI.Document | string);
|
||||
|
||||
swaggerCSP: {
|
||||
script: string[];
|
||||
style: string[];
|
||||
}
|
||||
}
|
||||
|
||||
interface FastifySchema {
|
||||
hide?: boolean;
|
||||
deprecated?: boolean;
|
||||
tags?: readonly string[];
|
||||
description?: string;
|
||||
summary?: string;
|
||||
consumes?: readonly string[];
|
||||
produces?: readonly string[];
|
||||
externalDocs?: OpenAPIV2.ExternalDocumentationObject | OpenAPIV3.ExternalDocumentationObject;
|
||||
security?: ReadonlyArray<{ [securityLabel: string]: readonly string[] }>;
|
||||
/**
|
||||
* OpenAPI operation unique identifier
|
||||
*/
|
||||
operationId?: string;
|
||||
}
|
||||
|
||||
interface RouteShorthandOptions {
|
||||
links?: {
|
||||
[statusCode: string]: OpenAPIV3.ResponseObject['links'];
|
||||
}
|
||||
}
|
||||
|
||||
interface FastifyContextConfig {
|
||||
swaggerTransform?: fastifySwagger.SwaggerTransform | false;
|
||||
swagger?: {
|
||||
exposeHeadRoute?: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type SwaggerDocumentObject = {
|
||||
swaggerObject: Partial<OpenAPIV2.Document>;
|
||||
} | {
|
||||
// eslint-disable-next-line camelcase
|
||||
openapiObject: Partial<OpenAPIV3.Document | OpenAPIV3_1.Document>;
|
||||
}
|
||||
|
||||
type FastifySwagger = FastifyPluginCallback<fastifySwagger.SwaggerOptions>
|
||||
|
||||
declare namespace fastifySwagger {
|
||||
export type SwaggerOptions = (FastifyStaticSwaggerOptions | FastifyDynamicSwaggerOptions)
|
||||
export interface FastifySwaggerOptions {
|
||||
mode?: 'static' | 'dynamic';
|
||||
}
|
||||
|
||||
type JSONValue =
|
||||
| string
|
||||
| null
|
||||
| number
|
||||
| boolean
|
||||
| JSONObject
|
||||
| Array<JSONValue>
|
||||
|
||||
export interface JSONObject {
|
||||
[key: string]: JSONValue;
|
||||
}
|
||||
|
||||
export type SwaggerTransform<S extends FastifySchema = FastifySchema> = ({
|
||||
schema,
|
||||
url,
|
||||
route,
|
||||
...documentObject
|
||||
}: {
|
||||
schema: S;
|
||||
url: string;
|
||||
route: RouteOptions;
|
||||
} & SwaggerDocumentObject) => { schema: FastifySchema; url: string }
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export type SwaggerTransformObject = (documentObject: SwaggerDocumentObject) => Partial<OpenAPIV2.Document> | Partial<OpenAPIV3.Document | OpenAPIV3_1.Document>
|
||||
|
||||
export interface FastifyDynamicSwaggerOptions extends FastifySwaggerOptions {
|
||||
mode?: 'dynamic';
|
||||
swagger?: Partial<OpenAPIV2.Document>;
|
||||
// eslint-disable-next-line camelcase
|
||||
openapi?: Partial<OpenAPIV3.Document | OpenAPIV3_1.Document>
|
||||
hiddenTag?: string;
|
||||
hideUntagged?: boolean;
|
||||
|
||||
/** Include HEAD routes in the definitions */
|
||||
exposeHeadRoutes?: boolean;
|
||||
|
||||
/**
|
||||
* Strips matching base path from routes in documentation
|
||||
* @default true
|
||||
*/
|
||||
stripBasePath?: boolean;
|
||||
/**
|
||||
* custom function to transform the route's schema and url
|
||||
*/
|
||||
transform?: SwaggerTransform;
|
||||
|
||||
/**
|
||||
* custom function to transform the openapi or swagger object before it is rendered
|
||||
*/
|
||||
transformObject?: SwaggerTransformObject;
|
||||
|
||||
/** Overrides the Fastify decorator. */
|
||||
decorator?: 'swagger' | (string & Record<never, never>);
|
||||
|
||||
refResolver?: {
|
||||
/** Clone the input schema without changing it. Default to `false`. */
|
||||
clone?: boolean;
|
||||
buildLocalReference: (
|
||||
/** The `json` that is being resolved. */
|
||||
json: JSONObject,
|
||||
/** The `baseUri` object of the schema. */
|
||||
baseUri: {
|
||||
scheme?: string;
|
||||
userinfo?: string;
|
||||
host?: string;
|
||||
port?: number | string;
|
||||
path?: string;
|
||||
query?: string;
|
||||
fragment?: string;
|
||||
reference?: string;
|
||||
error?: string;
|
||||
},
|
||||
/** `fragment` is the `$ref` string when the `$ref` is a relative reference. */
|
||||
fragment: string,
|
||||
/** `i` is a local counter to generate a unique key. */
|
||||
i: number
|
||||
) => string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to convert const definitions to enum definitions.
|
||||
* const support was added in OpenAPI 3.1, but not all tools support it.
|
||||
* This option only affects OpenAPI documents.
|
||||
* @default true
|
||||
*/
|
||||
convertConstToEnum?: boolean;
|
||||
}
|
||||
|
||||
export interface StaticPathSpec {
|
||||
path: string;
|
||||
postProcessor?: (spec: OpenAPI.Document) => OpenAPI.Document;
|
||||
baseDir: string;
|
||||
}
|
||||
|
||||
export interface StaticDocumentSpec {
|
||||
document: OpenAPIV2.Document | OpenAPIV3.Document;
|
||||
}
|
||||
|
||||
export interface FastifyStaticSwaggerOptions extends FastifySwaggerOptions {
|
||||
mode: 'static';
|
||||
specification: StaticPathSpec | StaticDocumentSpec;
|
||||
}
|
||||
|
||||
export function formatParamUrl (paramUrl: string): string
|
||||
|
||||
export const fastifySwagger: FastifySwagger
|
||||
export { fastifySwagger as default }
|
||||
}
|
||||
|
||||
declare function fastifySwagger (...params: Parameters<FastifySwagger>): ReturnType<FastifySwagger>
|
||||
|
||||
export = fastifySwagger
|
||||
34
backend/node_modules/@fastify/swagger/index.js
generated
vendored
Normal file
34
backend/node_modules/@fastify/swagger/index.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
'use strict'
|
||||
|
||||
const fp = require('fastify-plugin')
|
||||
const { formatParamUrl } = require('./lib/util/format-param-url')
|
||||
|
||||
function fastifySwagger (fastify, opts, next) {
|
||||
// by default the mode is dynamic, as plugin initially was developed
|
||||
opts.mode = opts.mode || 'dynamic'
|
||||
|
||||
switch (opts.mode) {
|
||||
case 'static': {
|
||||
const setup = require('./lib/mode/static')
|
||||
setup(fastify, opts, next)
|
||||
break
|
||||
}
|
||||
case 'dynamic': {
|
||||
const setup = require('./lib/mode/dynamic')
|
||||
setup(fastify, opts, next)
|
||||
break
|
||||
}
|
||||
default: {
|
||||
return next(new Error("unsupported mode, should be one of ['static', 'dynamic']"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = fp(fastifySwagger, {
|
||||
fastify: '5.x',
|
||||
name: '@fastify/swagger'
|
||||
})
|
||||
module.exports.fastifySwagger = fastifySwagger
|
||||
module.exports.default = fastifySwagger
|
||||
|
||||
module.exports.formatParamUrl = formatParamUrl
|
||||
11
backend/node_modules/@fastify/swagger/lib/constants.js
generated
vendored
Normal file
11
backend/node_modules/@fastify/swagger/lib/constants.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const xConsume = 'x-consume'
|
||||
const xResponseDescription = 'x-response-description'
|
||||
const xExamples = 'x-examples'
|
||||
|
||||
module.exports = {
|
||||
xConsume,
|
||||
xResponseDescription,
|
||||
xExamples
|
||||
}
|
||||
39
backend/node_modules/@fastify/swagger/lib/mode/dynamic.js
generated
vendored
Normal file
39
backend/node_modules/@fastify/swagger/lib/mode/dynamic.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict'
|
||||
|
||||
const { addHook } = require('../util/add-hook')
|
||||
const { resolveSwaggerFunction } = require('../util/resolve-swagger-function')
|
||||
|
||||
module.exports = function (fastify, opts, done) {
|
||||
opts = Object.assign({}, {
|
||||
exposeRoute: false,
|
||||
hiddenTag: 'X-HIDDEN',
|
||||
hideUntagged: false,
|
||||
stripBasePath: true,
|
||||
openapi: null,
|
||||
swagger: {},
|
||||
transform: null,
|
||||
transformObject: null,
|
||||
decorator: 'swagger',
|
||||
refResolver: {
|
||||
buildLocalReference (json, _baseUri, _fragment, i) {
|
||||
if (!json.title && json.$id) {
|
||||
json.title = json.$id
|
||||
}
|
||||
return `def-${i}`
|
||||
}
|
||||
},
|
||||
convertConstToEnum: true
|
||||
}, opts)
|
||||
|
||||
const { routes, Ref } = addHook(fastify, opts)
|
||||
|
||||
const cache = {
|
||||
object: null,
|
||||
string: null
|
||||
}
|
||||
|
||||
const swagger = resolveSwaggerFunction(opts, cache, routes, Ref)
|
||||
fastify.decorate(opts.decorator, swagger)
|
||||
|
||||
done()
|
||||
}
|
||||
84
backend/node_modules/@fastify/swagger/lib/mode/static.js
generated
vendored
Normal file
84
backend/node_modules/@fastify/swagger/lib/mode/static.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('node:path')
|
||||
const fs = require('node:fs')
|
||||
const yaml = require('yaml')
|
||||
|
||||
module.exports = function (fastify, opts, done) {
|
||||
if (!opts.specification) return done(new Error('specification is missing in the module options'))
|
||||
if (typeof opts.specification !== 'object') return done(new Error('specification is not an object'))
|
||||
|
||||
let swaggerObject = {}
|
||||
|
||||
if (!opts.specification.path && !opts.specification.document) {
|
||||
return done(new Error('both specification.path and specification.document are missing, should be path to the file or swagger document spec'))
|
||||
} else if (opts.specification.path) {
|
||||
if (typeof opts.specification.path !== 'string') return done(new Error('specification.path is not a string'))
|
||||
|
||||
if (!fs.existsSync(path.resolve(opts.specification.path))) return done(new Error(`${opts.specification.path} does not exist`))
|
||||
|
||||
const extName = path.extname(opts.specification.path).toLowerCase()
|
||||
if (['.yaml', '.json'].indexOf(extName) === -1) return done(new Error("specification.path extension name is not supported, should be one from ['.yaml', '.json']"))
|
||||
|
||||
if (opts.specification.postProcessor && typeof opts.specification.postProcessor !== 'function') return done(new Error('specification.postProcessor should be a function'))
|
||||
|
||||
if (opts.specification.baseDir && typeof opts.specification.baseDir !== 'string') return done(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
|
||||
const source = fs.readFileSync(
|
||||
path.resolve(opts.specification.path),
|
||||
'utf8'
|
||||
)
|
||||
switch (extName) {
|
||||
case '.yaml':
|
||||
swaggerObject = yaml.parse(source)
|
||||
break
|
||||
case '.json':
|
||||
swaggerObject = JSON.parse(source)
|
||||
break
|
||||
}
|
||||
|
||||
// apply postProcessor, if one was passed as an argument
|
||||
if (opts.specification.postProcessor) {
|
||||
swaggerObject = opts.specification.postProcessor(swaggerObject)
|
||||
}
|
||||
} else {
|
||||
if (typeof opts.specification.document !== 'object') return done(new Error('specification.document is not an object'))
|
||||
|
||||
swaggerObject = opts.specification.document
|
||||
}
|
||||
|
||||
fastify.decorate(opts.decorator || 'swagger', swagger)
|
||||
|
||||
const cache = {
|
||||
swaggerObject: null,
|
||||
swaggerString: null
|
||||
}
|
||||
|
||||
function swagger (opts) {
|
||||
if (opts?.yaml) {
|
||||
if (cache.swaggerString) return cache.swaggerString
|
||||
} else {
|
||||
if (cache.swaggerObject) return cache.swaggerObject
|
||||
}
|
||||
|
||||
if (opts?.yaml) {
|
||||
const swaggerString = yaml.stringify(swaggerObject, { strict: false })
|
||||
cache.swaggerString = swaggerString
|
||||
return swaggerString
|
||||
}
|
||||
|
||||
cache.swaggerObject = swaggerObject
|
||||
return swaggerObject
|
||||
}
|
||||
|
||||
done()
|
||||
}
|
||||
85
backend/node_modules/@fastify/swagger/lib/spec/openapi/index.js
generated
vendored
Normal file
85
backend/node_modules/@fastify/swagger/lib/spec/openapi/index.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
'use strict'
|
||||
|
||||
const yaml = require('yaml')
|
||||
const { shouldRouteHide } = require('../../util/should-route-hide')
|
||||
const { prepareDefaultOptions, prepareOpenapiObject, prepareOpenapiMethod, prepareOpenapiSchemas, normalizeUrl, resolveServerUrls } = require('./utils')
|
||||
|
||||
module.exports = function (opts, cache, routes, Ref) {
|
||||
let ref
|
||||
|
||||
const defOpts = prepareDefaultOptions(opts)
|
||||
|
||||
return function (opts) {
|
||||
if (opts?.yaml) {
|
||||
if (cache.string) return cache.string
|
||||
} else {
|
||||
if (cache.object) return cache.object
|
||||
}
|
||||
|
||||
// Base Openapi info
|
||||
const openapiObject = prepareOpenapiObject(defOpts)
|
||||
|
||||
ref = Ref()
|
||||
openapiObject.components.schemas = prepareOpenapiSchemas(defOpts, {
|
||||
...openapiObject.components.schemas,
|
||||
...(ref.definitions().definitions)
|
||||
}, ref)
|
||||
|
||||
const serverUrls = resolveServerUrls(defOpts.servers)
|
||||
|
||||
for (const route of routes) {
|
||||
const transformResult = route.config?.swaggerTransform !== undefined
|
||||
? route.config.swaggerTransform
|
||||
? route.config.swaggerTransform({ schema: route.schema, url: route.url, route, openapiObject })
|
||||
: {}
|
||||
: defOpts.transform
|
||||
? defOpts.transform({ schema: route.schema, url: route.url, route, openapiObject })
|
||||
: {}
|
||||
|
||||
const schema = transformResult.schema || route.schema
|
||||
const shouldRouteHideOpts = {
|
||||
hiddenTag: defOpts.hiddenTag,
|
||||
hideUntagged: defOpts.hideUntagged
|
||||
}
|
||||
|
||||
if (shouldRouteHide(schema, shouldRouteHideOpts)) continue
|
||||
|
||||
let url = transformResult.url || route.url
|
||||
url = normalizeUrl(url, serverUrls, defOpts.stripBasePath)
|
||||
|
||||
const openapiRoute = Object.assign({}, openapiObject.paths[url])
|
||||
|
||||
const openapiMethod = prepareOpenapiMethod(defOpts, schema, ref, openapiObject, url)
|
||||
|
||||
if (route.links) {
|
||||
for (const statusCode of Object.keys(route.links)) {
|
||||
if (!openapiMethod.responses[statusCode]) {
|
||||
throw new Error(`missing status code ${statusCode} in route ${route.path}`)
|
||||
}
|
||||
openapiMethod.responses[statusCode].links = route.links[statusCode]
|
||||
}
|
||||
}
|
||||
|
||||
// route.method should be either a String, like 'POST', or an Array of Strings, like ['POST','PUT','PATCH']
|
||||
const methods = typeof route.method === 'string' ? [route.method] : route.method
|
||||
|
||||
for (const method of methods) {
|
||||
openapiRoute[method.toLowerCase()] = openapiMethod
|
||||
}
|
||||
|
||||
openapiObject.paths[url] = openapiRoute
|
||||
}
|
||||
|
||||
const transformObjectResult = defOpts.transformObject
|
||||
? defOpts.transformObject({ openapiObject })
|
||||
: openapiObject
|
||||
|
||||
if (opts?.yaml) {
|
||||
cache.string = yaml.stringify(transformObjectResult, { strict: false })
|
||||
return cache.string
|
||||
}
|
||||
|
||||
cache.object = transformObjectResult
|
||||
return cache.object
|
||||
}
|
||||
}
|
||||
602
backend/node_modules/@fastify/swagger/lib/spec/openapi/utils.js
generated
vendored
Normal file
602
backend/node_modules/@fastify/swagger/lib/spec/openapi/utils.js
generated
vendored
Normal file
@@ -0,0 +1,602 @@
|
||||
'use strict'
|
||||
|
||||
const { readPackageJson } = require('../../util/read-package-json')
|
||||
const { formatParamUrl } = require('../../util/format-param-url')
|
||||
const { resolveLocalRef } = require('../../util/resolve-local-ref')
|
||||
const { resolveSchemaReference } = require('../../util/resolve-schema-reference')
|
||||
const { xResponseDescription, xConsume, xExamples } = require('../../constants')
|
||||
const { rawRequired } = require('../../symbols')
|
||||
const { generateParamsSchema } = require('../../util/generate-params-schema')
|
||||
const { hasParams } = require('../../util/match-params')
|
||||
|
||||
function prepareDefaultOptions (opts) {
|
||||
const openapi = opts.openapi
|
||||
const info = openapi.info || null
|
||||
const servers = openapi.servers || null
|
||||
const components = openapi.components || null
|
||||
const security = openapi.security || null
|
||||
const tags = openapi.tags || null
|
||||
const externalDocs = openapi.externalDocs || null
|
||||
const stripBasePath = opts.stripBasePath
|
||||
const transform = opts.transform
|
||||
const transformObject = opts.transformObject
|
||||
const hiddenTag = opts.hiddenTag
|
||||
const hideUntagged = opts.hideUntagged
|
||||
const extensions = []
|
||||
const convertConstToEnum = opts.convertConstToEnum
|
||||
|
||||
for (const [key, value] of Object.entries(opts.openapi)) {
|
||||
if (key.startsWith('x-')) {
|
||||
extensions.push([key, value])
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...openapi,
|
||||
info,
|
||||
servers,
|
||||
components,
|
||||
security,
|
||||
tags,
|
||||
externalDocs,
|
||||
stripBasePath,
|
||||
transform,
|
||||
transformObject,
|
||||
hiddenTag,
|
||||
extensions,
|
||||
hideUntagged,
|
||||
convertConstToEnum
|
||||
}
|
||||
}
|
||||
|
||||
function prepareOpenapiObject (opts) {
|
||||
const pkg = readPackageJson()
|
||||
const openapiObject = {
|
||||
openapi: '3.0.3',
|
||||
info: {
|
||||
version: pkg.version || '1.0.0',
|
||||
title: pkg.name || ''
|
||||
},
|
||||
components: { schemas: {} },
|
||||
paths: {}
|
||||
}
|
||||
|
||||
if (opts.openapi) openapiObject.openapi = opts.openapi
|
||||
if (opts.info) openapiObject.info = opts.info
|
||||
if (opts.servers) openapiObject.servers = opts.servers
|
||||
if (opts.components) openapiObject.components = Object.assign({}, opts.components, { schemas: Object.assign({}, opts.components.schemas) })
|
||||
if (opts.paths) openapiObject.paths = opts.paths
|
||||
if (opts.webhooks) openapiObject.webhooks = opts.webhooks
|
||||
if (opts.security) openapiObject.security = opts.security
|
||||
if (opts.tags) openapiObject.tags = opts.tags
|
||||
if (opts.externalDocs) openapiObject.externalDocs = opts.externalDocs
|
||||
|
||||
for (const [key, value] of opts.extensions) {
|
||||
// "x-" extension can not be typed
|
||||
openapiObject[key] = value
|
||||
}
|
||||
|
||||
return openapiObject
|
||||
}
|
||||
|
||||
function normalizeUrl (url, serverUrls, stripBasePath) {
|
||||
if (!stripBasePath) return formatParamUrl(url)
|
||||
serverUrls.forEach(function (serverUrl) {
|
||||
const basePath = serverUrl.startsWith('/') ? serverUrl : new URL(serverUrl).pathname
|
||||
if (url.startsWith(basePath) && basePath !== '/') {
|
||||
url = url.replace(basePath, '')
|
||||
}
|
||||
})
|
||||
return formatParamUrl(url)
|
||||
}
|
||||
|
||||
function resolveServerUrls (servers) {
|
||||
const resolvedUrls = []
|
||||
const findVariablesRegex = /\{([^{}]+)\}/gu // As for OpenAPI v3 spec url variables are named in brackets, e.g. {foo}
|
||||
|
||||
servers = Array.isArray(servers) ? servers : []
|
||||
for (const server of servers) {
|
||||
const originalUrl = server.url
|
||||
const variables = server.variables
|
||||
|
||||
let url = originalUrl
|
||||
const matches = url.matchAll(findVariablesRegex)
|
||||
|
||||
for (const [nameInBrackets, name] of matches) {
|
||||
const value = variables?.[name]?.default
|
||||
|
||||
if (value === undefined) {
|
||||
throw new Error(`Server URL ${originalUrl} could not be resolved. Make sure to provide a default value for each URL variable.`)
|
||||
}
|
||||
|
||||
url = url.replace(nameInBrackets, value)
|
||||
}
|
||||
|
||||
resolvedUrls.push(url)
|
||||
}
|
||||
|
||||
return resolvedUrls
|
||||
}
|
||||
|
||||
function convertExamplesArrayToObject (examples) {
|
||||
return examples.reduce((examplesObject, example, index) => {
|
||||
if (typeof example === 'object') {
|
||||
examplesObject['example' + (index + 1)] = { value: example }
|
||||
} else {
|
||||
examplesObject[example] = { value: example }
|
||||
}
|
||||
|
||||
return examplesObject
|
||||
}, {})
|
||||
}
|
||||
|
||||
// For supported keys read:
|
||||
// https://swagger.io/docs/specification/describing-parameters/
|
||||
function plainJsonObjectToOpenapi3 (opts, container, jsonSchema, externalSchemas, securityIgnores = []) {
|
||||
const obj = convertJsonSchemaToOpenapi3(opts, resolveLocalRef(jsonSchema, externalSchemas))
|
||||
let toOpenapiProp
|
||||
switch (container) {
|
||||
case 'cookie':
|
||||
case 'header':
|
||||
case 'query':
|
||||
toOpenapiProp = function (propertyName, jsonSchemaElement) {
|
||||
let result = {
|
||||
in: container,
|
||||
name: propertyName,
|
||||
required: jsonSchemaElement.required
|
||||
}
|
||||
|
||||
const media = schemaToMedia(jsonSchemaElement)
|
||||
|
||||
// complex serialization in query or cookie, eg. JSON
|
||||
// https://swagger.io/docs/specification/describing-parameters/#schema-vs-content
|
||||
if (jsonSchemaElement[xConsume]) {
|
||||
media.schema.required = jsonSchemaElement[rawRequired]
|
||||
|
||||
result.content = {
|
||||
[jsonSchemaElement[xConsume]]: media
|
||||
}
|
||||
|
||||
delete result.content[jsonSchemaElement[xConsume]].schema[xConsume]
|
||||
} else {
|
||||
result = { ...media, ...result }
|
||||
}
|
||||
// description should be optional
|
||||
if (jsonSchemaElement.description) result.description = jsonSchemaElement.description
|
||||
// optionally add serialization format style
|
||||
if (jsonSchema.style) result.style = jsonSchema.style
|
||||
if (jsonSchema.explode != null) result.explode = jsonSchema.explode
|
||||
if (jsonSchema.allowReserved === true && container === 'query') {
|
||||
result.allowReserved = jsonSchema.allowReserved
|
||||
}
|
||||
return result
|
||||
}
|
||||
break
|
||||
case 'path':
|
||||
toOpenapiProp = function (propertyName, jsonSchemaElement) {
|
||||
const media = schemaToMedia(jsonSchemaElement)
|
||||
|
||||
const result = {
|
||||
...media,
|
||||
in: container,
|
||||
name: propertyName,
|
||||
required: true
|
||||
}
|
||||
|
||||
// description should be optional
|
||||
if (jsonSchemaElement.description) result.description = jsonSchemaElement.description
|
||||
return result
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return Object.keys(obj)
|
||||
.filter((propKey) => (!securityIgnores.includes(propKey)))
|
||||
.map((propKey) => {
|
||||
const jsonSchema = toOpenapiProp(propKey, obj[propKey])
|
||||
if (jsonSchema.schema) {
|
||||
// it is needed as required in schema is invalid prop - delete only if needed
|
||||
if (jsonSchema.schema.required !== undefined) delete jsonSchema.schema.required
|
||||
// it is needed as description in schema is invalid prop - delete only if needed
|
||||
if (jsonSchema.schema.description !== undefined) delete jsonSchema.schema.description
|
||||
}
|
||||
return jsonSchema
|
||||
})
|
||||
}
|
||||
|
||||
const schemaTypeToNestedSchemas = {
|
||||
object: (schema) => {
|
||||
return [
|
||||
...Object.values(schema.properties || {}),
|
||||
...Object.values(schema.patternProperties || {}),
|
||||
...Object.values(schema.additionalProperties || {})
|
||||
]
|
||||
},
|
||||
array: (schema) => {
|
||||
return [
|
||||
...(schema.items ? [schema.items] : []),
|
||||
...(schema.contains ? [schema.contains] : [])
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSchemaExamples (schema) {
|
||||
const example = schema[xExamples] ?? schema.examples?.[0]
|
||||
if (typeof example !== 'undefined') {
|
||||
schema.example = example
|
||||
}
|
||||
delete schema[xExamples]
|
||||
delete schema.examples
|
||||
}
|
||||
|
||||
function resolveSchemaExamplesRecursive (schema) {
|
||||
resolveSchemaExamples(schema)
|
||||
const getNestedSchemas = schemaTypeToNestedSchemas[schema.type]
|
||||
const nestedSchemas = getNestedSchemas?.(schema) ?? []
|
||||
for (const nestedSchema of nestedSchemas) {
|
||||
resolveSchemaExamplesRecursive(nestedSchema)
|
||||
}
|
||||
}
|
||||
|
||||
function schemaToMedia (schema) {
|
||||
const media = { schema }
|
||||
|
||||
if (schema.examples?.length === 1) {
|
||||
media.example = schema.examples[0]
|
||||
delete schema.examples
|
||||
} else if (schema.examples?.length > 1) {
|
||||
media.examples = convertExamplesArrayToObject(schema.examples)
|
||||
// examples is invalid property of media object schema
|
||||
delete schema.examples
|
||||
}
|
||||
|
||||
if (schema[xExamples]) {
|
||||
media.examples = schema[xExamples]
|
||||
delete schema[xExamples]
|
||||
}
|
||||
|
||||
return media
|
||||
}
|
||||
|
||||
function schemaToMediaRecursive (schema) {
|
||||
const media = schemaToMedia(schema)
|
||||
resolveSchemaExamplesRecursive(schema)
|
||||
return media
|
||||
}
|
||||
|
||||
function resolveBodyParams (opts, body, schema, consumes, ref) {
|
||||
const resolved = convertJsonSchemaToOpenapi3(opts, ref.resolve(schema))
|
||||
|
||||
if (resolved.content?.[Object.keys(resolved.content)[0]].schema) {
|
||||
for (const contentType in schema.content) {
|
||||
body.content[contentType] = schemaToMediaRecursive(resolved.content[contentType].schema)
|
||||
}
|
||||
} else {
|
||||
if ((Array.isArray(consumes) && consumes.length === 0) || consumes === undefined) {
|
||||
consumes = ['application/json']
|
||||
}
|
||||
|
||||
const media = schemaToMediaRecursive(resolved)
|
||||
consumes.forEach((consume) => {
|
||||
body.content[consume] = media
|
||||
})
|
||||
|
||||
if (resolved?.required?.length) {
|
||||
body.required = true
|
||||
}
|
||||
|
||||
if (resolved?.description) {
|
||||
body.description = resolved.description
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCommonParams (opts, container, parameters, schema, ref, sharedSchemas, securityIgnores) {
|
||||
const schemasPath = '#/components/schemas/'
|
||||
let resolved = convertJsonSchemaToOpenapi3(opts, ref.resolve(schema))
|
||||
|
||||
// if the resolved definition is in global schema
|
||||
if (resolved.$ref?.startsWith(schemasPath)) {
|
||||
const parts = resolved.$ref.split(schemasPath)
|
||||
const pathParts = parts[1].split('/')
|
||||
resolved = pathParts.reduce((resolved, pathPart) => resolved[pathPart], ref.definitions().definitions)
|
||||
}
|
||||
|
||||
const arr = plainJsonObjectToOpenapi3(opts, container, resolved, { ...sharedSchemas, ...ref.definitions().definitions }, securityIgnores)
|
||||
arr.forEach(swaggerSchema => parameters.push(swaggerSchema))
|
||||
}
|
||||
|
||||
function findReferenceDescription (rawSchema, ref) {
|
||||
const resolved = resolveSchemaReference(rawSchema, ref)
|
||||
return resolved?.description
|
||||
}
|
||||
|
||||
// https://swagger.io/docs/specification/describing-responses/
|
||||
function resolveResponse (opts, fastifyResponseJson, produces, ref) {
|
||||
// if the user does not provided an out schema
|
||||
if (!fastifyResponseJson) {
|
||||
return { 200: { description: 'Default Response' } }
|
||||
}
|
||||
|
||||
const responsesContainer = {}
|
||||
|
||||
const statusCodes = Object.keys(fastifyResponseJson)
|
||||
|
||||
statusCodes.forEach(statusCode => {
|
||||
const rawJsonSchema = fastifyResponseJson[statusCode]
|
||||
const resolved = convertJsonSchemaToOpenapi3(opts, ref.resolve(rawJsonSchema))
|
||||
|
||||
/**
|
||||
* 2xx require to be all upper-case
|
||||
* converts statusCode to upper case only when it is not "default"
|
||||
*/
|
||||
if (statusCode !== 'default') {
|
||||
statusCode = statusCode.toUpperCase()
|
||||
}
|
||||
|
||||
const response = {
|
||||
description: resolved[xResponseDescription] ||
|
||||
rawJsonSchema.description ||
|
||||
findReferenceDescription(rawJsonSchema, ref) ||
|
||||
'Default Response'
|
||||
}
|
||||
|
||||
// add headers when there are any.
|
||||
if (rawJsonSchema.headers) {
|
||||
response.headers = {}
|
||||
Object.keys(rawJsonSchema.headers).forEach(function (key) {
|
||||
const header = {
|
||||
schema: { ...rawJsonSchema.headers[key] }
|
||||
}
|
||||
|
||||
if (rawJsonSchema.headers[key].description) {
|
||||
header.description = rawJsonSchema.headers[key].description
|
||||
// remove invalid field
|
||||
delete header.schema.description
|
||||
}
|
||||
|
||||
response.headers[key] = header
|
||||
})
|
||||
// remove invalid field
|
||||
delete resolved.headers
|
||||
}
|
||||
|
||||
// add schema when type is not 'null'
|
||||
if (rawJsonSchema.type !== 'null') {
|
||||
if (resolved.content?.[Object.keys(resolved.content)[0]].schema) {
|
||||
response.content = resolved.content
|
||||
} else {
|
||||
const content = {}
|
||||
|
||||
if ((Array.isArray(produces) && produces.length === 0) || produces === undefined) {
|
||||
produces = ['application/json']
|
||||
}
|
||||
|
||||
delete resolved[xResponseDescription]
|
||||
|
||||
const media = schemaToMediaRecursive(resolved)
|
||||
|
||||
for (const produce of produces) {
|
||||
content[produce] = media
|
||||
}
|
||||
|
||||
response.content = content
|
||||
}
|
||||
}
|
||||
|
||||
responsesContainer[statusCode] = response
|
||||
})
|
||||
|
||||
return responsesContainer
|
||||
}
|
||||
|
||||
function resolveCallbacks (opts, schema, ref) {
|
||||
const callbacksContainer = {}
|
||||
|
||||
// Iterate over each callback event
|
||||
for (const eventName in schema) {
|
||||
if (!schema[eventName]) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create an empty object to house the future iterations
|
||||
callbacksContainer[eventName] = {}
|
||||
const eventSchema = schema[eventName]
|
||||
|
||||
// Iterate over each callbackUrl for the event
|
||||
for (const callbackUrl in eventSchema) {
|
||||
if (!callbackUrl || !eventSchema[callbackUrl]) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create an empty object to house the future iterations
|
||||
callbacksContainer[eventName][callbackUrl] = {}
|
||||
const callbackSchema = eventSchema[callbackUrl]
|
||||
|
||||
// Iterate over each httpMethod for the callbackUrl
|
||||
for (const httpMethodName in callbackSchema) {
|
||||
if (!httpMethodName || !callbackSchema[httpMethodName]) {
|
||||
continue
|
||||
}
|
||||
|
||||
const httpMethodSchema = callbackSchema[httpMethodName]
|
||||
const httpMethodContainer = {}
|
||||
|
||||
if (httpMethodSchema.requestBody) {
|
||||
httpMethodContainer.requestBody = convertJsonSchemaToOpenapi3(
|
||||
opts,
|
||||
ref.resolve(httpMethodSchema.requestBody)
|
||||
)
|
||||
}
|
||||
|
||||
// If a response is not provided, set a 2XX default response
|
||||
httpMethodContainer.responses = httpMethodSchema.responses
|
||||
? convertJsonSchemaToOpenapi3(opts, ref.resolve(httpMethodSchema.responses))
|
||||
: { '2XX': { description: 'Default Response' } }
|
||||
|
||||
// Set the schema at the appropriate location in the response object
|
||||
callbacksContainer[eventName][callbackUrl][httpMethodName] = httpMethodContainer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return callbacksContainer
|
||||
}
|
||||
|
||||
function prepareOpenapiMethod (opts, schema, ref, openapiObject, url) {
|
||||
const openapiMethod = {}
|
||||
const parameters = []
|
||||
|
||||
// Parse out the security prop keys to ignore
|
||||
const securityIgnores = [
|
||||
...(openapiObject?.security || []),
|
||||
...(schema?.security || [])
|
||||
]
|
||||
.reduce((acc, securitySchemeGroup) => {
|
||||
Object.keys(securitySchemeGroup).forEach((securitySchemeLabel) => {
|
||||
const scheme = openapiObject.components.securitySchemes[securitySchemeLabel]
|
||||
const isBearer = scheme.type === 'http' && scheme.scheme === 'bearer'
|
||||
const category = isBearer ? 'header' : scheme.in
|
||||
const name = isBearer ? 'authorization' : scheme.name
|
||||
if (!acc[category]) {
|
||||
acc[category] = []
|
||||
}
|
||||
acc[category].push(name)
|
||||
})
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
// All the data the user can give us, is via the schema object
|
||||
if (schema) {
|
||||
if (schema.operationId) openapiMethod.operationId = schema.operationId
|
||||
if (schema.summary) openapiMethod.summary = schema.summary
|
||||
if (schema.tags) openapiMethod.tags = schema.tags
|
||||
if (schema.description) openapiMethod.description = schema.description
|
||||
if (schema.externalDocs) openapiMethod.externalDocs = schema.externalDocs
|
||||
if (schema.querystring) resolveCommonParams(opts, 'query', parameters, schema.querystring, ref, openapiObject.definitions, securityIgnores.query)
|
||||
if (schema.body) {
|
||||
openapiMethod.requestBody = { content: {} }
|
||||
resolveBodyParams(opts, openapiMethod.requestBody, schema.body, schema.consumes, ref)
|
||||
}
|
||||
if (schema.params) resolveCommonParams(opts, 'path', parameters, schema.params, ref, openapiObject.definitions)
|
||||
if (schema.headers) resolveCommonParams(opts, 'header', parameters, schema.headers, ref, openapiObject.definitions, securityIgnores.header)
|
||||
// TODO: need to documentation, we treat it same as the querystring
|
||||
// fastify do not support cookies schema in first place
|
||||
if (schema.cookies) resolveCommonParams(opts, 'cookie', parameters, schema.cookies, ref, openapiObject.definitions, securityIgnores.cookie)
|
||||
if (parameters.length > 0) openapiMethod.parameters = parameters
|
||||
if (schema.deprecated) openapiMethod.deprecated = schema.deprecated
|
||||
if (schema.security) openapiMethod.security = schema.security
|
||||
if (schema.servers) openapiMethod.servers = schema.servers
|
||||
if (schema.callbacks) openapiMethod.callbacks = resolveCallbacks(opts, schema.callbacks, ref)
|
||||
for (const key of Object.keys(schema)) {
|
||||
if (key.startsWith('x-')) {
|
||||
openapiMethod[key] = schema[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no schema or schema.params, we need to generate them
|
||||
if ((!schema || !schema.params) && hasParams(url)) {
|
||||
const schemaGenerated = generateParamsSchema(url)
|
||||
resolveCommonParams(opts, 'path', parameters, schemaGenerated.params, ref, openapiObject.definitions)
|
||||
openapiMethod.parameters = parameters
|
||||
}
|
||||
|
||||
openapiMethod.responses = resolveResponse(opts, schema ? schema.response : null, schema ? schema.produces : null, ref)
|
||||
|
||||
return openapiMethod
|
||||
}
|
||||
|
||||
function convertJsonSchemaToOpenapi3 (opts, jsonSchema) {
|
||||
if (typeof jsonSchema !== 'object' || jsonSchema === null) {
|
||||
return jsonSchema
|
||||
}
|
||||
|
||||
if (Array.isArray(jsonSchema)) {
|
||||
return jsonSchema.map((s) => convertJsonSchemaToOpenapi3(opts, s))
|
||||
}
|
||||
|
||||
const openapiSchema = { ...jsonSchema }
|
||||
|
||||
if (Object.hasOwn(openapiSchema, '$ref') && Object.keys(openapiSchema).length !== 1) {
|
||||
for (const key of Object.keys(openapiSchema).filter(k => k !== '$ref')) {
|
||||
delete openapiSchema[key]
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for (const key of Object.keys(openapiSchema)) {
|
||||
const value = openapiSchema[key]
|
||||
|
||||
if (key === '$id' || key === '$schema' || key === 'definitions') {
|
||||
// TODO: this breaks references to the definition properties
|
||||
delete openapiSchema[key]
|
||||
continue
|
||||
}
|
||||
|
||||
if (key === '$ref') {
|
||||
openapiSchema.$ref = value.replace('definitions', 'components/schemas')
|
||||
continue
|
||||
}
|
||||
|
||||
if (opts.convertConstToEnum && key === 'const') {
|
||||
// OAS 3.1 supports `const` but it is not supported by `swagger-ui`
|
||||
// https://swagger.io/docs/specification/data-models/keywords/
|
||||
// TODO: check if enum property already exists
|
||||
// TODO: this breaks references to the const property
|
||||
openapiSchema.enum = [openapiSchema.const]
|
||||
delete openapiSchema.const
|
||||
continue
|
||||
}
|
||||
|
||||
if (key === 'patternProperties') {
|
||||
// TODO: check if additionalProperties property already exists
|
||||
// TODO: this breaks references to the additionalProperties properties
|
||||
// TODO: patternProperties actually allowed in the openapi schema, but should
|
||||
// always start with "x-" prefix
|
||||
const propertyJsonSchema = Object.values(openapiSchema.patternProperties)[0]
|
||||
const propertyOpenapiSchema = convertJsonSchemaToOpenapi3(opts, propertyJsonSchema)
|
||||
openapiSchema.additionalProperties = propertyOpenapiSchema
|
||||
delete openapiSchema.patternProperties
|
||||
continue
|
||||
}
|
||||
|
||||
if (key === 'properties') {
|
||||
openapiSchema[key] = {}
|
||||
for (const propertyName of Object.keys(value)) {
|
||||
const propertyJsonSchema = value[propertyName]
|
||||
const propertyOpenapiSchema = convertJsonSchemaToOpenapi3(opts, propertyJsonSchema)
|
||||
openapiSchema[key][propertyName] = propertyOpenapiSchema
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
openapiSchema[key] = convertJsonSchemaToOpenapi3(opts, value)
|
||||
}
|
||||
|
||||
return openapiSchema
|
||||
}
|
||||
|
||||
function prepareOpenapiSchemas (opts, jsonSchemas, ref) {
|
||||
const openapiSchemas = {}
|
||||
|
||||
for (const schemaName of Object.keys(jsonSchemas)) {
|
||||
const jsonSchema = { ...jsonSchemas[schemaName] }
|
||||
|
||||
const resolvedJsonSchema = ref.resolve(jsonSchema, { externalSchemas: [jsonSchemas] })
|
||||
const openapiSchema = convertJsonSchemaToOpenapi3(opts, resolvedJsonSchema)
|
||||
resolveSchemaExamplesRecursive(openapiSchema)
|
||||
|
||||
openapiSchemas[schemaName] = openapiSchema
|
||||
}
|
||||
return openapiSchemas
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
prepareDefaultOptions,
|
||||
prepareOpenapiObject,
|
||||
prepareOpenapiMethod,
|
||||
prepareOpenapiSchemas,
|
||||
resolveServerUrls,
|
||||
normalizeUrl
|
||||
}
|
||||
77
backend/node_modules/@fastify/swagger/lib/spec/swagger/index.js
generated
vendored
Normal file
77
backend/node_modules/@fastify/swagger/lib/spec/swagger/index.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
'use strict'
|
||||
|
||||
const yaml = require('yaml')
|
||||
const { shouldRouteHide } = require('../../util/should-route-hide')
|
||||
const { prepareDefaultOptions, prepareSwaggerObject, prepareSwaggerMethod, normalizeUrl, prepareSwaggerDefinitions } = require('./utils')
|
||||
|
||||
module.exports = function (opts, cache, routes, Ref) {
|
||||
let ref
|
||||
|
||||
const defOpts = prepareDefaultOptions(opts)
|
||||
|
||||
return function (opts) {
|
||||
if (opts?.yaml) {
|
||||
if (cache.string) return cache.string
|
||||
} else {
|
||||
if (cache.object) return cache.object
|
||||
}
|
||||
|
||||
const swaggerObject = prepareSwaggerObject(defOpts)
|
||||
|
||||
ref = Ref()
|
||||
swaggerObject.definitions = prepareSwaggerDefinitions({
|
||||
...swaggerObject.definitions,
|
||||
...(ref.definitions().definitions)
|
||||
}, ref)
|
||||
|
||||
for (const route of routes) {
|
||||
const transformResult = route.config?.swaggerTransform !== undefined
|
||||
? route.config.swaggerTransform
|
||||
? route.config.swaggerTransform({ schema: route.schema, url: route.url, route, swaggerObject })
|
||||
: {}
|
||||
: defOpts.transform
|
||||
? defOpts.transform({ schema: route.schema, url: route.url, route, swaggerObject })
|
||||
: {}
|
||||
|
||||
const schema = transformResult.schema || route.schema
|
||||
const shouldRouteHideOpts = {
|
||||
hiddenTag: defOpts.hiddenTag,
|
||||
hideUntagged: defOpts.hideUntagged
|
||||
}
|
||||
|
||||
if (shouldRouteHide(schema, shouldRouteHideOpts)) continue
|
||||
|
||||
let url = transformResult.url || route.url
|
||||
url = normalizeUrl(url, defOpts.basePath, defOpts.stripBasePath)
|
||||
|
||||
const swaggerRoute = Object.assign({}, swaggerObject.paths[url])
|
||||
|
||||
const swaggerMethod = prepareSwaggerMethod(schema, ref, swaggerObject, url)
|
||||
|
||||
if (route.links) {
|
||||
throw new Error('Swagger (Open API v2) does not support Links. Upgrade to OpenAPI v3 (see @fastify/swagger readme)')
|
||||
}
|
||||
|
||||
// route.method should be either a String, like 'POST', or an Array of Strings, like ['POST','PUT','PATCH']
|
||||
const methods = typeof route.method === 'string' ? [route.method] : route.method
|
||||
|
||||
for (const method of methods) {
|
||||
swaggerRoute[method.toLowerCase()] = swaggerMethod
|
||||
}
|
||||
|
||||
swaggerObject.paths[url] = swaggerRoute
|
||||
}
|
||||
|
||||
const transformObjectResult = defOpts.transformObject
|
||||
? defOpts.transformObject({ swaggerObject })
|
||||
: swaggerObject
|
||||
|
||||
if (opts?.yaml) {
|
||||
cache.string = yaml.stringify(transformObjectResult, { strict: false })
|
||||
return cache.string
|
||||
}
|
||||
|
||||
cache.object = transformObjectResult
|
||||
return cache.object
|
||||
}
|
||||
}
|
||||
354
backend/node_modules/@fastify/swagger/lib/spec/swagger/utils.js
generated
vendored
Normal file
354
backend/node_modules/@fastify/swagger/lib/spec/swagger/utils.js
generated
vendored
Normal file
@@ -0,0 +1,354 @@
|
||||
'use strict'
|
||||
|
||||
const { readPackageJson } = require('../../util/read-package-json')
|
||||
const { formatParamUrl } = require('../../util/format-param-url')
|
||||
const { resolveLocalRef } = require('../../util/resolve-local-ref')
|
||||
const { resolveSchemaReference } = require('../../util/resolve-schema-reference')
|
||||
const { xResponseDescription, xConsume } = require('../../constants')
|
||||
const { generateParamsSchema } = require('../../util/generate-params-schema')
|
||||
const { hasParams } = require('../../util/match-params')
|
||||
|
||||
function prepareDefaultOptions (opts) {
|
||||
const swagger = opts.swagger
|
||||
const info = swagger.info || null
|
||||
const host = swagger.host || null
|
||||
const schemes = swagger.schemes || null
|
||||
const consumes = swagger.consumes || null
|
||||
const produces = swagger.produces || null
|
||||
const definitions = swagger.definitions || null
|
||||
const paths = swagger.paths || null
|
||||
const basePath = swagger.basePath || null
|
||||
const securityDefinitions = swagger.securityDefinitions || null
|
||||
const security = swagger.security || null
|
||||
const tags = swagger.tags || null
|
||||
const externalDocs = swagger.externalDocs || null
|
||||
const stripBasePath = opts.stripBasePath
|
||||
const transform = opts.transform
|
||||
const transformObject = opts.transformObject
|
||||
const hiddenTag = opts.hiddenTag
|
||||
const hideUntagged = opts.hideUntagged
|
||||
const extensions = []
|
||||
|
||||
for (const [key, value] of Object.entries(opts.swagger)) {
|
||||
if (key.startsWith('x-')) {
|
||||
extensions.push([key, value])
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
info,
|
||||
host,
|
||||
schemes,
|
||||
consumes,
|
||||
produces,
|
||||
definitions,
|
||||
paths,
|
||||
basePath,
|
||||
securityDefinitions,
|
||||
security,
|
||||
tags,
|
||||
externalDocs,
|
||||
stripBasePath,
|
||||
transform,
|
||||
transformObject,
|
||||
hiddenTag,
|
||||
extensions,
|
||||
hideUntagged
|
||||
}
|
||||
}
|
||||
|
||||
function prepareSwaggerObject (opts) {
|
||||
const pkg = readPackageJson()
|
||||
const swaggerObject = {
|
||||
swagger: '2.0',
|
||||
info: {
|
||||
version: pkg.version || '1.0.0',
|
||||
title: pkg.name || ''
|
||||
},
|
||||
definitions: {},
|
||||
paths: {}
|
||||
}
|
||||
|
||||
if (opts.info) swaggerObject.info = opts.info
|
||||
if (opts.host) swaggerObject.host = opts.host
|
||||
if (opts.schemes) swaggerObject.schemes = opts.schemes
|
||||
if (opts.basePath) swaggerObject.basePath = opts.basePath
|
||||
if (opts.consumes) swaggerObject.consumes = opts.consumes
|
||||
if (opts.produces) swaggerObject.produces = opts.produces
|
||||
if (opts.definitions) swaggerObject.definitions = opts.definitions
|
||||
if (opts.paths) swaggerObject.paths = opts.paths
|
||||
if (opts.securityDefinitions) swaggerObject.securityDefinitions = opts.securityDefinitions
|
||||
if (opts.security) swaggerObject.security = opts.security
|
||||
if (opts.tags) swaggerObject.tags = opts.tags
|
||||
if (opts.externalDocs) swaggerObject.externalDocs = opts.externalDocs
|
||||
|
||||
for (const [key, value] of opts.extensions) {
|
||||
// "x-" extension can not be typed
|
||||
swaggerObject[key] = value
|
||||
}
|
||||
|
||||
return swaggerObject
|
||||
}
|
||||
|
||||
function normalizeUrl (url, basePath, stripBasePath) {
|
||||
let path
|
||||
if (stripBasePath && url.startsWith(basePath)) {
|
||||
path = url.replace(basePath, '')
|
||||
} else {
|
||||
path = url
|
||||
}
|
||||
if (!path.startsWith('/')) {
|
||||
path = '/' + String(path)
|
||||
}
|
||||
return formatParamUrl(path)
|
||||
}
|
||||
|
||||
// For supported keys read:
|
||||
// https://swagger.io/docs/specification/2-0/describing-parameters/
|
||||
function plainJsonObjectToSwagger2 (container, jsonSchema, externalSchemas, securityIgnores = []) {
|
||||
const obj = resolveLocalRef(jsonSchema, externalSchemas)
|
||||
let toSwaggerProp
|
||||
switch (container) {
|
||||
case 'header':
|
||||
case 'query':
|
||||
toSwaggerProp = function (propertyName, jsonSchemaElement) {
|
||||
// complex serialization is not supported by swagger
|
||||
if (jsonSchemaElement[xConsume]) {
|
||||
throw new Error('Complex serialization is not supported by Swagger. ' +
|
||||
'Remove "' + xConsume + '" for "' + propertyName + '" querystring/header schema or ' +
|
||||
'change specification to OpenAPI')
|
||||
}
|
||||
jsonSchemaElement.in = container
|
||||
jsonSchemaElement.name = propertyName
|
||||
return jsonSchemaElement
|
||||
}
|
||||
break
|
||||
case 'formData':
|
||||
toSwaggerProp = function (propertyName, jsonSchemaElement) {
|
||||
delete jsonSchemaElement.$id
|
||||
jsonSchemaElement.in = container
|
||||
jsonSchemaElement.name = propertyName
|
||||
|
||||
// https://json-schema.org/understanding-json-schema/reference/non_json_data.html#contentencoding
|
||||
if (jsonSchemaElement.contentEncoding === 'binary') {
|
||||
delete jsonSchemaElement.contentEncoding // Must be removed
|
||||
jsonSchemaElement.type = 'file'
|
||||
}
|
||||
|
||||
return jsonSchemaElement
|
||||
}
|
||||
break
|
||||
case 'path':
|
||||
toSwaggerProp = function (propertyName, jsonSchemaElement) {
|
||||
jsonSchemaElement.in = container
|
||||
jsonSchemaElement.name = propertyName
|
||||
jsonSchemaElement.required = true
|
||||
return jsonSchemaElement
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return Object.keys(obj)
|
||||
.filter((propKey) => (!securityIgnores.includes(propKey)))
|
||||
.map((propKey) => {
|
||||
return toSwaggerProp(propKey, obj[propKey])
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
} else if (jsonSchema.const !== undefined) {
|
||||
// Handle const, that is not part of OpenAPI definitions
|
||||
jsonSchema.enum = [jsonSchema.const]
|
||||
delete jsonSchema.const
|
||||
}
|
||||
|
||||
Object.keys(jsonSchema).forEach(function (key) {
|
||||
jsonSchema[key] = replaceUnsupported(jsonSchema[key])
|
||||
})
|
||||
}
|
||||
|
||||
return jsonSchema
|
||||
}
|
||||
|
||||
function isConsumesFormOnly (schema) {
|
||||
const consumes = schema.consumes
|
||||
return (
|
||||
consumes &&
|
||||
consumes.length === 1 &&
|
||||
(consumes[0] === 'application/x-www-form-urlencoded' ||
|
||||
consumes[0] === 'multipart/form-data')
|
||||
)
|
||||
}
|
||||
|
||||
function resolveBodyParams (parameters, schema, ref) {
|
||||
const resolved = ref.resolve(schema)
|
||||
replaceUnsupported(resolved)
|
||||
|
||||
parameters.push({
|
||||
name: 'body',
|
||||
in: 'body',
|
||||
description: resolved?.description,
|
||||
schema: resolved
|
||||
})
|
||||
}
|
||||
|
||||
function resolveCommonParams (container, parameters, schema, ref, sharedSchemas, securityIgnores) {
|
||||
const resolved = ref.resolve(schema)
|
||||
const arr = plainJsonObjectToSwagger2(container, resolved, sharedSchemas, securityIgnores)
|
||||
arr.forEach(swaggerSchema => parameters.push(swaggerSchema))
|
||||
}
|
||||
|
||||
function findReferenceDescription (rawSchema, ref) {
|
||||
const resolved = resolveSchemaReference(rawSchema, ref)
|
||||
return resolved?.description
|
||||
}
|
||||
|
||||
// https://swagger.io/docs/specification/2-0/describing-responses/
|
||||
function resolveResponse (fastifyResponseJson, ref) {
|
||||
// if the user does not provided an out schema
|
||||
if (!fastifyResponseJson) {
|
||||
return { 200: { description: 'Default Response' } }
|
||||
}
|
||||
|
||||
const responsesContainer = {}
|
||||
|
||||
const statusCodes = Object.keys(fastifyResponseJson)
|
||||
|
||||
statusCodes.forEach(statusCode => {
|
||||
const rawJsonSchema = fastifyResponseJson[statusCode]
|
||||
const resolved = ref.resolve(rawJsonSchema)
|
||||
|
||||
delete resolved.$schema
|
||||
|
||||
// 2xx is not supported by swagger
|
||||
const deXXStatusCode = statusCode.toUpperCase().replace('XX', '00')
|
||||
// conflict when we have both 2xx and 200
|
||||
if (statusCode.toUpperCase().includes('XX') && statusCodes.includes(deXXStatusCode)) {
|
||||
return
|
||||
}
|
||||
|
||||
// converts statusCode to upper case only when it is not "default"
|
||||
if (statusCode !== 'default') {
|
||||
statusCode = deXXStatusCode
|
||||
}
|
||||
|
||||
const response = {
|
||||
description: rawJsonSchema[xResponseDescription] ||
|
||||
rawJsonSchema.description ||
|
||||
findReferenceDescription(rawJsonSchema, ref) ||
|
||||
'Default Response'
|
||||
}
|
||||
|
||||
// add headers when there are any.
|
||||
if (rawJsonSchema.headers) {
|
||||
response.headers = rawJsonSchema.headers
|
||||
// remove invalid field
|
||||
delete resolved.headers
|
||||
}
|
||||
|
||||
// add schema when type is not 'null'
|
||||
if (rawJsonSchema.type !== 'null') {
|
||||
const schema = { ...resolved }
|
||||
replaceUnsupported(schema)
|
||||
delete schema[xResponseDescription]
|
||||
response.schema = schema
|
||||
}
|
||||
|
||||
responsesContainer[statusCode] = response
|
||||
})
|
||||
|
||||
return responsesContainer
|
||||
}
|
||||
|
||||
function prepareSwaggerMethod (schema, ref, swaggerObject, url) {
|
||||
const swaggerMethod = {}
|
||||
const parameters = []
|
||||
|
||||
// Parse out the security prop keys to ignore
|
||||
const securityIgnores = [
|
||||
...(swaggerObject?.security || []),
|
||||
...(schema?.security || [])
|
||||
]
|
||||
.reduce((acc, securitySchemeGroup) => {
|
||||
Object.keys(securitySchemeGroup).forEach((securitySchemeLabel) => {
|
||||
const { name, in: category } = swaggerObject.securityDefinitions[securitySchemeLabel]
|
||||
if (!acc[category]) {
|
||||
acc[category] = []
|
||||
}
|
||||
acc[category].push(name)
|
||||
})
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
// All the data the user can give us, is via the schema object
|
||||
if (schema) {
|
||||
if (schema.operationId) swaggerMethod.operationId = schema.operationId
|
||||
if (schema.summary) swaggerMethod.summary = schema.summary
|
||||
if (schema.description) swaggerMethod.description = schema.description
|
||||
if (schema.externalDocs) swaggerMethod.externalDocs = schema.externalDocs
|
||||
if (schema.tags) swaggerMethod.tags = schema.tags
|
||||
if (schema.produces) swaggerMethod.produces = schema.produces
|
||||
if (schema.consumes) swaggerMethod.consumes = schema.consumes
|
||||
if (schema.querystring) resolveCommonParams('query', parameters, schema.querystring, ref, swaggerObject.definitions, securityIgnores.query)
|
||||
if (schema.body) {
|
||||
const isConsumesAllFormOnly = isConsumesFormOnly(schema) || isConsumesFormOnly(swaggerObject)
|
||||
isConsumesAllFormOnly
|
||||
? resolveCommonParams('formData', parameters, schema.body, ref, swaggerObject.definitions)
|
||||
: resolveBodyParams(parameters, schema.body, ref)
|
||||
}
|
||||
if (schema.params) resolveCommonParams('path', parameters, schema.params, ref, swaggerObject.definitions)
|
||||
if (schema.headers) resolveCommonParams('header', parameters, schema.headers, ref, swaggerObject.definitions, securityIgnores.header)
|
||||
if (parameters.length > 0) swaggerMethod.parameters = parameters
|
||||
if (schema.deprecated) swaggerMethod.deprecated = schema.deprecated
|
||||
if (schema.security) swaggerMethod.security = schema.security
|
||||
for (const key of Object.keys(schema)) {
|
||||
if (key.startsWith('x-')) {
|
||||
swaggerMethod[key] = schema[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no schema or schema.params, we need to generate them
|
||||
if ((!schema || !schema.params) && hasParams(url)) {
|
||||
const schemaGenerated = generateParamsSchema(url)
|
||||
resolveCommonParams('path', parameters, schemaGenerated.params, ref, swaggerObject.definitions)
|
||||
swaggerMethod.parameters = parameters
|
||||
}
|
||||
|
||||
swaggerMethod.responses = resolveResponse(schema ? schema.response : null, ref)
|
||||
|
||||
return swaggerMethod
|
||||
}
|
||||
|
||||
function prepareSwaggerDefinitions (definitions, ref) {
|
||||
return Object.entries(definitions)
|
||||
.reduce((res, [name, definition]) => {
|
||||
const _ = { ...definition }
|
||||
const resolved = ref.resolve(_, { externalSchemas: [definitions] })
|
||||
|
||||
// Swagger doesn't accept $id on /definitions schemas.
|
||||
// The $ids are needed by Ref() to check the URI so we need
|
||||
// to remove them at the end of the process
|
||||
delete resolved.$id
|
||||
delete resolved.definitions
|
||||
|
||||
res[name] = resolved
|
||||
return res
|
||||
}, {})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
prepareDefaultOptions,
|
||||
prepareSwaggerObject,
|
||||
prepareSwaggerMethod,
|
||||
normalizeUrl,
|
||||
prepareSwaggerDefinitions
|
||||
}
|
||||
7
backend/node_modules/@fastify/swagger/lib/symbols.js
generated
vendored
Normal file
7
backend/node_modules/@fastify/swagger/lib/symbols.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const rawRequired = Symbol('@fastify/swagger.rawRequired')
|
||||
|
||||
module.exports = {
|
||||
rawRequired
|
||||
}
|
||||
82
backend/node_modules/@fastify/swagger/lib/util/add-hook.js
generated
vendored
Normal file
82
backend/node_modules/@fastify/swagger/lib/util/add-hook.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
'use strict'
|
||||
|
||||
const Ref = require('json-schema-resolver')
|
||||
const cloner = require('rfdc')({ proto: true, circles: false })
|
||||
|
||||
function addHook (fastify, pluginOptions) {
|
||||
const routes = []
|
||||
const sharedSchemasMap = new Map()
|
||||
let hookRun = false
|
||||
|
||||
fastify.addHook('onRoute', (routeOptions) => {
|
||||
const routeConfig = routeOptions.config || {}
|
||||
const swaggerConfig = routeConfig.swagger || {}
|
||||
if (routeOptions.method === 'HEAD' && pluginOptions.exposeHeadRoutes !== true && swaggerConfig.exposeHeadRoute !== true) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
routeOptions.method === 'HEAD' &&
|
||||
routeOptions.schema !== undefined &&
|
||||
routeOptions.schema.operationId !== undefined
|
||||
) {
|
||||
routes.push(
|
||||
// If two routes with operationId are added to the swagger
|
||||
// object, it is no longer valid.
|
||||
// therefore we suffix the operationId with `-head`.
|
||||
Object.assign({}, routeOptions, {
|
||||
schema: Object.assign({}, routeOptions.schema, {
|
||||
operationId: `${routeOptions.schema.operationId}-head`
|
||||
})
|
||||
})
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
routes.push(routeOptions)
|
||||
})
|
||||
|
||||
fastify.addHook('onRegister', async (instance) => {
|
||||
// we need to wait the ready event to get all the .getSchemas()
|
||||
// otherwise it will be empty
|
||||
// TODO: better handle for schemaId
|
||||
// when schemaId is the same in difference instance
|
||||
// the latter will lost
|
||||
instance.addHook('onReady', (done) => {
|
||||
const allSchemas = instance.getSchemas()
|
||||
for (const schemaId of Object.keys(allSchemas)) {
|
||||
sharedSchemasMap.set(schemaId, allSchemas[schemaId])
|
||||
}
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
fastify.addHook('onReady', (done) => {
|
||||
hookRun = true
|
||||
const allSchemas = fastify.getSchemas()
|
||||
for (const schemaId of Object.keys(allSchemas)) {
|
||||
// it is the top-level, we do not expect to have duplicate id
|
||||
sharedSchemasMap.set(schemaId, allSchemas[schemaId])
|
||||
}
|
||||
done()
|
||||
})
|
||||
|
||||
return {
|
||||
routes,
|
||||
Ref () {
|
||||
if (hookRun === false) {
|
||||
throw new Error('.swagger() must be called after .ready()')
|
||||
}
|
||||
const externalSchemas = cloner(Array.from(sharedSchemasMap.values()))
|
||||
return Ref(Object.assign(
|
||||
{ applicationUri: 'todo.com' },
|
||||
pluginOptions.refResolver,
|
||||
{ clone: true, externalSchemas })
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
addHook
|
||||
}
|
||||
86
backend/node_modules/@fastify/swagger/lib/util/format-param-url.js
generated
vendored
Normal file
86
backend/node_modules/@fastify/swagger/lib/util/format-param-url.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
'use strict'
|
||||
|
||||
// The swagger standard does not accept the url param with ':'
|
||||
// so '/user/:id' is not valid.
|
||||
// This function converts the url in a swagger compliant url string
|
||||
// => '/user/{id}'
|
||||
// custom verbs at the end of a url are okay => /user::watch but should be rendered as /user:watch in swagger
|
||||
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 === '*') {
|
||||
// * -> {*}
|
||||
// should be exist once only
|
||||
path += '{*}'
|
||||
} else {
|
||||
path += char
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// clean up
|
||||
if (state === 'colon' && param !== '') {
|
||||
path += '{' + param + '}'
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatParamUrl
|
||||
}
|
||||
35
backend/node_modules/@fastify/swagger/lib/util/generate-params-schema.js
generated
vendored
Normal file
35
backend/node_modules/@fastify/swagger/lib/util/generate-params-schema.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
'use strict'
|
||||
|
||||
const { matchParams } = require('./match-params')
|
||||
|
||||
const namePattern = /\{([^{}]+)\}/u
|
||||
|
||||
function paramName (param) {
|
||||
return param.replace(namePattern, (_, captured) => captured)
|
||||
}
|
||||
|
||||
// Generates default parameters schema from the given URL. (ex: /example/{userId})
|
||||
function generateParamsSchema (url) {
|
||||
const params = matchParams(url)
|
||||
const schema = {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
|
||||
schema.params.properties = params.reduce((acc, param) => {
|
||||
const name = paramName(param)
|
||||
acc[name] = {
|
||||
type: 'string'
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateParamsSchema,
|
||||
paramName
|
||||
}
|
||||
18
backend/node_modules/@fastify/swagger/lib/util/match-params.js
generated
vendored
Normal file
18
backend/node_modules/@fastify/swagger/lib/util/match-params.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
const paramPattern = /\{[^{}]+\}/gu
|
||||
|
||||
function hasParams (url) {
|
||||
if (!url) return false
|
||||
return paramPattern.test(url)
|
||||
}
|
||||
|
||||
function matchParams (url) {
|
||||
if (!url) return []
|
||||
return url.match(paramPattern) || []
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasParams,
|
||||
matchParams
|
||||
}
|
||||
16
backend/node_modules/@fastify/swagger/lib/util/read-package-json.js
generated
vendored
Normal file
16
backend/node_modules/@fastify/swagger/lib/util/read-package-json.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict'
|
||||
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
|
||||
function readPackageJson () {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'package.json')))
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readPackageJson
|
||||
}
|
||||
42
backend/node_modules/@fastify/swagger/lib/util/resolve-local-ref.js
generated
vendored
Normal file
42
backend/node_modules/@fastify/swagger/lib/util/resolve-local-ref.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
'use strict'
|
||||
|
||||
const { rawRequired } = require('../symbols')
|
||||
const { xConsume } = require('../constants')
|
||||
|
||||
function resolveLocalRef (jsonSchema, externalSchemas) {
|
||||
if (jsonSchema.type !== undefined && jsonSchema.properties !== undefined) {
|
||||
// for the shorthand querystring/params/headers declaration
|
||||
const propertiesMap = Object.keys(jsonSchema.properties).reduce((acc, headers) => {
|
||||
const rewriteProps = {}
|
||||
rewriteProps.required = (Array.isArray(jsonSchema.required) && jsonSchema.required.indexOf(headers) >= 0) || false
|
||||
// save raw required for next restore in the content/<media-type>
|
||||
if (jsonSchema.properties[headers][xConsume]) {
|
||||
rewriteProps[rawRequired] = jsonSchema.properties[headers].required
|
||||
}
|
||||
const newProps = Object.assign({}, jsonSchema.properties[headers], rewriteProps)
|
||||
|
||||
return Object.assign({}, acc, { [headers]: newProps })
|
||||
}, {})
|
||||
|
||||
return propertiesMap
|
||||
}
|
||||
|
||||
// for oneOf, anyOf, allOf support in querystring/params/headers
|
||||
if (jsonSchema.oneOf || jsonSchema.anyOf || jsonSchema.allOf) {
|
||||
const schemas = jsonSchema.oneOf || jsonSchema.anyOf || jsonSchema.allOf
|
||||
return schemas.reduce((acc, schema) => Object.assign(acc, resolveLocalRef(schema, externalSchemas)), {})
|
||||
}
|
||||
|
||||
// $ref is in the format: #/definitions/<resolved definition>/<optional fragment>
|
||||
if (jsonSchema.$ref) {
|
||||
const localRef = jsonSchema.$ref.split('/', 3)[2]
|
||||
if (externalSchemas[localRef]) return resolveLocalRef(externalSchemas[localRef], externalSchemas)
|
||||
// $ref is in the format: #/components/schemas/<resolved definition>
|
||||
return resolveLocalRef(externalSchemas[jsonSchema.$ref.split('/', 4)[3]], externalSchemas)
|
||||
}
|
||||
return jsonSchema
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolveLocalRef
|
||||
}
|
||||
18
backend/node_modules/@fastify/swagger/lib/util/resolve-schema-reference.js
generated
vendored
Normal file
18
backend/node_modules/@fastify/swagger/lib/util/resolve-schema-reference.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
function resolveSchemaReference (rawSchema, ref) {
|
||||
const resolvedReference = ref.resolve(rawSchema, { externalSchemas: [ref.definitions().definitions] })
|
||||
|
||||
// Ref has format `#/definitions/id`
|
||||
const schemaId = resolvedReference?.$ref?.split('/', 3)[2]
|
||||
|
||||
if (schemaId === undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return resolvedReference.definitions?.[schemaId]
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolveSchemaReference
|
||||
}
|
||||
13
backend/node_modules/@fastify/swagger/lib/util/resolve-swagger-function.js
generated
vendored
Normal file
13
backend/node_modules/@fastify/swagger/lib/util/resolve-swagger-function.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
function resolveSwaggerFunction (opts, cache, routes, Ref) {
|
||||
if (opts.openapi === undefined || opts.openapi === null) {
|
||||
return require('../spec/swagger')(opts, cache, routes, Ref)
|
||||
} else {
|
||||
return require('../spec/openapi')(opts, cache, routes, Ref)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolveSwaggerFunction
|
||||
}
|
||||
25
backend/node_modules/@fastify/swagger/lib/util/should-route-hide.js
generated
vendored
Normal file
25
backend/node_modules/@fastify/swagger/lib/util/should-route-hide.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict'
|
||||
|
||||
function shouldRouteHide (schema, opts) {
|
||||
const { hiddenTag, hideUntagged } = opts
|
||||
|
||||
if (schema?.hide) {
|
||||
return true
|
||||
}
|
||||
|
||||
const tags = schema?.tags || []
|
||||
|
||||
if (tags.length === 0 && hideUntagged) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (tags.includes(hiddenTag)) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldRouteHide
|
||||
}
|
||||
2
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.gitattributes
generated
vendored
Normal file
2
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.gitattributes
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# Set default behavior to automatically convert line endings
|
||||
* text=auto eol=lf
|
||||
13
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.github/dependabot.yml
generated
vendored
Normal file
13
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.github/dependabot.yml
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
open-pull-requests-limit: 10
|
||||
21
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.github/stale.yml
generated
vendored
Normal file
21
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.github/stale.yml
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 15
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- "discussion"
|
||||
- "feature request"
|
||||
- "bug"
|
||||
- "help wanted"
|
||||
- "plugin suggestion"
|
||||
- "good first issue"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
28
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.github/workflows/ci.yml
generated
vendored
Normal file
28
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/.github/workflows/ci.yml
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- next
|
||||
- 'v*'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
|
||||
with:
|
||||
license-check: true
|
||||
lint: true
|
||||
23
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/LICENSE
generated
vendored
Normal file
23
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-present The Fastify team
|
||||
|
||||
The Fastify team members are listed at https://github.com/fastify/fastify#team.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
188
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/README.md
generated
vendored
Normal file
188
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/README.md
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
# fastify-plugin
|
||||
|
||||
[](https://github.com/fastify/fastify-plugin/actions/workflows/ci.yml)
|
||||
[](https://www.npmjs.com/package/fastify-plugin)
|
||||
[](https://github.com/neostandard/neostandard)
|
||||
|
||||
`fastify-plugin` is a plugin helper for [Fastify](https://github.com/fastify/fastify).
|
||||
|
||||
When you build plugins for Fastify and you want them to be accessible in the same context where you require them, you have two ways:
|
||||
1. Use the `skip-override` hidden property
|
||||
2. Use this module
|
||||
|
||||
__Note: the v4.x series of this module covers Fastify v4__
|
||||
__Note: the v2.x & v3.x series of this module covers Fastify v3. For Fastify v2 support, refer to the v1.x series.__
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm i fastify-plugin
|
||||
```
|
||||
|
||||
## Usage
|
||||
`fastify-plugin` can do three things for you:
|
||||
- Add the `skip-override` hidden property
|
||||
- Check the bare-minimum version of Fastify
|
||||
- Pass some custom metadata of the plugin to Fastify
|
||||
|
||||
Example using a callback:
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
module.exports = fp(function (fastify, opts, done) {
|
||||
// your plugin code
|
||||
done()
|
||||
})
|
||||
```
|
||||
|
||||
Example using an [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function:
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
// A callback function param is not required for async functions
|
||||
module.exports = fp(async function (fastify, opts) {
|
||||
// Wait for an async function to fulfill promise before proceeding
|
||||
await exampleAsyncFunction()
|
||||
})
|
||||
```
|
||||
|
||||
## Metadata
|
||||
In addition, if you use this module when creating new plugins, you can declare the dependencies, the name, and the expected Fastify version that your plugin needs.
|
||||
|
||||
#### Fastify version
|
||||
If you need to set a bare-minimum version of Fastify for your plugin, just add the [semver](https://semver.org/) range that you need:
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
module.exports = fp(function (fastify, opts, done) {
|
||||
// your plugin code
|
||||
done()
|
||||
}, { fastify: '5.x' })
|
||||
```
|
||||
|
||||
If you need to check the Fastify version only, you can pass just the version string.
|
||||
|
||||
You can check [here](https://github.com/npm/node-semver#ranges) how to define a `semver` range.
|
||||
|
||||
#### Name
|
||||
Fastify uses this option to validate the dependency graph, allowing it to ensure that no name collisions occur and making it possible to perform [dependency checks](https://github.com/fastify/fastify-plugin#dependencies).
|
||||
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
function plugin (fastify, opts, done) {
|
||||
// your plugin code
|
||||
done()
|
||||
}
|
||||
|
||||
module.exports = fp(plugin, {
|
||||
fastify: '5.x',
|
||||
name: 'your-plugin-name'
|
||||
})
|
||||
```
|
||||
|
||||
#### Dependencies
|
||||
You can also check if the `plugins` and `decorators` that your plugin intend to use are present in the dependency graph.
|
||||
> *Note:* This is the point where registering `name` of the plugins become important, because you can reference `plugin` dependencies by their [name](https://github.com/fastify/fastify-plugin#name).
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
function plugin (fastify, opts, done) {
|
||||
// your plugin code
|
||||
done()
|
||||
}
|
||||
|
||||
module.exports = fp(plugin, {
|
||||
fastify: '5.x',
|
||||
decorators: {
|
||||
fastify: ['plugin1', 'plugin2'],
|
||||
reply: ['compress']
|
||||
},
|
||||
dependencies: ['plugin1-name', 'plugin2-name']
|
||||
})
|
||||
```
|
||||
|
||||
#### Encapsulate
|
||||
|
||||
By default, `fastify-plugin` breaks the [encapsulation](https://github.com/fastify/fastify/blob/HEAD/docs/Reference/Encapsulation.md) but you can optionally keep the plugin encapsulated.
|
||||
This allows you to set the plugin's name and validate its dependencies without making the plugin accessible.
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
function plugin (fastify, opts, done) {
|
||||
// the decorator is not accessible outside this plugin
|
||||
fastify.decorate('util', function() {})
|
||||
done()
|
||||
}
|
||||
|
||||
module.exports = fp(plugin, {
|
||||
name: 'my-encapsulated-plugin',
|
||||
fastify: '5.x',
|
||||
decorators: {
|
||||
fastify: ['plugin1', 'plugin2'],
|
||||
reply: ['compress']
|
||||
},
|
||||
dependencies: ['plugin1-name', 'plugin2-name'],
|
||||
encapsulate: true
|
||||
})
|
||||
```
|
||||
|
||||
#### Bundlers and Typescript
|
||||
`fastify-plugin` adds a `.default` and `[name]` property to the passed in function.
|
||||
The type definition would have to be updated to leverage this.
|
||||
|
||||
## Known Issue: TypeScript Contextual Inference
|
||||
|
||||
[Documentation Reference](https://www.typescriptlang.org/docs/handbook/functions.html#inferring-the-types)
|
||||
|
||||
It is common for developers to inline their plugin with fastify-plugin such as:
|
||||
|
||||
```js
|
||||
fp((fastify, opts, done) => { done() })
|
||||
fp(async (fastify, opts) => { return })
|
||||
```
|
||||
|
||||
TypeScript can sometimes infer the types of the arguments for these functions. Plugins in Fastify are recommended to be typed using either `FastifyPluginCallback` or `FastifyPluginAsync`. These two definitions only differ in two ways:
|
||||
|
||||
1. The third argument `done` (the callback part)
|
||||
2. The return type `FastifyPluginCallback` or `FastifyPluginAsync`
|
||||
|
||||
At this time, TypeScript inference is not smart enough to differentiate by definition argument length alone.
|
||||
|
||||
Thus, if you are a TypeScript developer please use on the following patterns instead:
|
||||
|
||||
```ts
|
||||
// Callback
|
||||
|
||||
// Assign type directly
|
||||
const pluginCallback: FastifyPluginCallback = (fastify, options, done) => { }
|
||||
fp(pluginCallback)
|
||||
|
||||
// or define your own function declaration that satisfies the existing definitions
|
||||
const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, done: (error?: FastifyError) => void): void => { }
|
||||
fp(pluginCallbackWithTypes)
|
||||
// or inline
|
||||
fp((fastify: FastifyInstance, options: FastifyPluginOptions, done: (error?: FastifyError) => void): void => { })
|
||||
|
||||
// Async
|
||||
|
||||
// Assign type directly
|
||||
const pluginAsync: FastifyPluginAsync = async (fastify, options) => { }
|
||||
fp(pluginAsync)
|
||||
|
||||
// or define your own function declaration that satisfies the existing definitions
|
||||
const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { }
|
||||
fp(pluginAsyncWithTypes)
|
||||
// or inline
|
||||
fp(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise<void> => { })
|
||||
```
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
This project is kindly sponsored by:
|
||||
- [nearForm](https://nearform.com)
|
||||
- [LetzDoIt](https://www.letzdoitapp.com/)
|
||||
|
||||
## License
|
||||
|
||||
Licensed under [MIT](./LICENSE).
|
||||
6
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/eslint.config.js
generated
vendored
Normal file
6
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/eslint.config.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = require('neostandard')({
|
||||
ignores: require('neostandard').resolveIgnoresFromGitignore(),
|
||||
ts: true
|
||||
})
|
||||
25
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/lib/getPluginName.js
generated
vendored
Normal file
25
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/lib/getPluginName.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict'
|
||||
|
||||
const fpStackTracePattern = /at\s(?:.*\.)?plugin\s.*\n\s*(.*)/
|
||||
const fileNamePattern = /(\w*(\.\w*)*)\..*/
|
||||
|
||||
module.exports = function getPluginName (fn) {
|
||||
if (fn.name.length > 0) return fn.name
|
||||
|
||||
const stackTraceLimit = Error.stackTraceLimit
|
||||
Error.stackTraceLimit = 10
|
||||
try {
|
||||
throw new Error('anonymous function')
|
||||
} catch (e) {
|
||||
Error.stackTraceLimit = stackTraceLimit
|
||||
return extractPluginName(e.stack)
|
||||
}
|
||||
}
|
||||
|
||||
function extractPluginName (stack) {
|
||||
const m = stack.match(fpStackTracePattern)
|
||||
|
||||
// get last section of path and match for filename
|
||||
return m ? m[1].split(/[/\\]/).slice(-1)[0].match(fileNamePattern)[1] : 'anonymous'
|
||||
}
|
||||
module.exports.extractPluginName = extractPluginName
|
||||
10
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/lib/toCamelCase.js
generated
vendored
Normal file
10
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/lib/toCamelCase.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = function toCamelCase (name) {
|
||||
if (name[0] === '@') {
|
||||
name = name.slice(1).replace('/', '-')
|
||||
}
|
||||
return name.replace(/-(.)/g, function (match, g1) {
|
||||
return g1.toUpperCase()
|
||||
})
|
||||
}
|
||||
70
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/package.json
generated
vendored
Normal file
70
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/package.json
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "fastify-plugin",
|
||||
"version": "5.1.0",
|
||||
"description": "Plugin helper for Fastify",
|
||||
"main": "plugin.js",
|
||||
"type": "commonjs",
|
||||
"types": "types/plugin.d.ts",
|
||||
"scripts": {
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"test": "npm run test:unit && npm run test:typescript",
|
||||
"test:unit": "c8 --100 node --test",
|
||||
"test:coverage": "c8 node --test && c8 report --reporter=html",
|
||||
"test:typescript": "tsd"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/fastify/fastify-plugin.git"
|
||||
},
|
||||
"keywords": [
|
||||
"plugin",
|
||||
"helper",
|
||||
"fastify"
|
||||
],
|
||||
"author": "Tomas Della Vedova - @delvedor (http://delved.org)",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Matteo Collina",
|
||||
"email": "hello@matteocollina.com"
|
||||
},
|
||||
{
|
||||
"name": "Manuel Spigolon",
|
||||
"email": "behemoth89@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Aras Abbasi",
|
||||
"email": "aras.abbasi@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Frazer Smith",
|
||||
"email": "frazer.dev@icloud.com",
|
||||
"url": "https://github.com/fdawgs"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/fastify/fastify-plugin/issues"
|
||||
},
|
||||
"homepage": "https://github.com/fastify/fastify-plugin#readme",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
"@fastify/type-provider-typebox": "^5.1.0",
|
||||
"@types/node": "^24.0.8",
|
||||
"c8": "^10.1.2",
|
||||
"eslint": "^9.17.0",
|
||||
"fastify": "^5.0.0",
|
||||
"neostandard": "^0.12.0",
|
||||
"proxyquire": "^2.1.3",
|
||||
"tsd": "^0.33.0"
|
||||
}
|
||||
}
|
||||
67
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/plugin.js
generated
vendored
Normal file
67
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/plugin.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
'use strict'
|
||||
|
||||
const getPluginName = require('./lib/getPluginName')
|
||||
const toCamelCase = require('./lib/toCamelCase')
|
||||
|
||||
let count = 0
|
||||
|
||||
function plugin (fn, options = {}) {
|
||||
let autoName = false
|
||||
|
||||
if (fn.default !== undefined) {
|
||||
// Support for 'export default' behaviour in transpiled ECMAScript module
|
||||
fn = fn.default
|
||||
}
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError(
|
||||
`fastify-plugin expects a function, instead got a '${typeof fn}'`
|
||||
)
|
||||
}
|
||||
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
fastify: options
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
typeof options !== 'object' ||
|
||||
Array.isArray(options) ||
|
||||
options === null
|
||||
) {
|
||||
throw new TypeError('The options object should be an object')
|
||||
}
|
||||
|
||||
if (options.fastify !== undefined && typeof options.fastify !== 'string') {
|
||||
throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`)
|
||||
}
|
||||
|
||||
if (!options.name) {
|
||||
autoName = true
|
||||
options.name = getPluginName(fn) + '-auto-' + count++
|
||||
}
|
||||
|
||||
fn[Symbol.for('skip-override')] = options.encapsulate !== true
|
||||
fn[Symbol.for('fastify.display-name')] = options.name
|
||||
fn[Symbol.for('plugin-meta')] = options
|
||||
|
||||
// Faux modules support
|
||||
if (!fn.default) {
|
||||
fn.default = fn
|
||||
}
|
||||
|
||||
// TypeScript support for named imports
|
||||
// See https://github.com/fastify/fastify/issues/2404 for more details
|
||||
// The type definitions would have to be update to match this.
|
||||
const camelCase = toCamelCase(options.name)
|
||||
if (!autoName && !fn[camelCase]) {
|
||||
fn[camelCase] = fn
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
module.exports = plugin
|
||||
module.exports.default = plugin
|
||||
module.exports.fastifyPlugin = plugin
|
||||
110
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/bundlers.test.js
generated
vendored
Normal file
110
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/bundlers.test.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const fp = require('../plugin')
|
||||
|
||||
test('webpack removes require.main.filename', t => {
|
||||
const filename = require.main.filename
|
||||
const info = console.info
|
||||
t.after(() => {
|
||||
require.main.filename = filename
|
||||
console.info = info
|
||||
})
|
||||
|
||||
require.main.filename = null
|
||||
|
||||
console.info = function (msg) {
|
||||
t.assert.fail('logged: ' + msg)
|
||||
}
|
||||
|
||||
fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
fastify: '^5.0.0'
|
||||
})
|
||||
})
|
||||
|
||||
test('support faux modules', (t) => {
|
||||
const plugin = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.default, plugin)
|
||||
})
|
||||
|
||||
test('support faux modules does not override existing default field in babel module', (t) => {
|
||||
const module = {
|
||||
default: (_fastify, _opts, next) => next()
|
||||
}
|
||||
|
||||
module.default.default = 'Existing default field'
|
||||
|
||||
const plugin = fp(module)
|
||||
|
||||
t.assert.strictEqual(plugin.default, 'Existing default field')
|
||||
})
|
||||
|
||||
test('support ts named imports', (t) => {
|
||||
const plugin = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
name: 'hello'
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.hello, plugin)
|
||||
})
|
||||
|
||||
test('from kebab-case to camelCase', (t) => {
|
||||
const plugin = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
name: 'hello-world'
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.helloWorld, plugin)
|
||||
})
|
||||
|
||||
test('from @-prefixed named imports', (t) => {
|
||||
const plugin = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
name: '@hello/world'
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.helloWorld, plugin)
|
||||
})
|
||||
|
||||
test('from @-prefixed named kebab-case to camelCase', (t) => {
|
||||
const plugin = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
name: '@hello/my-world'
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.helloMyWorld, plugin)
|
||||
})
|
||||
|
||||
test('from kebab-case to camelCase multiple words', (t) => {
|
||||
const plugin = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
name: 'hello-long-world'
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.helloLongWorld, plugin)
|
||||
})
|
||||
|
||||
test('from kebab-case to camelCase multiple words does not override', (t) => {
|
||||
const fn = (_fastify, _opts, next) => {
|
||||
next()
|
||||
}
|
||||
|
||||
const foobar = {}
|
||||
fn.helloLongWorld = foobar
|
||||
|
||||
const plugin = fp(fn, {
|
||||
name: 'hello-long-world'
|
||||
})
|
||||
|
||||
t.assert.strictEqual(plugin.helloLongWorld, foobar)
|
||||
})
|
||||
67
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/checkVersion.test.js
generated
vendored
Normal file
67
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/checkVersion.test.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const fp = require('../plugin')
|
||||
|
||||
test('checkVersion having require.main.filename', (t) => {
|
||||
const info = console.info
|
||||
t.assert.ok(require.main.filename)
|
||||
t.after(() => {
|
||||
console.info = info
|
||||
})
|
||||
|
||||
console.info = function (msg) {
|
||||
t.assert.fail('logged: ' + msg)
|
||||
}
|
||||
|
||||
fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
fastify: '^5.0.0'
|
||||
})
|
||||
})
|
||||
|
||||
test('checkVersion having no require.main.filename but process.argv[1]', (t) => {
|
||||
const filename = require.main.filename
|
||||
const info = console.info
|
||||
t.after(() => {
|
||||
require.main.filename = filename
|
||||
console.info = info
|
||||
})
|
||||
|
||||
require.main.filename = null
|
||||
|
||||
console.info = function (msg) {
|
||||
t.assert.fail('logged: ' + msg)
|
||||
}
|
||||
|
||||
fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
fastify: '^5.0.0'
|
||||
})
|
||||
})
|
||||
|
||||
test('checkVersion having no require.main.filename and no process.argv[1]', (t) => {
|
||||
const filename = require.main.filename
|
||||
const argv = process.argv
|
||||
const info = console.info
|
||||
t.after(() => {
|
||||
require.main.filename = filename
|
||||
process.argv = argv
|
||||
console.info = info
|
||||
})
|
||||
|
||||
require.main.filename = null
|
||||
process.argv[1] = null
|
||||
|
||||
console.info = function (msg) {
|
||||
t.assert.fail('logged: ' + msg)
|
||||
}
|
||||
|
||||
fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
fastify: '^5.0.0'
|
||||
})
|
||||
})
|
||||
14
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/composite.test.js
generated
vendored
Normal file
14
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/composite.test.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const fp = require('../plugin')
|
||||
|
||||
test('anonymous function should be named composite.test0', (t) => {
|
||||
t.plan(2)
|
||||
const fn = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn[Symbol.for('plugin-meta')].name, 'composite.test-auto-0')
|
||||
t.assert.strictEqual(fn[Symbol.for('fastify.display-name')], 'composite.test-auto-0')
|
||||
})
|
||||
11
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/esm/esm.mjs
generated
vendored
Normal file
11
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/esm/esm.mjs
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { test } from 'node:test'
|
||||
import fp from '../../plugin.js'
|
||||
|
||||
test('esm base support', (t) => {
|
||||
fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
}, {
|
||||
fastify: '^5.0.0'
|
||||
})
|
||||
t.assert.ok(true, 'fp function called without throwing an error')
|
||||
})
|
||||
11
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/esm/index.test.js
generated
vendored
Normal file
11
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/esm/index.test.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
// Node v8 throw a `SyntaxError: Unexpected token import`
|
||||
// even if this branch is never touch in the code,
|
||||
// by using `eval` we can avoid this issue.
|
||||
// eslint-disable-next-line
|
||||
new Function('module', 'return import(module)')('./esm.mjs').catch((err) => {
|
||||
process.nextTick(() => {
|
||||
throw err
|
||||
})
|
||||
})
|
||||
49
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/extractPluginName.test.js
generated
vendored
Normal file
49
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/extractPluginName.test.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const extractPluginName = require('../lib/getPluginName').extractPluginName
|
||||
|
||||
const winStack = `Error: anonymous function
|
||||
at checkName (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\index.js:43:11)
|
||||
at plugin (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\index.js:24:20)
|
||||
at Test.test (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\test\\hello.test.js:9:14)
|
||||
at bound (domain.js:396:14)
|
||||
at Test.runBound (domain.js:409:12)
|
||||
at ret (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:278:21)
|
||||
at Test.main (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:282:7)
|
||||
at writeSubComment (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:371:13)
|
||||
at TAP.writeSubComment (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:403:5)
|
||||
at Test.runBeforeEach (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:370:14)
|
||||
at loop (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\function-loop\\index.js:35:15)
|
||||
at TAP.runBeforeEach (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:683:7)
|
||||
at TAP.processSubtest (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:369:12)
|
||||
at TAP.process (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:306:14)
|
||||
at TAP.sub (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:185:10)
|
||||
at TAP.test (C:\\Users\\leonardo.davinci\\Desktop\\fastify-plugin\\node_modules\\tap\\lib\\test.js:209:17)`
|
||||
|
||||
const nixStack = `Error: anonymous function
|
||||
at checkName (/home/leonardo/desktop/fastify-plugin/index.js:43:11)
|
||||
at plugin (/home/leonardo/desktop/fastify-plugin/index.js:24:20)
|
||||
at Test.test (/home/leonardo/desktop/fastify-plugin/test/this.is.a.test.js:9:14)
|
||||
at bound (domain.js:396:14)
|
||||
at Test.runBound (domain.js:409:12)
|
||||
at ret (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:278:21)
|
||||
at Test.main (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:282:7)
|
||||
at writeSubComment (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:371:13)
|
||||
at TAP.writeSubComment (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:403:5)
|
||||
at Test.runBeforeEach (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:370:14)
|
||||
at loop (/home/leonardo/desktop/fastify-plugin/node_modules/function-loop/index.js:35:15)
|
||||
at TAP.runBeforeEach (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:683:7)
|
||||
at TAP.processSubtest (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:369:12)
|
||||
at TAP.process (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:306:14)
|
||||
at TAP.sub (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:185:10)
|
||||
at TAP.test (/home/leonardo/desktop/fastify-plugin/node_modules/tap/lib/test.js:209:17)`
|
||||
|
||||
const anonymousStack = 'Unable to parse this'
|
||||
|
||||
test('extractPluginName tests', (t) => {
|
||||
t.plan(3)
|
||||
t.assert.strictEqual(extractPluginName(winStack), 'hello.test')
|
||||
t.assert.strictEqual(extractPluginName(nixStack), 'this.is.a.test')
|
||||
t.assert.strictEqual(extractPluginName(anonymousStack), 'anonymous')
|
||||
})
|
||||
15
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/mu1tip1e.composite.test.js
generated
vendored
Normal file
15
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/mu1tip1e.composite.test.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const fp = require('../plugin')
|
||||
|
||||
test('anonymous function should be named mu1tip1e.composite.test', (t) => {
|
||||
t.plan(2)
|
||||
|
||||
const fn = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn[Symbol.for('plugin-meta')].name, 'mu1tip1e.composite.test-auto-0')
|
||||
t.assert.strictEqual(fn[Symbol.for('fastify.display-name')], 'mu1tip1e.composite.test-auto-0')
|
||||
})
|
||||
396
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/test.js
generated
vendored
Normal file
396
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/test.js
generated
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const proxyquire = require('proxyquire')
|
||||
const fp = require('../plugin')
|
||||
const Fastify = require('fastify')
|
||||
|
||||
const pkg = require('../package.json')
|
||||
|
||||
test('fastify-plugin is a function', (t) => {
|
||||
t.plan(1)
|
||||
t.assert.ok(typeof fp === 'function')
|
||||
})
|
||||
|
||||
test('should return the function with the skip-override Symbol', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
function plugin (_fastify, _opts, next) {
|
||||
next()
|
||||
}
|
||||
|
||||
fp(plugin)
|
||||
t.assert.ok(plugin[Symbol.for('skip-override')])
|
||||
})
|
||||
|
||||
test('should support "default" function from babel module', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
const plugin = {
|
||||
default: () => { }
|
||||
}
|
||||
|
||||
try {
|
||||
fp(plugin)
|
||||
t.assert.ok(true)
|
||||
} catch (e) {
|
||||
t.assert.strictEqual(e.message, 'fastify-plugin expects a function, instead got a \'object\'')
|
||||
}
|
||||
})
|
||||
|
||||
test('should throw if the plugin is not a function', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
try {
|
||||
fp('plugin')
|
||||
t.assert.fail()
|
||||
} catch (e) {
|
||||
t.assert.strictEqual(e.message, 'fastify-plugin expects a function, instead got a \'string\'')
|
||||
}
|
||||
})
|
||||
|
||||
test('should check the fastify version', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
function plugin (_fastify, _opts, next) {
|
||||
next()
|
||||
}
|
||||
|
||||
try {
|
||||
fp(plugin, { fastify: '>=0.10.0' })
|
||||
t.assert.ok(true)
|
||||
} catch {
|
||||
t.assert.fail()
|
||||
}
|
||||
})
|
||||
|
||||
test('should check the fastify version', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
function plugin (_fastify, _opts, next) {
|
||||
next()
|
||||
}
|
||||
|
||||
try {
|
||||
fp(plugin, '>=0.10.0')
|
||||
t.assert.ok(true)
|
||||
} catch {
|
||||
t.assert.fail()
|
||||
}
|
||||
})
|
||||
|
||||
test('the options object should be an object', (t) => {
|
||||
t.plan(2)
|
||||
|
||||
try {
|
||||
fp(() => { }, null)
|
||||
t.assert.fail()
|
||||
} catch (e) {
|
||||
t.assert.strictEqual(e.message, 'The options object should be an object')
|
||||
}
|
||||
|
||||
try {
|
||||
fp(() => { }, [])
|
||||
t.assert.fail()
|
||||
} catch (e) {
|
||||
t.assert.strictEqual(e.message, 'The options object should be an object')
|
||||
}
|
||||
})
|
||||
|
||||
test('should throw if the version number is not a string', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
try {
|
||||
fp(() => { }, { fastify: 12 })
|
||||
t.assert.fail()
|
||||
} catch (e) {
|
||||
t.assert.strictEqual(e.message, 'fastify-plugin expects a version string, instead got \'number\'')
|
||||
}
|
||||
})
|
||||
|
||||
test('Should accept an option object', (t) => {
|
||||
t.plan(2)
|
||||
|
||||
const opts = { hello: 'world' }
|
||||
|
||||
function plugin (_fastify, _opts, next) {
|
||||
next()
|
||||
}
|
||||
|
||||
fp(plugin, opts)
|
||||
|
||||
t.assert.ok(plugin[Symbol.for('skip-override')], 'skip-override symbol should be present')
|
||||
t.assert.deepStrictEqual(plugin[Symbol.for('plugin-meta')], opts, 'plugin-meta should match opts')
|
||||
})
|
||||
|
||||
test('Should accept an option object and checks the version', (t) => {
|
||||
t.plan(2)
|
||||
|
||||
const opts = { hello: 'world', fastify: '>=0.10.0' }
|
||||
|
||||
function plugin (_fastify, _opts, next) {
|
||||
next()
|
||||
}
|
||||
|
||||
fp(plugin, opts)
|
||||
t.assert.ok(plugin[Symbol.for('skip-override')])
|
||||
t.assert.deepStrictEqual(plugin[Symbol.for('plugin-meta')], opts)
|
||||
})
|
||||
|
||||
test('should set anonymous function name to file it was called from with a counter', (t) => {
|
||||
const fp = proxyquire('../plugin.js', { stubs: {} })
|
||||
|
||||
const fn = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn[Symbol.for('plugin-meta')].name, 'test-auto-0')
|
||||
t.assert.strictEqual(fn[Symbol.for('fastify.display-name')], 'test-auto-0')
|
||||
|
||||
const fn2 = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn2[Symbol.for('plugin-meta')].name, 'test-auto-1')
|
||||
t.assert.strictEqual(fn2[Symbol.for('fastify.display-name')], 'test-auto-1')
|
||||
})
|
||||
|
||||
test('should set function name if Error.stackTraceLimit is set to 0', (t) => {
|
||||
const stackTraceLimit = Error.stackTraceLimit = 0
|
||||
|
||||
const fp = proxyquire('../plugin.js', { stubs: {} })
|
||||
|
||||
const fn = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn[Symbol.for('plugin-meta')].name, 'test-auto-0')
|
||||
t.assert.strictEqual(fn[Symbol.for('fastify.display-name')], 'test-auto-0')
|
||||
|
||||
const fn2 = fp((_fastify, _opts, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn2[Symbol.for('plugin-meta')].name, 'test-auto-1')
|
||||
t.assert.strictEqual(fn2[Symbol.for('fastify.display-name')], 'test-auto-1')
|
||||
|
||||
Error.stackTraceLimit = stackTraceLimit
|
||||
})
|
||||
|
||||
test('should set display-name to meta name', (t) => {
|
||||
t.plan(2)
|
||||
|
||||
const functionName = 'superDuperSpecialFunction'
|
||||
|
||||
const fn = fp((_fastify, _opts, next) => next(), {
|
||||
name: functionName
|
||||
})
|
||||
|
||||
t.assert.strictEqual(fn[Symbol.for('plugin-meta')].name, functionName)
|
||||
t.assert.strictEqual(fn[Symbol.for('fastify.display-name')], functionName)
|
||||
})
|
||||
|
||||
test('should preserve fastify version in meta', (t) => {
|
||||
t.plan(1)
|
||||
|
||||
const opts = { hello: 'world', fastify: '>=0.10.0' }
|
||||
|
||||
const fn = fp((_fastify, _opts, next) => next(), opts)
|
||||
|
||||
t.assert.strictEqual(fn[Symbol.for('plugin-meta')].fastify, '>=0.10.0')
|
||||
})
|
||||
|
||||
test('should check fastify dependency graph - plugin', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'plugin1-name'
|
||||
}))
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'test',
|
||||
dependencies: ['plugin1-name', 'plugin2-name']
|
||||
}))
|
||||
|
||||
await t.assert.rejects(fastify.ready(), { message: "The dependency 'plugin2-name' of plugin 'test' is not registered" })
|
||||
})
|
||||
|
||||
test('should check fastify dependency graph - decorate', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.decorate('plugin1', fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'plugin1-name'
|
||||
}))
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'test',
|
||||
decorators: { fastify: ['plugin1', 'plugin2'] }
|
||||
}))
|
||||
|
||||
await t.assert.rejects(fastify.ready(), { message: "The decorator 'plugin2' required by 'test' is not present in Fastify" })
|
||||
})
|
||||
|
||||
test('should check fastify dependency graph - decorateReply', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.decorateReply('plugin1', fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'plugin1-name'
|
||||
}))
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'test',
|
||||
decorators: { reply: ['plugin1', 'plugin2'] }
|
||||
}))
|
||||
|
||||
await t.assert.rejects(fastify.ready(), { message: "The decorator 'plugin2' required by 'test' is not present in Reply" })
|
||||
})
|
||||
|
||||
test('should accept an option to encapsulate', async (t) => {
|
||||
t.plan(3)
|
||||
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.register(fp((fastify, _opts, next) => {
|
||||
fastify.decorate('accessible', true)
|
||||
next()
|
||||
}, {
|
||||
name: 'accessible-plugin'
|
||||
}))
|
||||
|
||||
fastify.register(fp((fastify, _opts, next) => {
|
||||
fastify.decorate('alsoAccessible', true)
|
||||
next()
|
||||
}, {
|
||||
name: 'accessible-plugin2',
|
||||
encapsulate: false
|
||||
}))
|
||||
|
||||
fastify.register(fp((fastify, _opts, next) => {
|
||||
fastify.decorate('encapsulated', true)
|
||||
next()
|
||||
}, {
|
||||
name: 'encapsulated-plugin',
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.ok(fastify.hasDecorator('accessible'))
|
||||
t.assert.ok(fastify.hasDecorator('alsoAccessible'))
|
||||
t.assert.ok(!fastify.hasDecorator('encapsulated'))
|
||||
})
|
||||
|
||||
test('should check dependencies when encapsulated', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
name: 'test',
|
||||
dependencies: ['missing-dependency-name'],
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
await t.assert.rejects(fastify.ready(), { message: "The dependency 'missing-dependency-name' of plugin 'test' is not registered" })
|
||||
})
|
||||
|
||||
test(
|
||||
'should check version when encapsulated',
|
||||
{ skip: /\d-.+/.test(pkg.devDependencies.fastify) },
|
||||
async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
name: 'test',
|
||||
fastify: '<=2.10.0',
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
await t.assert.rejects(fastify.ready(), { message: /fastify-plugin: test - expected '<=2.10.0' fastify version, '\d.\d+.\d+' is installed/ })
|
||||
}
|
||||
)
|
||||
|
||||
test('should check decorators when encapsulated', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.decorate('plugin1', 'foo')
|
||||
|
||||
fastify.register(fp((_fastify, _opts, next) => next(), {
|
||||
fastify: '5.x',
|
||||
name: 'test',
|
||||
encapsulate: true,
|
||||
decorators: { fastify: ['plugin1', 'plugin2'] }
|
||||
}))
|
||||
|
||||
await t.assert.rejects(fastify.ready(), { message: "The decorator 'plugin2' required by 'test' is not present in Fastify" })
|
||||
})
|
||||
|
||||
test('plugin name when encapsulated', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.register(function plugin (_instance, _opts, next) {
|
||||
next()
|
||||
})
|
||||
|
||||
fastify.register(fp(getFn('hello'), {
|
||||
fastify: '5.x',
|
||||
name: 'hello',
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
fastify.register(function plugin (fastify, _opts, next) {
|
||||
fastify.register(fp(getFn('deep'), {
|
||||
fastify: '5.x',
|
||||
name: 'deep',
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
fastify.register(fp(function genericPlugin (fastify, _opts, next) {
|
||||
t.assert.strictEqual(fastify.pluginName, 'deep-deep', 'should be deep-deep')
|
||||
|
||||
fastify.register(fp(getFn('deep-deep-deep'), {
|
||||
fastify: '5.x',
|
||||
name: 'deep-deep-deep',
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
fastify.register(fp(getFn('deep-deep -> not-encapsulated-2'), {
|
||||
fastify: '5.x',
|
||||
name: 'not-encapsulated-2'
|
||||
}))
|
||||
|
||||
next()
|
||||
}, {
|
||||
fastify: '5.x',
|
||||
name: 'deep-deep',
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
fastify.register(fp(getFn('plugin -> not-encapsulated'), {
|
||||
fastify: '5.x',
|
||||
name: 'not-encapsulated'
|
||||
}))
|
||||
|
||||
next()
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
function getFn (expectedName) {
|
||||
return function genericPlugin (fastify, _opts, next) {
|
||||
t.assert.strictEqual(fastify.pluginName, expectedName, `should be ${expectedName}`)
|
||||
next()
|
||||
}
|
||||
}
|
||||
})
|
||||
24
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/toCamelCase.test.js
generated
vendored
Normal file
24
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/test/toCamelCase.test.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const toCamelCase = require('../lib/toCamelCase')
|
||||
|
||||
test('from kebab-case to camelCase', (t) => {
|
||||
t.plan(1)
|
||||
t.assert.strictEqual(toCamelCase('hello-world'), 'helloWorld')
|
||||
})
|
||||
|
||||
test('from @-prefixed named imports', (t) => {
|
||||
t.plan(1)
|
||||
t.assert.strictEqual(toCamelCase('@hello/world'), 'helloWorld')
|
||||
})
|
||||
|
||||
test('from @-prefixed named kebab-case to camelCase', (t) => {
|
||||
t.plan(1)
|
||||
t.assert.strictEqual(toCamelCase('@hello/my-world'), 'helloMyWorld')
|
||||
})
|
||||
|
||||
test('from kebab-case to camelCase multiple words', (t) => {
|
||||
t.plan(1)
|
||||
t.assert.strictEqual(toCamelCase('hello-long-world'), 'helloLongWorld')
|
||||
})
|
||||
19
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/example-async.test-d.ts
generated
vendored
Normal file
19
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/example-async.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { FastifyPluginAsync } from 'fastify'
|
||||
|
||||
type FastifyExampleAsync = FastifyPluginAsync<fastifyExampleAsync.FastifyExampleAsyncOptions>
|
||||
|
||||
declare namespace fastifyExampleAsync {
|
||||
|
||||
export interface FastifyExampleAsyncOptions {
|
||||
foo?: 'bar'
|
||||
}
|
||||
|
||||
export interface FastifyExampleAsyncPluginOptions extends FastifyExampleAsyncOptions {
|
||||
}
|
||||
export const fastifyExampleAsync: FastifyExampleAsync
|
||||
export { fastifyExampleAsync as default }
|
||||
}
|
||||
|
||||
declare function fastifyExampleAsync (...params: Parameters<FastifyExampleAsync>): ReturnType<FastifyExampleAsync>
|
||||
|
||||
export default fastifyExampleAsync
|
||||
19
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/example-callback.test-d.ts
generated
vendored
Normal file
19
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/example-callback.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import { FastifyPluginCallback } from 'fastify'
|
||||
|
||||
type FastifyExampleCallback = FastifyPluginCallback<fastifyExampleCallback.FastifyExampleCallbackOptions>
|
||||
|
||||
declare namespace fastifyExampleCallback {
|
||||
|
||||
export interface FastifyExampleCallbackOptions {
|
||||
foo?: 'bar'
|
||||
}
|
||||
|
||||
export interface FastifyExampleCallbackPluginOptions extends FastifyExampleCallbackOptions {
|
||||
}
|
||||
export const fastifyExampleCallback: FastifyExampleCallback
|
||||
export { fastifyExampleCallback as default }
|
||||
}
|
||||
|
||||
declare function fastifyExampleCallback (...params: Parameters<FastifyExampleCallback>): ReturnType<FastifyExampleCallback>
|
||||
|
||||
export default fastifyExampleCallback
|
||||
61
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/plugin.d.ts
generated
vendored
Normal file
61
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/plugin.d.ts
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/// <reference types="fastify" />
|
||||
|
||||
import {
|
||||
FastifyPluginCallback,
|
||||
FastifyPluginAsync,
|
||||
FastifyPluginOptions,
|
||||
RawServerBase,
|
||||
RawServerDefault,
|
||||
FastifyTypeProvider,
|
||||
FastifyTypeProviderDefault,
|
||||
FastifyBaseLogger,
|
||||
} from 'fastify'
|
||||
|
||||
type FastifyPlugin = typeof fastifyPlugin
|
||||
|
||||
declare namespace fastifyPlugin {
|
||||
export interface PluginMetadata {
|
||||
/** Bare-minimum version of Fastify for your plugin, just add the semver range that you need. */
|
||||
fastify?: string,
|
||||
name?: string,
|
||||
/** Decorator dependencies for this plugin */
|
||||
decorators?: {
|
||||
fastify?: (string | symbol)[],
|
||||
reply?: (string | symbol)[],
|
||||
request?: (string | symbol)[]
|
||||
},
|
||||
/** The plugin dependencies */
|
||||
dependencies?: string[],
|
||||
encapsulate?: boolean
|
||||
}
|
||||
// Exporting PluginOptions for backward compatibility after renaming it to PluginMetadata
|
||||
/**
|
||||
* @deprecated Use PluginMetadata instead
|
||||
*/
|
||||
export interface PluginOptions extends PluginMetadata {}
|
||||
|
||||
export const fastifyPlugin: FastifyPlugin
|
||||
export { fastifyPlugin as default }
|
||||
}
|
||||
|
||||
/**
|
||||
* This function does three things for you:
|
||||
* 1. Add the `skip-override` hidden property
|
||||
* 2. Check bare-minimum version of Fastify
|
||||
* 3. Pass some custom metadata of the plugin to Fastify
|
||||
* @param fn Fastify plugin function
|
||||
* @param options Optional plugin options
|
||||
*/
|
||||
|
||||
declare function fastifyPlugin<
|
||||
Options extends FastifyPluginOptions = Record<never, never>,
|
||||
RawServer extends RawServerBase = RawServerDefault,
|
||||
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
|
||||
Logger extends FastifyBaseLogger = FastifyBaseLogger,
|
||||
Fn extends FastifyPluginCallback<Options, RawServer, TypeProvider, Logger> | FastifyPluginAsync<Options, RawServer, TypeProvider, Logger> = FastifyPluginCallback<Options, RawServer, TypeProvider, Logger>
|
||||
> (
|
||||
fn: Fn extends unknown ? Fn extends (...args: any) => Promise<any> ? FastifyPluginAsync<Options, RawServer, TypeProvider, Logger> : FastifyPluginCallback<Options, RawServer, TypeProvider, Logger> : Fn,
|
||||
options?: fastifyPlugin.PluginMetadata | string
|
||||
): Fn
|
||||
|
||||
export = fastifyPlugin
|
||||
166
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/plugin.test-d.ts
generated
vendored
Normal file
166
backend/node_modules/@fastify/swagger/node_modules/fastify-plugin/types/plugin.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
import fastifyPlugin from '..'
|
||||
import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault, FastifyBaseLogger } from 'fastify'
|
||||
import { expectAssignable, expectError, expectNotType, expectType } from 'tsd'
|
||||
import { Server } from 'node:https'
|
||||
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
||||
import fastifyExampleCallback from './example-callback.test-d'
|
||||
import fastifyExampleAsync from './example-async.test-d'
|
||||
|
||||
interface Options {
|
||||
foo: string
|
||||
}
|
||||
|
||||
const testSymbol = Symbol('foobar')
|
||||
|
||||
// Callback
|
||||
|
||||
const pluginCallback: FastifyPluginCallback = (_fastify, _options, _next) => { }
|
||||
expectType<FastifyPluginCallback>(fastifyPlugin(pluginCallback))
|
||||
|
||||
const pluginCallbackWithTypes = (_fastify: FastifyInstance, _options: FastifyPluginOptions, _next: (error?: FastifyError) => void): void => { }
|
||||
expectAssignable<FastifyPluginCallback>(fastifyPlugin(pluginCallbackWithTypes))
|
||||
expectNotType<any>(fastifyPlugin(pluginCallbackWithTypes))
|
||||
|
||||
expectAssignable<FastifyPluginCallback>(fastifyPlugin((_fastify: FastifyInstance, _options: FastifyPluginOptions, _next: (error?: FastifyError) => void): void => { }))
|
||||
expectNotType<any>(fastifyPlugin((_fastify: FastifyInstance, _options: FastifyPluginOptions, _next: (error?: FastifyError) => void): void => { }))
|
||||
|
||||
expectType<FastifyPluginCallback>(fastifyPlugin(pluginCallback, ''))
|
||||
expectType<FastifyPluginCallback>(fastifyPlugin(pluginCallback, {
|
||||
fastify: '',
|
||||
name: '',
|
||||
decorators: {
|
||||
fastify: ['', testSymbol],
|
||||
reply: ['', testSymbol],
|
||||
request: ['', testSymbol]
|
||||
},
|
||||
dependencies: [''],
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
const pluginCallbackWithOptions: FastifyPluginCallback<Options> = (_fastify, options, _next) => {
|
||||
expectType<string>(options.foo)
|
||||
}
|
||||
|
||||
expectType<FastifyPluginCallback<Options>>(fastifyPlugin(pluginCallbackWithOptions))
|
||||
|
||||
const pluginCallbackWithServer: FastifyPluginCallback<Options, Server> = (fastify, _options, _next) => {
|
||||
expectType<Server>(fastify.server)
|
||||
}
|
||||
|
||||
expectType<FastifyPluginCallback<Options, Server>>(fastifyPlugin(pluginCallbackWithServer))
|
||||
|
||||
const pluginCallbackWithTypeProvider: FastifyPluginCallback<Options, Server, TypeBoxTypeProvider> = (_fastify, _options, _next) => { }
|
||||
|
||||
expectType<FastifyPluginCallback<Options, Server, TypeBoxTypeProvider>>(fastifyPlugin(pluginCallbackWithTypeProvider))
|
||||
|
||||
// Async
|
||||
|
||||
const pluginAsync: FastifyPluginAsync = async (_fastify, _options) => { }
|
||||
expectType<FastifyPluginAsync>(fastifyPlugin(pluginAsync))
|
||||
|
||||
const pluginAsyncWithTypes = async (_fastify: FastifyInstance, _options: FastifyPluginOptions): Promise<void> => { }
|
||||
expectType<FastifyPluginAsync<FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault>>(fastifyPlugin(pluginAsyncWithTypes))
|
||||
|
||||
expectType<FastifyPluginAsync<FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault>>(fastifyPlugin(async (_fastify: FastifyInstance, _options: FastifyPluginOptions): Promise<void> => { }))
|
||||
expectType<FastifyPluginAsync>(fastifyPlugin(pluginAsync, ''))
|
||||
expectType<FastifyPluginAsync>(fastifyPlugin(pluginAsync, {
|
||||
fastify: '',
|
||||
name: '',
|
||||
decorators: {
|
||||
fastify: ['', testSymbol],
|
||||
reply: ['', testSymbol],
|
||||
request: ['', testSymbol]
|
||||
},
|
||||
dependencies: [''],
|
||||
encapsulate: true
|
||||
}))
|
||||
|
||||
const pluginAsyncWithOptions: FastifyPluginAsync<Options> = async (_fastify, options) => {
|
||||
expectType<string>(options.foo)
|
||||
}
|
||||
|
||||
expectType<FastifyPluginAsync<Options>>(fastifyPlugin(pluginAsyncWithOptions))
|
||||
|
||||
const pluginAsyncWithServer: FastifyPluginAsync<Options, Server> = async (fastify, _options) => {
|
||||
expectType<Server>(fastify.server)
|
||||
}
|
||||
|
||||
expectType<FastifyPluginAsync<Options, Server>>(fastifyPlugin(pluginAsyncWithServer))
|
||||
|
||||
const pluginAsyncWithTypeProvider: FastifyPluginAsync<Options, Server, TypeBoxTypeProvider> = async (_fastify, _options) => { }
|
||||
|
||||
expectType<FastifyPluginAsync<Options, Server, TypeBoxTypeProvider>>(fastifyPlugin(pluginAsyncWithTypeProvider))
|
||||
|
||||
// Fastify register
|
||||
|
||||
const server = fastify()
|
||||
server.register(fastifyPlugin(pluginCallback))
|
||||
server.register(fastifyPlugin(pluginCallbackWithTypes), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginCallbackWithOptions), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginCallbackWithServer), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginCallbackWithTypeProvider), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginAsync))
|
||||
server.register(fastifyPlugin(pluginAsyncWithTypes), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginAsyncWithOptions), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginAsyncWithServer), { foo: 'bar' })
|
||||
server.register(fastifyPlugin(pluginAsyncWithTypeProvider), { foo: 'bar' })
|
||||
|
||||
// properly handling callback and async
|
||||
fastifyPlugin(function (fastify, options, next) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Record<never, never>>(options)
|
||||
expectType<(err?: Error) => void>(next)
|
||||
})
|
||||
|
||||
fastifyPlugin<Options>(function (fastify, options, next) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Options>(options)
|
||||
expectType<(err?: Error) => void>(next)
|
||||
})
|
||||
|
||||
fastifyPlugin<Options>(async function (fastify, options) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Options>(options)
|
||||
})
|
||||
|
||||
expectAssignable<FastifyPluginAsync<Options, RawServerDefault, FastifyTypeProviderDefault, FastifyBaseLogger>>(fastifyPlugin(async function (_fastify: FastifyInstance, _options: Options) { }))
|
||||
expectNotType<any>(fastifyPlugin(async function (_fastify: FastifyInstance, _options: Options) { }))
|
||||
|
||||
fastifyPlugin(async function (fastify, options: Options) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Options>(options)
|
||||
})
|
||||
|
||||
fastifyPlugin(async function (fastify, options) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Record<never, never>>(options)
|
||||
})
|
||||
|
||||
expectError(
|
||||
fastifyPlugin(async function (fastify, options: Options, _next) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Options>(options)
|
||||
})
|
||||
)
|
||||
expectAssignable<FastifyPluginCallback<Options>>(fastifyPlugin(function (_fastify, _options, _next) { }))
|
||||
expectNotType<any>(fastifyPlugin(function (_fastify, _options, _next) { }))
|
||||
|
||||
fastifyPlugin(function (fastify, options: Options, next) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Options>(options)
|
||||
expectType<(err?: Error) => void>(next)
|
||||
})
|
||||
|
||||
expectError(
|
||||
fastifyPlugin(function (fastify, options: Options, _next) {
|
||||
expectType<FastifyInstance>(fastify)
|
||||
expectType<Options>(options)
|
||||
return Promise.resolve()
|
||||
})
|
||||
)
|
||||
|
||||
server.register(fastifyExampleCallback, { foo: 'bar' })
|
||||
expectError(server.register(fastifyExampleCallback, { foo: 'baz' }))
|
||||
|
||||
server.register(fastifyExampleAsync, { foo: 'bar' })
|
||||
expectError(server.register(fastifyExampleAsync, { foo: 'baz' }))
|
||||
89
backend/node_modules/@fastify/swagger/package.json
generated
vendored
Normal file
89
backend/node_modules/@fastify/swagger/package.json
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "@fastify/swagger",
|
||||
"version": "9.6.1",
|
||||
"description": "Serve Swagger/OpenAPI documentation for Fastify, supporting dynamic generation",
|
||||
"main": "index.js",
|
||||
"type": "commonjs",
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"lint": "eslint",
|
||||
"lint:fix": "eslint --fix",
|
||||
"test": "npm run test:unit && npm run test:typescript",
|
||||
"test:typescript": "tsd",
|
||||
"test:unit": "c8 --100 node --test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/fastify/fastify-swagger.git"
|
||||
},
|
||||
"keywords": [
|
||||
"fastify",
|
||||
"swagger",
|
||||
"openapi",
|
||||
"serve",
|
||||
"generate",
|
||||
"static"
|
||||
],
|
||||
"author": "Tomas Della Vedova - @delvedor (http://delved.org)",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Matteo Collina",
|
||||
"email": "hello@matteocollina.com"
|
||||
},
|
||||
{
|
||||
"name": "Manuel Spigolon",
|
||||
"email": "behemoth89@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Aras Abbasi",
|
||||
"email": "aras.abbasi@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Frazer Smith",
|
||||
"email": "frazer.dev@icloud.com",
|
||||
"url": "https://github.com/fdawgs"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/fastify/fastify-swagger/issues"
|
||||
},
|
||||
"homepage": "https://github.com/fastify/fastify-swagger#readme",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"devDependencies": {
|
||||
"@apidevtools/swagger-parser": "^12.0.0",
|
||||
"@fastify/cookie": "^11.0.1",
|
||||
"@types/node": "^24.0.10",
|
||||
"c8": "^10.1.3",
|
||||
"eslint": "^9.17.0",
|
||||
"fastify": "^5.0.0",
|
||||
"fluent-json-schema": "^6.0.0",
|
||||
"joi": "^17.13.1",
|
||||
"joi-to-json": "^5.0.0",
|
||||
"neostandard": "^0.12.0",
|
||||
"qs": "^6.12.1",
|
||||
"tsd": "^0.33.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"fastify-plugin": "^5.0.0",
|
||||
"json-schema-resolver": "^3.0.0",
|
||||
"openapi-types": "^12.1.3",
|
||||
"rfdc": "^1.3.1",
|
||||
"yaml": "^2.4.2"
|
||||
},
|
||||
"tsd": {
|
||||
"directory": "test-types"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
72
backend/node_modules/@fastify/swagger/test-types/http2-types.test-d.ts
generated
vendored
Normal file
72
backend/node_modules/@fastify/swagger/test-types/http2-types.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import fastify from 'fastify'
|
||||
import fastifySwagger from '..'
|
||||
import { minimalOpenApiV3Document } from './minimal-openapiV3-document'
|
||||
|
||||
const app = fastify({
|
||||
http2: true
|
||||
})
|
||||
|
||||
app.register(fastifySwagger)
|
||||
app.register(fastifySwagger, {})
|
||||
app.register(fastifySwagger, {
|
||||
transform: ({ schema, url }) => ({
|
||||
schema,
|
||||
url,
|
||||
})
|
||||
})
|
||||
app.register(fastifySwagger, {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
document: minimalOpenApiV3Document
|
||||
}
|
||||
})
|
||||
|
||||
app.put('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'put me some data',
|
||||
tags: ['user', 'code'],
|
||||
summary: 'qwerty',
|
||||
security: [{ apiKey: [] }]
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
app.get('/public/route', {
|
||||
schema: {
|
||||
description: 'returns 200 OK',
|
||||
summary: 'qwerty',
|
||||
security: []
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
app
|
||||
.register(fastifySwagger, {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
externalDocs: {
|
||||
url: 'https://swagger.io',
|
||||
description: 'Find more info here'
|
||||
},
|
||||
host: 'localhost',
|
||||
schemes: ['http'],
|
||||
consumes: ['application/json'],
|
||||
produces: ['application/json'],
|
||||
tags: [
|
||||
{ name: 'user', description: 'User related end-points' },
|
||||
{ name: 'code', description: 'Code related end-points' }
|
||||
],
|
||||
securityDefinitions: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.ready(() => {
|
||||
app.swagger()
|
||||
})
|
||||
22
backend/node_modules/@fastify/swagger/test-types/imports.test-d.ts
generated
vendored
Normal file
22
backend/node_modules/@fastify/swagger/test-types/imports.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import fastify from 'fastify'
|
||||
|
||||
import swaggerDefault, { fastifySwagger, SwaggerOptions } from '..'
|
||||
import * as fastifySwaggerStar from '..'
|
||||
import { minimalOpenApiV3Document } from './minimal-openapiV3-document'
|
||||
|
||||
const app = fastify()
|
||||
const fastifySwaggerOptions: SwaggerOptions = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
document: minimalOpenApiV3Document,
|
||||
}
|
||||
}
|
||||
|
||||
app.register(swaggerDefault, fastifySwaggerOptions)
|
||||
app.register(fastifySwagger, fastifySwaggerOptions)
|
||||
app.register(fastifySwaggerStar.default, fastifySwaggerOptions)
|
||||
app.register(fastifySwaggerStar.fastifySwagger, fastifySwaggerOptions)
|
||||
|
||||
app.ready(() => {
|
||||
app.swagger()
|
||||
})
|
||||
11
backend/node_modules/@fastify/swagger/test-types/minimal-openapiV3-document.ts
generated
vendored
Normal file
11
backend/node_modules/@fastify/swagger/test-types/minimal-openapiV3-document.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import { OpenAPIV3 } from 'openapi-types'
|
||||
|
||||
export const minimalOpenApiV3Document: OpenAPIV3.Document = {
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
version: '1.0.0',
|
||||
title: 'Test OpenApiv3 specification',
|
||||
},
|
||||
paths: {
|
||||
}
|
||||
}
|
||||
113
backend/node_modules/@fastify/swagger/test-types/swagger-ui-vendor-extensions.test-d.ts
generated
vendored
Normal file
113
backend/node_modules/@fastify/swagger/test-types/swagger-ui-vendor-extensions.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
import { OpenAPIV2, OpenAPIV3 } from 'openapi-types'
|
||||
import { expectAssignable } from 'tsd'
|
||||
|
||||
expectAssignable<OpenAPIV3.Document>({
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
version: '1.0.0',
|
||||
title: 'Test OpenApiv3 specification',
|
||||
},
|
||||
components: {
|
||||
securitySchemes: {
|
||||
myAuth: {
|
||||
type: 'oauth2',
|
||||
'x-tokenName': 'id_token',
|
||||
flows: {
|
||||
implicit: {
|
||||
authorizationUrl: 'http.../login/oauth/authorize',
|
||||
scopes: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
paths: {}
|
||||
})
|
||||
|
||||
expectAssignable<OpenAPIV2.Document>({
|
||||
swagger: '2.0.0',
|
||||
info: {
|
||||
title: 'Test OpenApiv2 specification',
|
||||
version: '2.0.0'
|
||||
},
|
||||
securityDefinitions: {
|
||||
OAuth2AccessCodeFlow: {
|
||||
type: 'oauth2',
|
||||
flow: 'accessCode',
|
||||
authorizationUrl: 'https://example.com/oauth/authorize',
|
||||
tokenUrl: 'https://example.com/oauth/token',
|
||||
'x-tokenName': 'id_token',
|
||||
scopes: { }
|
||||
},
|
||||
OAuth2ApplicationFlow: {
|
||||
type: 'oauth2',
|
||||
flow: 'application',
|
||||
tokenUrl: 'https://example.com/oauth/token',
|
||||
'x-tokenName': 'id_token',
|
||||
scopes: { }
|
||||
},
|
||||
OAuth2ImplicitFlow: {
|
||||
type: 'oauth2',
|
||||
flow: 'implicit',
|
||||
authorizationUrl: 'https://example.com/oauth/authorize',
|
||||
'x-tokenName': 'id_token',
|
||||
scopes: { }
|
||||
},
|
||||
OAuth2PasswordFlow: {
|
||||
type: 'oauth2',
|
||||
flow: 'password',
|
||||
tokenUrl: 'https://example.com/oauth/token',
|
||||
'x-tokenName': 'id_token',
|
||||
scopes: { }
|
||||
},
|
||||
},
|
||||
paths: {}
|
||||
})
|
||||
|
||||
expectAssignable<OpenAPIV2.Document>({
|
||||
swagger: '2.0.0',
|
||||
info: {
|
||||
title: 'Test OpenApiv2 specification',
|
||||
version: '2.0.0'
|
||||
},
|
||||
paths: {
|
||||
'/users/{userId}': {
|
||||
get: {
|
||||
summary: 'Gets a user by ID.',
|
||||
responses: {
|
||||
},
|
||||
parameters: [
|
||||
{
|
||||
in: 'path',
|
||||
name: 'userId',
|
||||
type: 'integer',
|
||||
required: true,
|
||||
description: 'Numeric ID of the user to get.',
|
||||
'x-example': 'BADC0FFEE'
|
||||
},
|
||||
{
|
||||
in: 'query',
|
||||
name: 'offset',
|
||||
type: 'integer',
|
||||
description: 'The number of items to skip before starting to collect the result set.',
|
||||
'x-example': 1337
|
||||
},
|
||||
{
|
||||
in: 'header',
|
||||
name: 'X-Request-ID',
|
||||
type: 'string',
|
||||
required: true,
|
||||
'x-example': 'wget'
|
||||
},
|
||||
{
|
||||
in: 'formData',
|
||||
name: 'name',
|
||||
type: 'string',
|
||||
description: "A person's name.",
|
||||
'x-example': 'John Doe'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
272
backend/node_modules/@fastify/swagger/test-types/types.test-d.ts
generated
vendored
Normal file
272
backend/node_modules/@fastify/swagger/test-types/types.test-d.ts
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
import fastify, { FastifySchema, RouteOptions } from 'fastify'
|
||||
import fastifySwagger, {
|
||||
formatParamUrl,
|
||||
SwaggerOptions,
|
||||
} from '..'
|
||||
import { minimalOpenApiV3Document } from './minimal-openapiV3-document'
|
||||
import { expectType } from 'tsd'
|
||||
|
||||
import {
|
||||
OpenAPI,
|
||||
OpenAPIV2,
|
||||
OpenAPIV3,
|
||||
// eslint-disable-next-line camelcase
|
||||
OpenAPIV3_1
|
||||
} from 'openapi-types'
|
||||
|
||||
const app = fastify()
|
||||
|
||||
app.register(fastifySwagger)
|
||||
app.register(fastifySwagger, {})
|
||||
app.register(fastifySwagger, {
|
||||
transform: ({ schema, url }) => ({
|
||||
schema,
|
||||
url,
|
||||
})
|
||||
})
|
||||
app.register(fastifySwagger, {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
document: minimalOpenApiV3Document
|
||||
}
|
||||
})
|
||||
app.register(fastifySwagger, { convertConstToEnum: false })
|
||||
|
||||
const fastifySwaggerOptions: SwaggerOptions = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
document: minimalOpenApiV3Document
|
||||
}
|
||||
}
|
||||
app.register(fastifySwagger, fastifySwaggerOptions)
|
||||
|
||||
const fastifyDynamicSwaggerOptions: SwaggerOptions = {
|
||||
mode: 'dynamic',
|
||||
hiddenTag: 'X-HIDDEN',
|
||||
hideUntagged: true,
|
||||
stripBasePath: true,
|
||||
refResolver: {
|
||||
buildLocalReference: (_json, _baseUri, fragment, i) => `${fragment}-${i}`
|
||||
}
|
||||
}
|
||||
app.register(fastifySwagger, fastifyDynamicSwaggerOptions)
|
||||
|
||||
app.get('/deprecated', {
|
||||
schema: {
|
||||
deprecated: true,
|
||||
hide: true
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
app.put('/some-route/:id', {
|
||||
schema: {
|
||||
description: 'put me some data',
|
||||
tags: ['user', 'code'],
|
||||
summary: 'qwerty',
|
||||
consumes: ['application/json', 'multipart/form-data'],
|
||||
security: [{ apiKey: [] }],
|
||||
operationId: 'opeId',
|
||||
externalDocs: {
|
||||
url: 'https://swagger.io',
|
||||
description: 'Find more info here'
|
||||
},
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
app.put('/image.png', {
|
||||
schema: {
|
||||
description: 'returns an image',
|
||||
summary: 'qwerty',
|
||||
consumes: ['application/json', 'multipart/form-data'],
|
||||
produces: ['image/png'],
|
||||
response: {
|
||||
200: {
|
||||
type: 'string',
|
||||
format: 'binary'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, async (_req, reply) => {
|
||||
reply
|
||||
.type('image/png')
|
||||
.send(Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAAAgSURBVBhXY/iPCkB8BgYkEiSIBICiCCEoB0SBwf///wGHRzXLSklJLQAAAABJRU5ErkJggg==', 'base64'))
|
||||
})
|
||||
|
||||
app.get('/public/route', {
|
||||
schema: {
|
||||
description: 'returns 200 OK',
|
||||
summary: 'qwerty',
|
||||
security: [],
|
||||
response: { 200: {} }
|
||||
},
|
||||
links: {
|
||||
200: { 'some-route': { operationId: 'opeId' } }
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
app.get('/public/readonly-schema-route', {
|
||||
schema: {
|
||||
description: 'returns 200 OK',
|
||||
tags: ['foo'],
|
||||
summary: 'qwerty',
|
||||
security: [],
|
||||
response: { 200: {} }
|
||||
},
|
||||
links: {
|
||||
200: { 'some-route': { operationId: 'opeId' } }
|
||||
}
|
||||
} as const, () => {})
|
||||
|
||||
app
|
||||
.register(fastifySwagger, {
|
||||
swagger: {
|
||||
info: {
|
||||
title: 'Test swagger',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0'
|
||||
},
|
||||
externalDocs: {
|
||||
url: 'https://swagger.io',
|
||||
description: 'Find more info here'
|
||||
},
|
||||
host: 'localhost',
|
||||
schemes: ['http'],
|
||||
consumes: ['application/json'],
|
||||
produces: ['application/json'],
|
||||
tags: [
|
||||
{ name: 'user', description: 'User related end-points' },
|
||||
{ name: 'code', description: 'Code related end-points' }
|
||||
],
|
||||
securityDefinitions: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.ready(() => {
|
||||
app.swagger()
|
||||
})
|
||||
|
||||
app
|
||||
.register(fastifySwagger, {
|
||||
openapi: {
|
||||
info: {
|
||||
title: 'Test openapi',
|
||||
description: 'testing the fastify swagger api',
|
||||
version: '0.1.0',
|
||||
},
|
||||
servers: [{ url: 'http://localhost' }],
|
||||
externalDocs: {
|
||||
url: 'https://swagger.io',
|
||||
description: 'Find more info here',
|
||||
},
|
||||
components: {
|
||||
schemas: {},
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'header',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
.ready(() => {
|
||||
app.swagger()
|
||||
})
|
||||
|
||||
app.register(fastifySwagger, {
|
||||
openapi: {
|
||||
components: {
|
||||
schemas: {
|
||||
Model: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'null' },
|
||||
},
|
||||
required: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
.ready(() => {
|
||||
app.swagger()
|
||||
})
|
||||
|
||||
app.register(fastifySwagger, {
|
||||
})
|
||||
.ready(() => {
|
||||
app.swagger()
|
||||
})
|
||||
|
||||
app.get(
|
||||
'/endpoint-transform-function',
|
||||
{
|
||||
config: {
|
||||
swaggerTransform: ({
|
||||
schema,
|
||||
url,
|
||||
route,
|
||||
...documentObject
|
||||
}) => {
|
||||
schema satisfies FastifySchema
|
||||
url satisfies string
|
||||
route satisfies RouteOptions
|
||||
// eslint-disable-next-line camelcase
|
||||
documentObject satisfies { swaggerObject: Partial<OpenAPIV2.Document> } | { openapiObject: Partial<OpenAPIV3.Document | OpenAPIV3_1.Document> }
|
||||
return { schema, url }
|
||||
},
|
||||
},
|
||||
},
|
||||
() => {}
|
||||
)
|
||||
|
||||
app.get(
|
||||
'/endpoint-transform-false',
|
||||
{
|
||||
config: {
|
||||
swaggerTransform: false,
|
||||
},
|
||||
},
|
||||
() => {}
|
||||
)
|
||||
|
||||
expectType<OpenAPI.Document>(app.swagger())
|
||||
expectType<OpenAPI.Document>(app.swagger({ yaml: false }))
|
||||
expectType<string>(app.swagger({ yaml: true }))
|
||||
expectType<OpenAPI.Document | string>(app.swagger({ yaml: Boolean(process.env.YAML) }))
|
||||
|
||||
expectType<(arg: string)=>string>(formatParamUrl)
|
||||
|
||||
app.register(fastifySwagger, {
|
||||
decorator: 'swagger'
|
||||
})
|
||||
|
||||
app.register(fastifySwagger, {
|
||||
decorator: 'customSwagger'
|
||||
})
|
||||
|
||||
app.register(fastifySwagger, {
|
||||
exposeHeadRoutes: true
|
||||
})
|
||||
|
||||
app.register(fastifySwagger, {
|
||||
exposeHeadRoutes: false
|
||||
})
|
||||
|
||||
app.get(
|
||||
'/endpoint-expose-head-route',
|
||||
{
|
||||
config: {
|
||||
swagger: {
|
||||
exposeHeadRoute: true
|
||||
}
|
||||
},
|
||||
},
|
||||
() => {}
|
||||
)
|
||||
45
backend/node_modules/@fastify/swagger/test/decorator.test.js
generated
vendored
Normal file
45
backend/node_modules/@fastify/swagger/test/decorator.test.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const fastifySwagger = require('../index')
|
||||
|
||||
test('fastify.swagger should exist', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.ok(fastify.swagger)
|
||||
})
|
||||
|
||||
test('fastify.swagger should throw if called before ready', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
|
||||
t.assert.throws(fastify.swagger.bind(fastify))
|
||||
})
|
||||
|
||||
test('fastify.swagger should throw if called before ready (openapi)', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: {}
|
||||
})
|
||||
|
||||
t.assert.throws(fastify.swagger.bind(fastify))
|
||||
})
|
||||
|
||||
test('decorator can be overridden', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, { decorator: 'customSwaggerDecorator' })
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.ok(fastify.customSwaggerDecorator())
|
||||
})
|
||||
14
backend/node_modules/@fastify/swagger/test/esm/esm.mjs
generated
vendored
Normal file
14
backend/node_modules/@fastify/swagger/test/esm/esm.mjs
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import t from 'node:test'
|
||||
import Fastify from 'fastify'
|
||||
import swaggerDefault from '../../index.js'
|
||||
|
||||
t.test('esm support', async t => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(swaggerDefault)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.swagger, '2.0')
|
||||
})
|
||||
11
backend/node_modules/@fastify/swagger/test/esm/index.test.js
generated
vendored
Normal file
11
backend/node_modules/@fastify/swagger/test/esm/index.test.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
// Node v8 throw a `SyntaxError: Unexpected token import`
|
||||
// even if this branch is never touch in the code,
|
||||
// by using `eval` we can avoid this issue.
|
||||
// eslint-disable-next-line
|
||||
new Function('module', 'return import(module)')('./esm.mjs').catch((err) => {
|
||||
process.nextTick(() => {
|
||||
throw err
|
||||
})
|
||||
})
|
||||
510
backend/node_modules/@fastify/swagger/test/mode/static.test.js
generated
vendored
Normal file
510
backend/node_modules/@fastify/swagger/test/mode/static.test.js
generated
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('node:path')
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const fastifySwagger = require('../../index')
|
||||
const fastifySwaggerDynamic = require('../../lib/mode/dynamic')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const readFileSync = require('node:fs').readFileSync
|
||||
const resolve = require('node:path').resolve
|
||||
const yaml = require('yaml')
|
||||
|
||||
test('specification validation check works', async (t) => {
|
||||
const specificationTests = [
|
||||
{
|
||||
specification: '',
|
||||
error: 'Error: specification is missing in the module options'
|
||||
},
|
||||
{
|
||||
specification: '123',
|
||||
error: 'Error: specification is not an object'
|
||||
},
|
||||
{
|
||||
specification: {},
|
||||
error: 'Error: both specification.path and specification.document are missing, should be path to the file or swagger document spec'
|
||||
},
|
||||
{
|
||||
specification: {
|
||||
path: 123
|
||||
},
|
||||
error: 'Error: specification.path is not a string'
|
||||
},
|
||||
{
|
||||
specification: {
|
||||
path: '/hello/lionel.richie'
|
||||
},
|
||||
error: 'Error: /hello/lionel.richie does not exist'
|
||||
},
|
||||
{
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml',
|
||||
postProcessor: 'hello'
|
||||
},
|
||||
error: 'Error: specification.postProcessor should be a function'
|
||||
}
|
||||
]
|
||||
|
||||
t.plan(specificationTests.length * 2)
|
||||
|
||||
for (const specificationTest of specificationTests) {
|
||||
try {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, {
|
||||
mode: 'static',
|
||||
specification: specificationTest.specification
|
||||
})
|
||||
} catch (err) {
|
||||
t.assert.notEqual(err, undefined)
|
||||
t.assert.strictEqual(err.toString(), specificationTest.error)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('registering plugin with invalid mode throws an error', async (t) => {
|
||||
const config = {
|
||||
mode: 'error'
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
try {
|
||||
await fastify.register(fastifySwagger, config)
|
||||
} catch (err) {
|
||||
t.assert.strictEqual(err.message, 'unsupported mode, should be one of [\'static\', \'dynamic\']')
|
||||
}
|
||||
})
|
||||
|
||||
test('unsupported file extension in specification.path throws an error', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.js'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
try {
|
||||
await fastify.register(fastifySwagger, config)
|
||||
} catch (err) {
|
||||
t.assert.strictEqual(err.message, 'specification.path extension name is not supported, should be one from [\'.yaml\', \'.json\']')
|
||||
}
|
||||
})
|
||||
|
||||
test('non-string specification.baseDir throws an error ', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml',
|
||||
baseDir: 1
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
try {
|
||||
await fastify.register(fastifySwagger, config)
|
||||
} catch (err) {
|
||||
t.assert.strictEqual(err.message, 'specification.baseDir should be string')
|
||||
}
|
||||
})
|
||||
|
||||
test('valid specification.baseDir is handled properly /1', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json',
|
||||
baseDir: __dirname
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
t.assert.deepStrictEqual(
|
||||
JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.json'), 'utf8')),
|
||||
fastify.swagger({ json: true })
|
||||
)
|
||||
})
|
||||
|
||||
test('valid specification.baseDir is handled properly /2', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json',
|
||||
baseDir: __dirname + '/' // eslint-disable-line n/no-path-concat
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
t.assert.deepStrictEqual(
|
||||
JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.json'), 'utf8')),
|
||||
fastify.swagger({ json: true })
|
||||
)
|
||||
})
|
||||
|
||||
test('valid yaml-specification is converted properly to json', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
t.assert.deepStrictEqual(
|
||||
JSON.parse(readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.json'), 'utf8')),
|
||||
fastify.swagger()
|
||||
)
|
||||
})
|
||||
|
||||
test('valid specification yaml is properly handled as yaml', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml',
|
||||
baseDir: __dirname
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
t.assert.strictEqual(
|
||||
readFileSync(resolve(__dirname, '..', '..', 'examples', 'example-static-specification.yaml'), 'utf8'),
|
||||
fastify.swagger({ yaml: true })
|
||||
)
|
||||
})
|
||||
|
||||
test('non-object specification.document throws an error', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
document: 'doc'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = new Fastify()
|
||||
|
||||
await t.assert.rejects(async () => await fastify.register(fastifySwagger, config), new Error('specification.document is not an object'))
|
||||
})
|
||||
|
||||
test('object specification.document', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
document: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = new Fastify()
|
||||
fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
t.assert.deepStrictEqual(fastify.swagger(), { type: 'object' })
|
||||
})
|
||||
|
||||
test('inserts default opts in fastifySwagger', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
|
||||
t.assert.ok(true, 'Inserted default option for fastifySwagger.')
|
||||
})
|
||||
|
||||
test('inserts default package name', async (t) => {
|
||||
const config = {
|
||||
mode: 'dynamic',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
|
||||
const originalPathJoin = path.join
|
||||
const testPackageJSON = path.join(__dirname, '../../examples/test-package.json')
|
||||
|
||||
path.join = (...args) => {
|
||||
if (args[3] === 'package.json') {
|
||||
return testPackageJSON
|
||||
}
|
||||
return originalPathJoin(...args)
|
||||
}
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.deepStrictEqual(fastify.swagger(), {
|
||||
swagger: '2.0',
|
||||
info: { version: '1.0.0', title: 'test' },
|
||||
definitions: {},
|
||||
paths: {}
|
||||
})
|
||||
})
|
||||
|
||||
test('inserts default package name - openapi', async (t) => {
|
||||
const config = {
|
||||
mode: 'dynamic',
|
||||
openapi: {
|
||||
servers: []
|
||||
},
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
|
||||
const originalPathJoin = path.join
|
||||
const testPackageJSON = path.join(__dirname, '../../examples/test-package.json')
|
||||
|
||||
path.join = (...args) => {
|
||||
if (args[3] === 'package.json') {
|
||||
return testPackageJSON
|
||||
}
|
||||
return originalPathJoin(...args)
|
||||
}
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.deepStrictEqual(fastify.swagger(), {
|
||||
openapi: '3.0.3',
|
||||
info: { version: '1.0.0', title: 'test' },
|
||||
components: { schemas: {} },
|
||||
paths: {},
|
||||
servers: []
|
||||
})
|
||||
})
|
||||
|
||||
test('throws an error if cannot parse package\'s JSON', async (t) => {
|
||||
const config = {
|
||||
mode: 'dynamic',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
|
||||
const originalPathJoin = path.join
|
||||
const testPackageJSON = path.join(__dirname, '')
|
||||
|
||||
path.join = (...args) => {
|
||||
if (args[3] === 'package.json') {
|
||||
return testPackageJSON
|
||||
}
|
||||
return originalPathJoin(...args)
|
||||
}
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.deepStrictEqual(fastify.swagger(), {
|
||||
swagger: '2.0',
|
||||
info: { version: '1.0.0', title: '' },
|
||||
definitions: {},
|
||||
paths: {}
|
||||
})
|
||||
})
|
||||
|
||||
test('throws an error if cannot parse package\'s JSON - openapi', async (t) => {
|
||||
const config = {
|
||||
mode: 'dynamic',
|
||||
openapi: {
|
||||
servers: []
|
||||
},
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
|
||||
const originalPathJoin = path.join
|
||||
const testPackageJSON = path.join(__dirname, '')
|
||||
|
||||
path.join = (...args) => {
|
||||
if (args[3] === 'package.json') {
|
||||
return testPackageJSON
|
||||
}
|
||||
return originalPathJoin(...args)
|
||||
}
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.deepStrictEqual(fastify.swagger(), {
|
||||
openapi: '3.0.3',
|
||||
info: { version: '1.0.0', title: '' },
|
||||
components: { schemas: {} },
|
||||
paths: {},
|
||||
servers: []
|
||||
})
|
||||
})
|
||||
|
||||
test('inserts default opts in fastifySwaggerDynamic (dynamic.js)', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwaggerDynamic)
|
||||
|
||||
t.assert.ok(true, 'Inserted default option for fastifySwagger.')
|
||||
})
|
||||
|
||||
test('should still return valid swagger object when missing package.json', async (t) => {
|
||||
const config = {
|
||||
mode: 'dynamic',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
|
||||
const originalPathJoin = path.join
|
||||
const testPackageJSON = path.join(__dirname, 'missing.json')
|
||||
|
||||
path.join = (...args) => {
|
||||
if (args[3] === 'package.json') {
|
||||
return testPackageJSON
|
||||
}
|
||||
return originalPathJoin(...args)
|
||||
}
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
|
||||
await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(true, 'Swagger object is still valid.')
|
||||
})
|
||||
|
||||
test('.swagger() returns cache.swaggerObject on second request in static mode', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.json'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(3)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerJson1 = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerJson1, 'object')
|
||||
|
||||
const swaggerJson2 = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerJson2, 'object')
|
||||
t.assert.strictEqual(swaggerJson1, swaggerJson2)
|
||||
})
|
||||
|
||||
test('.swagger({ yaml: true }) returns cache.swaggerString on second request in static mode', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml'
|
||||
}
|
||||
}
|
||||
|
||||
t.plan(3)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerYaml1 = fastify.swagger({ yaml: true })
|
||||
t.assert.strictEqual(typeof swaggerYaml1, 'string')
|
||||
|
||||
const swaggerYaml2 = fastify.swagger({ yaml: true })
|
||||
t.assert.strictEqual(typeof swaggerYaml2, 'string')
|
||||
t.assert.strictEqual(swaggerYaml1, swaggerYaml2)
|
||||
})
|
||||
|
||||
test('postProcessor works, swagger route returns updated yaml', async (t) => {
|
||||
const config = {
|
||||
mode: 'static',
|
||||
specification: {
|
||||
path: './examples/example-static-specification.yaml',
|
||||
postProcessor: function (swaggerObject) {
|
||||
swaggerObject.servers[0].url = 'http://localhost:4000/'
|
||||
return swaggerObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expectedYaml = `openapi: 3.0.0
|
||||
info:
|
||||
description: Test swagger specification
|
||||
version: 1.0.0
|
||||
title: Test swagger specification
|
||||
contact:
|
||||
email: super.developer@gmail.com
|
||||
servers:
|
||||
- url: http://localhost:4000/
|
||||
description: Localhost (uses test data)
|
||||
paths:
|
||||
/status:
|
||||
get:
|
||||
description: Status route, so we can check if server is alive
|
||||
tags:
|
||||
- Status
|
||||
responses:
|
||||
"200":
|
||||
description: Server is alive
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
health:
|
||||
type: boolean
|
||||
date:
|
||||
type: string
|
||||
example:
|
||||
health: true
|
||||
date: 2018-02-19T15:36:46.758Z
|
||||
`
|
||||
|
||||
t.plan(3)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, config)
|
||||
await fastify.ready()
|
||||
|
||||
// check that yaml is there
|
||||
const res = fastify.swagger({ yaml: true })
|
||||
|
||||
t.assert.strictEqual(typeof res, 'string')
|
||||
yaml.parse(res)
|
||||
t.assert.strictEqual(res, expectedYaml)
|
||||
t.assert.ok(true, 'valid swagger yaml')
|
||||
})
|
||||
1732
backend/node_modules/@fastify/swagger/test/spec/openapi/option.test.js
generated
vendored
Normal file
1732
backend/node_modules/@fastify/swagger/test/spec/openapi/option.test.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
564
backend/node_modules/@fastify/swagger/test/spec/openapi/refs.test.js
generated
vendored
Normal file
564
backend/node_modules/@fastify/swagger/test/spec/openapi/refs.test.js
generated
vendored
Normal file
@@ -0,0 +1,564 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const fastifySwagger = require('../../../index')
|
||||
|
||||
const openapiOption = {
|
||||
openapi: {},
|
||||
refResolver: {
|
||||
buildLocalReference: (json, _baseUri, _fragment, i) => {
|
||||
return json.$id || `def-${i}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test('support $ref schema', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'Order', type: 'object', properties: { id: { type: 'integer', examples: [25] } } })
|
||||
instance.post('/', { schema: { body: { $ref: 'Order#' }, response: { 200: { $ref: 'Order#' } } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
t.assert.deepStrictEqual(Object.keys(openapiObject.components.schemas), ['Order'])
|
||||
t.assert.strictEqual(openapiObject.components.schemas.Order.properties.id.example, 25)
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support $ref relative pointers in params', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({
|
||||
$id: 'Order',
|
||||
type: 'object',
|
||||
properties: {
|
||||
OrderId: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
instance.get('/:id', { schema: { params: { $ref: 'Order#/properties/OrderId' }, response: { 200: { $ref: 'Order#' } } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
t.assert.deepStrictEqual(Object.keys(openapiObject.components.schemas), ['Order'])
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support nested $ref schema : simple test', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'OrderItem', type: 'object', properties: { id: { type: 'integer' } }, examples: [{ id: 1 }] })
|
||||
instance.addSchema({ $id: 'ProductItem', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
instance.addSchema({ $id: 'Order', type: 'object', properties: { products: { type: 'array', items: { $ref: 'OrderItem' } } } })
|
||||
instance.post('/', { schema: { body: { $ref: 'Order' }, response: { 200: { $ref: 'Order' } } } }, () => {})
|
||||
instance.post('/other', { schema: { body: { $ref: 'ProductItem' } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const schemas = openapiObject.components.schemas
|
||||
t.assert.deepStrictEqual(Object.keys(schemas), ['OrderItem', 'ProductItem', 'Order'])
|
||||
|
||||
// ref must be prefixed by '#/components/schemas/'
|
||||
t.assert.strictEqual(schemas.Order.properties.products.items.$ref, '#/components/schemas/OrderItem')
|
||||
t.assert.deepStrictEqual(schemas.OrderItem.example, { id: 1 })
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support nested $ref schema : complex case', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
instance.addSchema({ $id: 'schemaB', type: 'object', properties: { id: { type: 'string', examples: ['ABC'] } } })
|
||||
instance.addSchema({ $id: 'schemaC', type: 'object', properties: { a: { type: 'array', items: { $ref: 'schemaA' } } } })
|
||||
instance.addSchema({ $id: 'schemaD', type: 'object', properties: { b: { $ref: 'schemaB' }, c: { $ref: 'schemaC' } } })
|
||||
instance.post('/url1', { schema: { body: { $ref: 'schemaD' }, response: { 200: { $ref: 'schemaB' } } } }, () => {})
|
||||
instance.post('/url2', { schema: { body: { $ref: 'schemaC' }, response: { 200: { $ref: 'schemaA' } } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const schemas = openapiObject.components.schemas
|
||||
t.assert.deepStrictEqual(Object.keys(schemas), ['schemaA', 'schemaB', 'schemaC', 'schemaD'])
|
||||
|
||||
// ref must be prefixed by '#/components/schemas/'
|
||||
t.assert.strictEqual(schemas.schemaC.properties.a.items.$ref, '#/components/schemas/schemaA')
|
||||
t.assert.strictEqual(schemas.schemaD.properties.b.$ref, '#/components/schemas/schemaB')
|
||||
t.assert.strictEqual(schemas.schemaD.properties.c.$ref, '#/components/schemas/schemaC')
|
||||
t.assert.strictEqual(schemas.schemaB.properties.id.example, 'ABC')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support $ref in response schema', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.register(function (instance, _, done) {
|
||||
instance.addSchema({ $id: 'order', type: 'string', enum: ['foo'] })
|
||||
instance.post('/', { schema: { response: { 200: { type: 'object', properties: { order: { $ref: 'order' } } } } } }, () => {})
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support $ref for enums in other schemas', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
const enumSchema = { $id: 'order', anyOf: [{ type: 'string', const: 'foo' }, { type: 'string', const: 'bar' }] }
|
||||
const enumRef = { $ref: 'order' }
|
||||
const objectWithEnumSchema = { $id: 'object', type: 'object', properties: { type: enumRef }, required: ['type'] }
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
await fastify.register(async (instance) => {
|
||||
instance.addSchema(enumSchema)
|
||||
instance.addSchema(objectWithEnumSchema)
|
||||
instance.post('/', { schema: { body: { type: 'object', properties: { order: { $ref: 'order' } } } } }, async () => ({ result: 'OK' }))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const responseBeforeSwagger = await fastify.inject({ method: 'POST', url: '/', payload: { order: 'foo' } })
|
||||
|
||||
t.assert.strictEqual(responseBeforeSwagger.statusCode, 200)
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
|
||||
const responseAfterSwagger = await fastify.inject({ method: 'POST', url: '/', payload: { order: 'foo' } })
|
||||
|
||||
t.assert.strictEqual(responseAfterSwagger.statusCode, 200)
|
||||
})
|
||||
|
||||
test('support nested $ref schema : complex case without modifying buildLocalReference', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: {} })
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
instance.addSchema({ $id: 'schemaB', type: 'object', properties: { id: { type: 'string' } } })
|
||||
instance.addSchema({ $id: 'schemaC', type: 'object', properties: { a: { type: 'array', items: { $ref: 'schemaA' } } } })
|
||||
instance.addSchema({ $id: 'schemaD', type: 'object', properties: { b: { $ref: 'schemaB' }, c: { $ref: 'schemaC' } } })
|
||||
instance.post('/url1', { schema: { body: { $ref: 'schemaD' }, response: { 200: { $ref: 'schemaB' } } } }, () => {})
|
||||
instance.post('/url2', { schema: { body: { $ref: 'schemaC' }, response: { 200: { $ref: 'schemaA' } } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const schemas = openapiObject.components.schemas
|
||||
t.assert.deepStrictEqual(Object.keys(schemas), ['def-0', 'def-1', 'def-2', 'def-3'])
|
||||
|
||||
// ref must be prefixed by '#/components/schemas/'
|
||||
t.assert.strictEqual(schemas['def-2'].properties.a.items.$ref, '#/components/schemas/def-0')
|
||||
t.assert.strictEqual(schemas['def-3'].properties.b.$ref, '#/components/schemas/def-1')
|
||||
t.assert.strictEqual(schemas['def-3'].properties.c.$ref, '#/components/schemas/def-2')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support nested $ref with patternProperties', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: {} })
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
instance.addSchema({ $id: 'schemaB', type: 'object', patternProperties: { '^[A-z]{1,10}$': { $ref: 'schemaA#' } } })
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const schemas = openapiObject.components.schemas
|
||||
t.assert.deepStrictEqual(Object.keys(schemas), ['def-0', 'def-1'])
|
||||
|
||||
// ref must be prefixed by '#/components/schemas/'
|
||||
t.assert.strictEqual(schemas['def-1'].additionalProperties.$ref, '#/components/schemas/def-0')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('support $ref schema in allOf in querystring', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: {} })
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { field1: { type: 'integer' } } })
|
||||
instance.get('/url1', { schema: { query: { type: 'object', allOf: [{ $ref: 'schemaA#' }, { type: 'object', properties: { field3: { type: 'boolean' } } }] }, response: { 200: { type: 'object' } } } }, async () => ({ result: 'OK' }))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const schemas = openapiObject.components.schemas
|
||||
t.assert.deepStrictEqual(Object.keys(schemas), ['def-0'])
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
|
||||
const responseAfterSwagger = await fastify.inject({ method: 'GET', url: '/url1', query: { field1: 10, field3: false } })
|
||||
|
||||
t.assert.strictEqual(responseAfterSwagger.statusCode, 200)
|
||||
})
|
||||
|
||||
test('support $ref schema in allOf in headers', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: {} })
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'headerA', type: 'object', properties: { 'x-header-1': { type: 'string' } } })
|
||||
instance.get('/url1', { schema: { headers: { allOf: [{ $ref: 'headerA#' }, { type: 'object', properties: { 'x-header-2': { type: 'string' } } }] }, response: { 200: { type: 'object' } } } }, async () => ({ result: 'OK' }))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const schemas = openapiObject.components.schemas
|
||||
t.assert.deepStrictEqual(Object.keys(schemas), ['def-0'])
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
|
||||
const responseAfterSwagger = await fastify.inject({ method: 'GET', url: '/url1', headers: { 'x-header-1': 'test', 'x-header-2': 'test' } })
|
||||
|
||||
t.assert.strictEqual(responseAfterSwagger.statusCode, 200)
|
||||
})
|
||||
|
||||
test('uses examples if has property required in body', async (t) => {
|
||||
t.plan(3)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/', {
|
||||
schema: {
|
||||
query: {
|
||||
type: 'object',
|
||||
oneOf: [
|
||||
{
|
||||
properties: {
|
||||
bar: { type: 'number' }
|
||||
}
|
||||
},
|
||||
{
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
result: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => ({ result: 'OK' }))
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
const schema = openapiObject.paths['/'].get
|
||||
|
||||
t.assert.ok(schema)
|
||||
t.assert.ok(schema.parameters)
|
||||
t.assert.deepStrictEqual(schema.parameters[0].in, 'query')
|
||||
})
|
||||
|
||||
test('renders $ref schema with enum in headers', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: {} })
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'headerA', type: 'object', properties: { 'x-enum-header': { type: 'string', enum: ['OK', 'NOT_OK'] } } })
|
||||
instance.get('/url1', { schema: { headers: { $ref: 'headerA#' }, response: { 200: { type: 'object' } } } }, async () => ({ result: 'OK' }))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
|
||||
// the OpenAPI spec should show the enum
|
||||
t.assert.deepStrictEqual(openapiObject.paths['/url1'].get.parameters[0].schema, { type: 'string', enum: ['OK', 'NOT_OK'] })
|
||||
})
|
||||
|
||||
test('renders $ref schema with additional keywords', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: {} })
|
||||
await fastify.register(require('@fastify/cookie'))
|
||||
|
||||
const cookie = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
a: { type: 'string' },
|
||||
b: { type: 'string' },
|
||||
c: { type: 'string' }
|
||||
},
|
||||
minProperties: 2
|
||||
}
|
||||
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({
|
||||
$id: 'headerA',
|
||||
type: 'object',
|
||||
properties: {
|
||||
cookie
|
||||
}
|
||||
})
|
||||
|
||||
instance.get('/url1', {
|
||||
preValidation: async (request) => {
|
||||
request.headers.cookie = request.cookies
|
||||
},
|
||||
schema: {
|
||||
headers: {
|
||||
$ref: 'headerA#'
|
||||
}
|
||||
}
|
||||
}, async (req) => (req.headers))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
const openapiObject = fastify.swagger()
|
||||
await Swagger.validate(openapiObject)
|
||||
|
||||
t.assert.deepStrictEqual(openapiObject.paths['/url1'].get.parameters[0].schema, cookie)
|
||||
|
||||
let res = await fastify.inject({ method: 'GET', url: 'url1', cookies: { a: 'hi', b: 'asd' } })
|
||||
|
||||
t.assert.deepStrictEqual(res.statusCode, 200)
|
||||
|
||||
res = await fastify.inject({ method: 'GET', url: 'url1', cookies: { a: 'hi' } })
|
||||
|
||||
t.assert.deepStrictEqual(res.statusCode, 400)
|
||||
t.assert.deepStrictEqual(openapiObject.paths['/url1'].get.parameters[0].schema, cookie)
|
||||
})
|
||||
|
||||
test('support $ref in callbacks', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'Subscription', type: 'object', properties: { callbackUrl: { type: 'string', examples: ['https://example.com'] } } })
|
||||
instance.addSchema({ $id: 'Event', type: 'object', properties: { message: { type: 'string', examples: ['Some event happened'] } } })
|
||||
instance.post('/subscribe', {
|
||||
schema: {
|
||||
body: {
|
||||
$ref: 'Subscription#'
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
$ref: 'Subscription#'
|
||||
}
|
||||
},
|
||||
callbacks: {
|
||||
myEvent: {
|
||||
'{$request.body#/callbackUrl}': {
|
||||
post: {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: { $ref: 'Event#' }
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Success'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
t.assert.deepStrictEqual(Object.keys(openapiObject.components.schemas), ['Subscription', 'Event'])
|
||||
t.assert.strictEqual(openapiObject.components.schemas.Subscription.properties.callbackUrl.example, 'https://example.com')
|
||||
t.assert.strictEqual(openapiObject.components.schemas.Event.properties.message.example, 'Some event happened')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
|
||||
test('should return only ref if defs and ref is defined', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: { openapi: '3.1.0' } })
|
||||
|
||||
fastify.addSchema({
|
||||
$id: 'sharedSchema',
|
||||
humanModule: {
|
||||
$defs: {
|
||||
AddressSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
street: {
|
||||
type: 'string',
|
||||
},
|
||||
streetNumber: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'street',
|
||||
'streetNumber',
|
||||
],
|
||||
$id: 'AddressSchema',
|
||||
},
|
||||
PersonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
homeAddress: {
|
||||
$ref: 'AddressSchema',
|
||||
},
|
||||
workAddress: {
|
||||
$ref: 'AddressSchema',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'name',
|
||||
'homeAddress',
|
||||
'workAddress',
|
||||
],
|
||||
$id: 'PersonSchema',
|
||||
},
|
||||
PostRequestSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
person: {
|
||||
$ref: 'PersonSchema',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'person',
|
||||
],
|
||||
$id: 'PostRequestSchema',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
fastify.get('/person', {
|
||||
schema: {
|
||||
response: {
|
||||
200:
|
||||
{
|
||||
$defs: {
|
||||
AddressSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
street: {
|
||||
type: 'string',
|
||||
},
|
||||
streetNumber: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'street',
|
||||
'streetNumber',
|
||||
],
|
||||
$id: 'AddressSchema',
|
||||
},
|
||||
PersonSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
homeAddress: {
|
||||
$ref: 'AddressSchema',
|
||||
},
|
||||
workAddress: {
|
||||
$ref: 'AddressSchema',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'name',
|
||||
'homeAddress',
|
||||
'workAddress',
|
||||
],
|
||||
$id: 'PersonSchema',
|
||||
},
|
||||
PostRequestSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
person: {
|
||||
$ref: 'PersonSchema',
|
||||
},
|
||||
},
|
||||
required: [
|
||||
'person',
|
||||
],
|
||||
$id: 'PostRequestSchema',
|
||||
},
|
||||
},
|
||||
$ref: 'PersonSchema',
|
||||
}
|
||||
}
|
||||
},
|
||||
}, async () => ({ result: 'OK' }))
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const expectedPathContent = { 'application/json': { schema: { $ref: '#/components/schemas/def-2' } } }
|
||||
t.assert.deepStrictEqual(openapiObject.paths['/person'].get.responses[200].content, expectedPathContent)
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
})
|
||||
899
backend/node_modules/@fastify/swagger/test/spec/openapi/route.test.js
generated
vendored
Normal file
899
backend/node_modules/@fastify/swagger/test/spec/openapi/route.test.js
generated
vendored
Normal file
@@ -0,0 +1,899 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const yaml = require('yaml')
|
||||
const fastifySwagger = require('../../../index')
|
||||
const {
|
||||
openapiOption,
|
||||
openapiRelativeOptions,
|
||||
schemaBody,
|
||||
schemaConsumes,
|
||||
schemaCookies,
|
||||
schemaExtension,
|
||||
schemaHeaders,
|
||||
schemaHeadersParams,
|
||||
schemaParams,
|
||||
schemaProduces,
|
||||
schemaQuerystring,
|
||||
schemaSecurity,
|
||||
schemaOperationId
|
||||
} = require('../../../examples/options')
|
||||
|
||||
test('openapi should return a valid swagger object', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/', () => {})
|
||||
fastify.post('/', () => {})
|
||||
fastify.get('/example', schemaQuerystring, () => {})
|
||||
fastify.post('/example', schemaBody, () => {})
|
||||
fastify.get('/parameters/:id', schemaParams, () => {})
|
||||
fastify.get('/headers', schemaHeaders, () => {})
|
||||
fastify.get('/headers/:id', schemaHeadersParams, () => {})
|
||||
fastify.get('/security', schemaSecurity, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
})
|
||||
|
||||
test('openapi should return a valid swagger yaml', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/', () => {})
|
||||
fastify.post('/', () => {})
|
||||
fastify.get('/example', schemaQuerystring, () => {})
|
||||
fastify.post('/example', schemaBody, () => {})
|
||||
fastify.get('/parameters/:id', schemaParams, () => {})
|
||||
fastify.get('/headers', schemaHeaders, () => {})
|
||||
fastify.get('/headers/:id', schemaHeadersParams, () => {})
|
||||
fastify.get('/security', schemaSecurity, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerYaml = fastify.swagger({ yaml: true })
|
||||
t.assert.strictEqual(typeof swaggerYaml, 'string')
|
||||
yaml.parse(swaggerYaml)
|
||||
t.assert.ok(true, 'valid swagger yaml')
|
||||
})
|
||||
|
||||
test('route options - deprecated', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
deprecated: true,
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(openapiObject.paths['/'])
|
||||
})
|
||||
|
||||
test('route options - meta', async (t) => {
|
||||
t.plan(7)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
operationId: 'doSomething',
|
||||
summary: 'Route summary',
|
||||
tags: ['tag'],
|
||||
description: 'Route description',
|
||||
servers: [
|
||||
{
|
||||
url: 'https://localhost'
|
||||
}
|
||||
],
|
||||
externalDocs: {
|
||||
description: 'Find more info here',
|
||||
url: 'https://swagger.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.get('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.strictEqual(opts.schema.operationId, definedPath.operationId)
|
||||
t.assert.strictEqual(opts.schema.summary, definedPath.summary)
|
||||
t.assert.deepEqual(opts.schema.tags, definedPath.tags)
|
||||
t.assert.strictEqual(opts.schema.description, definedPath.description)
|
||||
t.assert.strictEqual(opts.schema.servers, definedPath.servers)
|
||||
t.assert.strictEqual(opts.schema.externalDocs, definedPath.externalDocs)
|
||||
})
|
||||
|
||||
test('route options - produces', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/', schemaProduces, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepEqual(definedPath.responses[200].content, {
|
||||
'*/*': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
description: 'hello',
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
test('route options - cookies', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/', schemaCookies, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepEqual(definedPath.parameters, [
|
||||
{
|
||||
required: false,
|
||||
in: 'cookie',
|
||||
name: 'bar',
|
||||
schema: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('route options - extension', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { openapi: { 'x-ternal': true } })
|
||||
fastify.get('/', schemaExtension, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
t.assert.ok(api['x-ternal'])
|
||||
t.assert.deepEqual(api['x-ternal'], true)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepEqual(definedPath['x-tension'], true)
|
||||
})
|
||||
|
||||
test('parses form parameters when all api consumes application/x-www-form-urlencoded', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
fastify.post('/', schemaConsumes, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
const definedPath = api.paths['/'].post
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepEqual(definedPath.requestBody.content, {
|
||||
'application/x-www-form-urlencoded': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
description: 'hello',
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
test('route options - method', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.route({
|
||||
method: ['GET', 'POST'],
|
||||
url: '/',
|
||||
handler: function (request, reply) {
|
||||
reply.send({ hello: 'world' })
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
})
|
||||
|
||||
test('cookie, query, path description', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
const schemaCookies = {
|
||||
schema: {
|
||||
cookies: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bar: { type: 'string', description: 'Bar' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const schemaQuerystring = {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string', description: 'Hello' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// test without description as other test case for params already have description
|
||||
const schemaParams = {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.get('/', schemaCookies, () => {})
|
||||
fastify.get('/example', schemaQuerystring, () => {})
|
||||
fastify.get('/parameters/:id', schemaParams, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
const cookiesPath = api.paths['/'].get
|
||||
t.assert.ok(cookiesPath)
|
||||
t.assert.deepEqual(cookiesPath.parameters, [
|
||||
{
|
||||
required: false,
|
||||
in: 'cookie',
|
||||
name: 'bar',
|
||||
description: 'Bar',
|
||||
schema: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
])
|
||||
const querystringPath = api.paths['/example'].get
|
||||
t.assert.ok(querystringPath)
|
||||
t.assert.deepEqual(querystringPath.parameters, [
|
||||
{
|
||||
required: false,
|
||||
in: 'query',
|
||||
name: 'hello',
|
||||
description: 'Hello',
|
||||
schema: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
])
|
||||
const paramPath = api.paths['/parameters/{id}'].get
|
||||
t.assert.ok(paramPath)
|
||||
t.assert.deepEqual(paramPath.parameters, [
|
||||
{
|
||||
required: true,
|
||||
in: 'path',
|
||||
name: 'id',
|
||||
schema: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('cookie and query with serialization type', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify({
|
||||
ajv: {
|
||||
plugins: [
|
||||
function (ajv) {
|
||||
ajv.addKeyword({
|
||||
keyword: 'x-consume'
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
const schemaCookies = {
|
||||
schema: {
|
||||
cookies: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bar: {
|
||||
type: 'object',
|
||||
'x-consume': 'application/json',
|
||||
required: ['foo'],
|
||||
properties: {
|
||||
foo: { type: 'string' },
|
||||
bar: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const schemaQuerystring = {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
type: 'object',
|
||||
'x-consume': 'application/json',
|
||||
required: ['bar'],
|
||||
properties: {
|
||||
bar: { type: 'string' },
|
||||
baz: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.get('/', schemaCookies, () => {})
|
||||
fastify.get('/example', schemaQuerystring, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
|
||||
const cookiesPath = api.paths['/'].get
|
||||
t.assert.ok(cookiesPath)
|
||||
t.assert.deepEqual(cookiesPath.parameters, [
|
||||
{
|
||||
[Symbol.for('@fastify/swagger.rawRequired')]: ['foo'],
|
||||
required: false,
|
||||
in: 'cookie',
|
||||
name: 'bar',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['foo'],
|
||||
properties: {
|
||||
foo: { type: 'string' },
|
||||
bar: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
const querystringPath = api.paths['/example'].get
|
||||
t.assert.ok(querystringPath)
|
||||
t.assert.deepEqual(querystringPath.parameters, [
|
||||
{
|
||||
required: false,
|
||||
in: 'query',
|
||||
name: 'hello',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['bar'],
|
||||
properties: {
|
||||
bar: { type: 'string' },
|
||||
baz: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('openapi should pass through operationId', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/hello', schemaOperationId, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
})
|
||||
|
||||
test('openapi should pass through Links', async (t) => {
|
||||
t.plan(3)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/user/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'the user identifier, as userId'
|
||||
}
|
||||
},
|
||||
required: ['id']
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
uuid: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
links: {
|
||||
200: {
|
||||
address: {
|
||||
operationId: 'getUserAddress',
|
||||
parameters: {
|
||||
id: '$request.path.id'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/user/:id/address', {
|
||||
schema: {
|
||||
operationId: 'getUserAddress',
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'the user identifier, as userId'
|
||||
}
|
||||
},
|
||||
required: ['id']
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.deepEqual(api.paths['/user/{id}'].get.responses['200'].links, {
|
||||
address: {
|
||||
operationId: 'getUserAddress',
|
||||
parameters: {
|
||||
id: '$request.path.id'
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
test('links without status code', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/user/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'the user identifier, as userId'
|
||||
}
|
||||
},
|
||||
required: ['id']
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
uuid: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
links: {
|
||||
201: {
|
||||
address: {
|
||||
operationId: 'getUserAddress',
|
||||
parameters: {
|
||||
id: '$request.path.id'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/user/:id/address', {
|
||||
schema: {
|
||||
operationId: 'getUserAddress',
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'the user identifier, as userId'
|
||||
}
|
||||
},
|
||||
required: ['id']
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.throws(() => fastify.swagger(), new Error('missing status code 201 in route /user/:id'))
|
||||
})
|
||||
|
||||
test('security headers ignored when declared in security and securityScheme', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiOption)
|
||||
|
||||
fastify.get('/address1/:id', {
|
||||
schema: {
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
description: 'api token'
|
||||
},
|
||||
bearerAuth: {
|
||||
type: 'string',
|
||||
description: 'authorization bearer'
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/address2/:id', {
|
||||
schema: {
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authKey: {
|
||||
type: 'string',
|
||||
description: 'auth token'
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.strictEqual(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'apiKey')), undefined)
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'authKey')))
|
||||
})
|
||||
|
||||
test('security querystrings ignored when declared in security and securityScheme', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: {
|
||||
components: {
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'query'
|
||||
}
|
||||
}
|
||||
},
|
||||
security: [{
|
||||
apiKey: []
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/address1/:id', {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
description: 'api token'
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/address2/:id', {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authKey: {
|
||||
type: 'string',
|
||||
description: 'auth token'
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.strictEqual(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'apiKey')), undefined)
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'authKey')))
|
||||
})
|
||||
|
||||
test('security cookies ignored when declared in security and securityScheme', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: {
|
||||
components: {
|
||||
securitySchemes: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'cookie'
|
||||
}
|
||||
}
|
||||
},
|
||||
security: [{
|
||||
apiKey: []
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/address1/:id', {
|
||||
schema: {
|
||||
cookies: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
description: 'api token'
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/address2/:id', {
|
||||
schema: {
|
||||
cookies: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authKey: {
|
||||
type: 'string',
|
||||
description: 'auth token'
|
||||
},
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof openapiObject, 'object')
|
||||
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.strictEqual(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'apiKey')), undefined)
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'authKey')))
|
||||
})
|
||||
|
||||
test('path params on relative url', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiRelativeOptions)
|
||||
|
||||
const schemaParams = {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fastify.get('/parameters/:id', schemaParams, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const openapiObject = fastify.swagger()
|
||||
const api = await Swagger.validate(openapiObject)
|
||||
const paramPath = api.paths['/parameters/{id}'].get
|
||||
t.assert.ok(paramPath)
|
||||
t.assert.deepEqual(paramPath.parameters, [
|
||||
{
|
||||
required: true,
|
||||
in: 'path',
|
||||
name: 'id',
|
||||
schema: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('verify generated path param definition with route prefixing', async (t) => {
|
||||
const opts = {
|
||||
schema: {}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, openapiRelativeOptions)
|
||||
await fastify.register(function (app, _, done) {
|
||||
app.get('/:userId', opts, () => {})
|
||||
|
||||
done()
|
||||
}, { prefix: '/v1' })
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/v1/{userId}'].get
|
||||
|
||||
t.assert.deepEqual(definedPath.parameters, [{
|
||||
schema: {
|
||||
type: 'string'
|
||||
},
|
||||
in: 'path',
|
||||
name: 'userId',
|
||||
required: true
|
||||
}])
|
||||
})
|
||||
1936
backend/node_modules/@fastify/swagger/test/spec/openapi/schema.test.js
generated
vendored
Normal file
1936
backend/node_modules/@fastify/swagger/test/spec/openapi/schema.test.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
470
backend/node_modules/@fastify/swagger/test/spec/swagger/option.test.js
generated
vendored
Normal file
470
backend/node_modules/@fastify/swagger/test/spec/swagger/option.test.js
generated
vendored
Normal file
@@ -0,0 +1,470 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const yaml = require('yaml')
|
||||
const fastifySwagger = require('../../../index')
|
||||
const { readPackageJson } = require('../../../lib/util/read-package-json')
|
||||
const { swaggerOption } = require('../../../examples/options')
|
||||
|
||||
test('swagger should have default version', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.swagger, '2.0')
|
||||
})
|
||||
|
||||
test('swagger should have default info properties', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const pkg = readPackageJson()
|
||||
|
||||
t.assert.strictEqual(swaggerObject.info.title, pkg.name)
|
||||
t.assert.strictEqual(swaggerObject.info.version, pkg.version)
|
||||
})
|
||||
|
||||
test('swagger basic properties', async (t) => {
|
||||
t.plan(5)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.info, swaggerOption.swagger.info)
|
||||
t.assert.strictEqual(swaggerObject.host, swaggerOption.swagger.host)
|
||||
t.assert.strictEqual(swaggerObject.schemes, swaggerOption.swagger.schemes)
|
||||
t.assert.ok(swaggerObject.paths)
|
||||
t.assert.ok(swaggerObject.paths['/'])
|
||||
})
|
||||
|
||||
test('swagger definitions', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
swaggerOption.swagger.definitions = {
|
||||
ExampleModel: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'integer',
|
||||
description: 'Some id'
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of smthng'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(swaggerObject.definitions)), swaggerOption.swagger.definitions)
|
||||
delete swaggerOption.swagger.definitions // remove what we just added
|
||||
})
|
||||
|
||||
test('swagger paths', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
swaggerOption.swagger.paths = {
|
||||
'/status': {
|
||||
get: {
|
||||
description: 'Status route, so we can check if server is alive',
|
||||
tags: [
|
||||
'Status'
|
||||
],
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Server is alive',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
health: {
|
||||
type: 'boolean'
|
||||
},
|
||||
date: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
example: {
|
||||
health: true,
|
||||
date: '2018-02-19T15:36:46.758Z'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.deepStrictEqual(swaggerObject.paths, swaggerOption.swagger.paths)
|
||||
delete swaggerOption.swagger.paths // remove what we just added
|
||||
})
|
||||
|
||||
test('swagger tags', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.tags, swaggerOption.swagger.tags)
|
||||
})
|
||||
|
||||
test('swagger externalDocs', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.externalDocs, swaggerOption.swagger.externalDocs)
|
||||
})
|
||||
|
||||
test('basePath support', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: Object.assign({}, swaggerOption.swagger, {
|
||||
basePath: '/prefix'
|
||||
})
|
||||
})
|
||||
|
||||
fastify.get('/prefix/endpoint', {}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/prefix/endpoint'], undefined)
|
||||
t.assert.ok(swaggerObject.paths['/endpoint'])
|
||||
})
|
||||
|
||||
test('basePath support with prefix', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
prefix: '/prefix',
|
||||
swagger: Object.assign({}, swaggerOption.swagger, {
|
||||
basePath: '/prefix'
|
||||
})
|
||||
})
|
||||
|
||||
fastify.get('/endpoint', {}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/prefix/endpoint'], undefined)
|
||||
t.assert.ok(swaggerObject.paths['/endpoint'])
|
||||
})
|
||||
|
||||
test('basePath ensure leading slash', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: Object.assign({}, swaggerOption.swagger, {
|
||||
basePath: '/'
|
||||
})
|
||||
})
|
||||
|
||||
fastify.get('/endpoint', {}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths.endpoint, undefined)
|
||||
t.assert.ok(swaggerObject.paths['/endpoint'])
|
||||
})
|
||||
|
||||
test('basePath with prefix ensure leading slash', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
prefix: '/',
|
||||
swagger: Object.assign({}, swaggerOption.swagger, {
|
||||
basePath: '/'
|
||||
})
|
||||
})
|
||||
|
||||
fastify.get('/endpoint', {}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths.endpoint, undefined)
|
||||
t.assert.ok(swaggerObject.paths['/endpoint'])
|
||||
})
|
||||
|
||||
test('basePath maintained when stripBasePath is set to false', async (t) => {
|
||||
t.plan(3)
|
||||
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
stripBasePath: false,
|
||||
swagger: Object.assign({}, swaggerOption.swagger, {
|
||||
basePath: '/foo'
|
||||
})
|
||||
})
|
||||
|
||||
fastify.get('/foo/endpoint', {}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths.endpoint, undefined)
|
||||
t.assert.strictEqual(swaggerObject.paths['/endpoint'], undefined)
|
||||
t.assert.ok(swaggerObject.paths['/foo/endpoint'])
|
||||
})
|
||||
|
||||
// hide testing
|
||||
|
||||
test('hide support - property', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
hide: true,
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/'], undefined)
|
||||
})
|
||||
|
||||
test('hide support when property set in transform() - property', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
...swaggerOption,
|
||||
transform: ({ schema, url }) => {
|
||||
return { schema: { ...schema, hide: true }, url }
|
||||
}
|
||||
})
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/'], undefined)
|
||||
})
|
||||
|
||||
test('hide support - tags Default', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
tags: ['X-HIDDEN'],
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/'], undefined)
|
||||
})
|
||||
|
||||
test('hide support - tags Custom', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, { ...swaggerOption, hiddenTag: 'NOP' })
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
tags: ['NOP'],
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/'], undefined)
|
||||
})
|
||||
|
||||
test('hide support - hidden untagged', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, { ...swaggerOption, hideUntagged: true })
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.paths['/'], undefined)
|
||||
})
|
||||
|
||||
test('cache - json', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
fastify.swagger()
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
|
||||
await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
})
|
||||
|
||||
test('cache - yaml', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
fastify.swagger({ yaml: true })
|
||||
const swaggerYaml = fastify.swagger({ yaml: true })
|
||||
t.assert.strictEqual(typeof swaggerYaml, 'string')
|
||||
yaml.parse(swaggerYaml)
|
||||
t.assert.ok(true, 'valid swagger yaml')
|
||||
})
|
||||
|
||||
module.exports = { swaggerOption }
|
||||
164
backend/node_modules/@fastify/swagger/test/spec/swagger/refs.test.js
generated
vendored
Normal file
164
backend/node_modules/@fastify/swagger/test/spec/swagger/refs.test.js
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const fastifySwagger = require('../../../index')
|
||||
const { FST_ERR_SCH_ALREADY_PRESENT } = require('fastify/lib/errors')
|
||||
|
||||
test('support $ref schema', async t => {
|
||||
t.plan(1)
|
||||
|
||||
const fastify = Fastify()
|
||||
fastify.addSchema({
|
||||
$id: 'example',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
|
||||
fastify.register((instance, _opts, next) => {
|
||||
instance.addSchema({
|
||||
$id: 'subschema-two',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
})
|
||||
|
||||
instance.register((subinstance, _opts, next) => {
|
||||
subinstance.addSchema({
|
||||
$id: 'subschema-three',
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
})
|
||||
|
||||
subinstance.post('/:hello', {
|
||||
handler () {},
|
||||
schema: {
|
||||
body: { $ref: 'example#/properties/hello' },
|
||||
querystring: { $ref: 'subschema-two#/properties/hello' },
|
||||
params: { $ref: 'subschema-two#/properties/hello' },
|
||||
headers: { $ref: 'subschema-three#/properties/hello' },
|
||||
response: {
|
||||
200: { $ref: 'example#/properties/hello' }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
next()
|
||||
})
|
||||
|
||||
next()
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
await Swagger.validate(fastify.swagger())
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
})
|
||||
|
||||
test('support nested $ref schema : complex case', async (t) => {
|
||||
const options = {
|
||||
swagger: {},
|
||||
refResolver: {
|
||||
buildLocalReference: (json, _baseUri, _fragment, i) => {
|
||||
return json.$id || `def-${i}`
|
||||
}
|
||||
}
|
||||
}
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, options)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
instance.addSchema({ $id: 'schemaB', type: 'object', properties: { id: { type: 'string' } } })
|
||||
instance.addSchema({ $id: 'schemaC', type: 'object', properties: { a: { type: 'array', items: { $ref: 'schemaA' } } } })
|
||||
instance.addSchema({ $id: 'schemaD', type: 'object', properties: { b: { $ref: 'schemaB' }, c: { $ref: 'schemaC' } } })
|
||||
instance.post('/url1', { schema: { body: { $ref: 'schemaD' }, response: { 200: { $ref: 'schemaB' } } } }, () => {})
|
||||
instance.post('/url2', { schema: { body: { $ref: 'schemaC' }, response: { 200: { $ref: 'schemaA' } } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
const definitions = swaggerObject.definitions
|
||||
t.assert.deepStrictEqual(Object.keys(definitions), ['schemaA', 'schemaB', 'schemaC', 'schemaD'])
|
||||
|
||||
// ref must be prefixed by '#/definitions/'
|
||||
t.assert.strictEqual(definitions.schemaC.properties.a.items.$ref, '#/definitions/schemaA')
|
||||
t.assert.strictEqual(definitions.schemaD.properties.b.$ref, '#/definitions/schemaB')
|
||||
t.assert.strictEqual(definitions.schemaD.properties.c.$ref, '#/definitions/schemaC')
|
||||
|
||||
await Swagger.validate(swaggerObject)
|
||||
})
|
||||
|
||||
test('support nested $ref schema : complex case without modifying buildLocalReference', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
instance.addSchema({ $id: 'schemaB', type: 'object', properties: { id: { type: 'string' } } })
|
||||
instance.addSchema({ $id: 'schemaC', type: 'object', properties: { a: { type: 'array', items: { $ref: 'schemaA' } } } })
|
||||
instance.addSchema({ $id: 'schemaD', type: 'object', properties: { b: { $ref: 'schemaB' }, c: { $ref: 'schemaC' } } })
|
||||
instance.post('/url1', { schema: { body: { $ref: 'schemaD' }, response: { 200: { $ref: 'schemaB' } } } }, () => {})
|
||||
instance.post('/url2', { schema: { body: { $ref: 'schemaC' }, response: { 200: { $ref: 'schemaA' } } } }, () => {})
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
|
||||
const definitions = swaggerObject.definitions
|
||||
t.assert.deepStrictEqual(Object.keys(definitions), ['def-0', 'def-1', 'def-2', 'def-3'])
|
||||
|
||||
// ref must be prefixed by '#/definitions/'
|
||||
t.assert.strictEqual(definitions['def-2'].properties.a.items.$ref, '#/definitions/def-0')
|
||||
t.assert.strictEqual(definitions['def-3'].properties.b.$ref, '#/definitions/def-1')
|
||||
t.assert.strictEqual(definitions['def-3'].properties.c.$ref, '#/definitions/def-2')
|
||||
|
||||
await Swagger.validate(swaggerObject)
|
||||
})
|
||||
|
||||
test('trying to overwriting a schema results in a FST_ERR_SCH_ALREADY_PRESENT', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } })
|
||||
t.assert.throws(() => instance.addSchema({ $id: 'schemaA', type: 'object', properties: { id: { type: 'integer' } } }), new FST_ERR_SCH_ALREADY_PRESENT('schemaA'))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
})
|
||||
|
||||
test('renders $ref schema with enum in headers', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.register(async (instance) => {
|
||||
instance.addSchema({ $id: 'headerA', type: 'object', properties: { 'x-enum-header': { type: 'string', enum: ['OK', 'NOT_OK'] } } })
|
||||
instance.get('/url1', { schema: { headers: { $ref: 'headerA#' }, response: { 200: { type: 'object' } } } }, async () => ({ result: 'OK' }))
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swagger = fastify.swagger()
|
||||
|
||||
await Swagger.validate(swagger)
|
||||
|
||||
t.assert.deepStrictEqual(
|
||||
swagger.paths['/url1'].get.parameters[0],
|
||||
{
|
||||
type: 'string',
|
||||
enum: ['OK', 'NOT_OK'],
|
||||
in: 'header',
|
||||
name: 'x-enum-header',
|
||||
required: false
|
||||
}
|
||||
)
|
||||
})
|
||||
585
backend/node_modules/@fastify/swagger/test/spec/swagger/route.test.js
generated
vendored
Normal file
585
backend/node_modules/@fastify/swagger/test/spec/swagger/route.test.js
generated
vendored
Normal file
@@ -0,0 +1,585 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const yaml = require('yaml')
|
||||
const fastifySwagger = require('../../../index')
|
||||
const {
|
||||
swaggerOption,
|
||||
schemaBody,
|
||||
schemaConsumes,
|
||||
schemaExtension,
|
||||
schemaHeaders,
|
||||
schemaHeadersParams,
|
||||
schemaParams,
|
||||
schemaQuerystring,
|
||||
schemaSecurity
|
||||
} = require('../../../examples/options')
|
||||
|
||||
test('swagger should return valid swagger object', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
fastify.get('/', () => {})
|
||||
fastify.post('/', () => {})
|
||||
fastify.get('/example', schemaQuerystring, () => {})
|
||||
fastify.post('/example', schemaBody, () => {})
|
||||
fastify.get('/parameters/:id', schemaParams, () => {})
|
||||
fastify.get('/headers', schemaHeaders, () => {})
|
||||
fastify.get('/headers/:id', schemaHeadersParams, () => {})
|
||||
fastify.get('/security', schemaSecurity, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
|
||||
await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
})
|
||||
|
||||
test('swagger should return a valid swagger yaml', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
fastify.get('/', () => {})
|
||||
fastify.route({
|
||||
method: ['POST'],
|
||||
url: '/',
|
||||
handler: () => {}
|
||||
})
|
||||
fastify.get('/example', schemaQuerystring, () => {})
|
||||
fastify.post('/example', schemaBody, () => {})
|
||||
fastify.get('/parameters/:id', schemaParams, () => {})
|
||||
fastify.get('/headers', schemaHeaders, () => {})
|
||||
fastify.get('/headers/:id', schemaHeadersParams, () => {})
|
||||
fastify.get('/security', schemaSecurity, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerYaml = fastify.swagger({ yaml: true })
|
||||
t.assert.strictEqual(typeof swaggerYaml, 'string')
|
||||
yaml.parse(swaggerYaml)
|
||||
t.assert.ok(true, 'valid swagger yaml')
|
||||
})
|
||||
|
||||
test('route options - deprecated', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
deprecated: true,
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
some: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.post('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(swaggerObject.paths['/'])
|
||||
})
|
||||
|
||||
test('route options - meta', async (t) => {
|
||||
t.plan(8)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
operationId: 'doSomething',
|
||||
summary: 'Route summary',
|
||||
tags: ['tag'],
|
||||
description: 'Route description',
|
||||
produces: ['application/octet-stream'],
|
||||
consumes: ['application/x-www-form-urlencoded'],
|
||||
externalDocs: {
|
||||
description: 'Find more info here',
|
||||
url: 'https://swagger.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.get('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.strictEqual(opts.schema.operationId, definedPath.operationId)
|
||||
t.assert.strictEqual(opts.schema.summary, definedPath.summary)
|
||||
t.assert.deepStrictEqual(opts.schema.tags, definedPath.tags)
|
||||
t.assert.strictEqual(opts.schema.description, definedPath.description)
|
||||
t.assert.deepStrictEqual(opts.schema.produces, definedPath.produces)
|
||||
t.assert.deepStrictEqual(opts.schema.consumes, definedPath.consumes)
|
||||
t.assert.strictEqual(opts.schema.externalDocs, definedPath.externalDocs)
|
||||
})
|
||||
|
||||
test('route options - consumes', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
fastify.post('/', schemaConsumes, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
const definedPath = api.paths['/'].post
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepStrictEqual(definedPath.parameters, [{
|
||||
in: 'formData',
|
||||
name: 'hello',
|
||||
description: 'hello',
|
||||
required: true,
|
||||
type: 'string'
|
||||
}])
|
||||
})
|
||||
|
||||
test('route options - extension', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { swagger: { 'x-ternal': true } })
|
||||
fastify.get('/', schemaExtension, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(api['x-ternal'])
|
||||
t.assert.deepStrictEqual(api['x-ternal'], true)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepStrictEqual(definedPath['x-tension'], true)
|
||||
})
|
||||
|
||||
test('route options - querystring', async (t) => {
|
||||
t.plan(2)
|
||||
|
||||
const opts = {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' },
|
||||
world: { type: 'string', description: 'world description' }
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
fastify.get('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepStrictEqual(definedPath.parameters, [
|
||||
{
|
||||
in: 'query',
|
||||
name: 'hello',
|
||||
type: 'string',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
in: 'query',
|
||||
name: 'world',
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'world description'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
test('swagger json output should not omit enum part in params config', async (t) => {
|
||||
t.plan(2)
|
||||
const opts = {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
enumKey: { type: 'string', enum: ['enum1', 'enum2'] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
fastify.get('/test/:enumKey', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
const definedPath = api.paths['/test/{enumKey}'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepStrictEqual(definedPath.parameters, [{
|
||||
in: 'path',
|
||||
name: 'enumKey',
|
||||
type: 'string',
|
||||
enum: ['enum1', 'enum2'],
|
||||
required: true
|
||||
}])
|
||||
})
|
||||
|
||||
test('custom verbs should not be interpreted as path params', async (t) => {
|
||||
t.plan(2)
|
||||
const opts = {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
fastify.get('/resource/:id/sub-resource::watch', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
const definedPath = api.paths['/resource/{id}/sub-resource:watch'].get
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepStrictEqual(definedPath.parameters, [{
|
||||
in: 'path',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
required: true
|
||||
}])
|
||||
})
|
||||
|
||||
test('swagger json output should not omit consume in querystring schema', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify({
|
||||
ajv: {
|
||||
plugins: [
|
||||
function (ajv) {
|
||||
ajv.addKeyword({ keyword: 'x-consume' })
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
const schemaQuerystring = {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
type: 'object',
|
||||
'x-consume': 'application/json',
|
||||
required: ['bar'],
|
||||
properties: {
|
||||
bar: { type: 'string' },
|
||||
baz: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fastify.get('/', schemaQuerystring, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
try {
|
||||
fastify.swagger()
|
||||
t.assert.fail('error was not thrown')
|
||||
} catch (err) {
|
||||
if (err.message.startsWith('Complex serialization is not supported by Swagger')) {
|
||||
t.assert.ok(true, 'error was thrown')
|
||||
} else {
|
||||
t.error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('swagger should not support Links', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
fastify.get('/user/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'the user identifier, as userId'
|
||||
}
|
||||
},
|
||||
required: ['id']
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
uuid: {
|
||||
type: 'string',
|
||||
format: 'uuid'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
links: {
|
||||
200: {
|
||||
address: {
|
||||
operationId: 'getUserAddress',
|
||||
parameters: {
|
||||
id: '$request.path.id'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/user/:id/address', {
|
||||
schema: {
|
||||
operationId: 'getUserAddress',
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'the user identifier, as userId'
|
||||
}
|
||||
},
|
||||
required: ['id']
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
t.assert.throws(() => fastify.swagger(), new Error('Swagger (Open API v2) does not support Links. Upgrade to OpenAPI v3 (see @fastify/swagger readme)'))
|
||||
})
|
||||
|
||||
test('security headers ignored when declared in security and securityScheme', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
|
||||
fastify.get('/address1/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
description: 'api token'
|
||||
},
|
||||
somethingElse: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/address2/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authKey: {
|
||||
type: 'string',
|
||||
description: 'auth token'
|
||||
},
|
||||
somethingElse: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'id')))
|
||||
t.assert.strictEqual(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'apiKey')), undefined)
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'authKey')))
|
||||
})
|
||||
|
||||
test('security querystrings ignored when declared in security and securityScheme', async (t) => {
|
||||
t.plan(6)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: {
|
||||
securityDefinitions: {
|
||||
apiKey: {
|
||||
type: 'apiKey',
|
||||
name: 'apiKey',
|
||||
in: 'query'
|
||||
}
|
||||
},
|
||||
security: [{
|
||||
apiKey: []
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/address1/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
description: 'api token'
|
||||
},
|
||||
somethingElse: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
fastify.get('/address2/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
},
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authKey: {
|
||||
type: 'string',
|
||||
description: 'auth token'
|
||||
},
|
||||
somethingElse: {
|
||||
type: 'string',
|
||||
description: 'common field'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(typeof swaggerObject, 'object')
|
||||
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
t.assert.ok(true, 'valid swagger object')
|
||||
t.assert.ok(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'somethingElse')))
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'somethingElse')))
|
||||
t.assert.strictEqual(api.paths['/address1/{id}'].get.parameters.find(({ name }) => (name === 'apiKey')), undefined)
|
||||
t.assert.ok(api.paths['/address2/{id}'].get.parameters.find(({ name }) => (name === 'authKey')))
|
||||
})
|
||||
|
||||
test('verify generated path param definition with route prefixing', async (t) => {
|
||||
const opts = {
|
||||
schema: {}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, swaggerOption)
|
||||
await fastify.register(function (app, _, done) {
|
||||
app.get('/:userId', opts, () => {})
|
||||
|
||||
done()
|
||||
}, { prefix: '/v1' })
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/v1/{userId}'].get
|
||||
|
||||
t.assert.deepStrictEqual(definedPath.parameters, [{
|
||||
in: 'path',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true
|
||||
}])
|
||||
})
|
||||
790
backend/node_modules/@fastify/swagger/test/spec/swagger/schema.test.js
generated
vendored
Normal file
790
backend/node_modules/@fastify/swagger/test/spec/swagger/schema.test.js
generated
vendored
Normal file
@@ -0,0 +1,790 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const Swagger = require('@apidevtools/swagger-parser')
|
||||
const fastifySwagger = require('../../../index')
|
||||
const S = require('fluent-json-schema')
|
||||
|
||||
test('support file in json schema', async t => {
|
||||
const opts7 = {
|
||||
schema: {
|
||||
consumes: ['application/x-www-form-urlencoded'],
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
description: 'hello',
|
||||
type: 'string',
|
||||
contentEncoding: 'binary'
|
||||
}
|
||||
},
|
||||
required: ['hello']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.post('/', opts7, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].post
|
||||
t.assert.ok(definedPath)
|
||||
t.assert.deepStrictEqual(definedPath.parameters, [{
|
||||
in: 'formData',
|
||||
name: 'hello',
|
||||
description: 'hello',
|
||||
required: true,
|
||||
type: 'file'
|
||||
}])
|
||||
})
|
||||
|
||||
test('support response description', async t => {
|
||||
const opts8 = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
description: 'Response OK!',
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opts8, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].description, 'Response OK!')
|
||||
})
|
||||
|
||||
test('support response description fallback to its $ref', async t => {
|
||||
const opts = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
$ref: 'my-ref#'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
fastify.addSchema({
|
||||
$id: 'my-ref',
|
||||
description: 'Response OK!',
|
||||
type: 'string'
|
||||
})
|
||||
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].description, 'Response OK!')
|
||||
})
|
||||
|
||||
test('response default description', async t => {
|
||||
const opts9 = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opts9, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].description, 'Default Response')
|
||||
})
|
||||
|
||||
test('response 2xx', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
'2xx': {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].description, 'Default Response')
|
||||
t.assert.strictEqual(definedPath.responses['2XX'], undefined)
|
||||
})
|
||||
|
||||
test('response conflict 2xx and 200', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
'2xx': {
|
||||
type: 'object',
|
||||
description: '2xx'
|
||||
},
|
||||
200: {
|
||||
type: 'object',
|
||||
description: '200'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].description, '200')
|
||||
t.assert.strictEqual(definedPath.responses['2XX'], undefined)
|
||||
})
|
||||
|
||||
test('support status code 204', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
204: {
|
||||
type: 'null',
|
||||
description: 'No Content'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['204'].description, 'No Content')
|
||||
t.assert.strictEqual(definedPath.responses['204'].schema, undefined)
|
||||
})
|
||||
|
||||
test('support empty response body for different status than 204', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
204: {
|
||||
type: 'null',
|
||||
description: 'No Content'
|
||||
},
|
||||
503: {
|
||||
type: 'null',
|
||||
description: 'Service Unavailable'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
|
||||
t.assert.deepStrictEqual(definedPath.responses['204'].description, 'No Content')
|
||||
t.assert.strictEqual(definedPath.responses['204'].content, undefined)
|
||||
t.assert.strictEqual(definedPath.responses['503'].type, undefined)
|
||||
|
||||
t.assert.deepStrictEqual(definedPath.responses['503'].description, 'Service Unavailable')
|
||||
t.assert.strictEqual(definedPath.responses['503'].content, undefined)
|
||||
t.assert.strictEqual(definedPath.responses['503'].type, undefined)
|
||||
})
|
||||
|
||||
test('support response headers', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: {
|
||||
type: 'string'
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
'X-WORLD': {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].headers, opt.schema.response['200'].headers)
|
||||
t.assert.strictEqual(definedPath.responses['200'].schema.headers, undefined)
|
||||
})
|
||||
|
||||
test('response: description and x-response-description', async () => {
|
||||
const description = 'description - always that of response body, sometimes also that of response as a whole'
|
||||
const responseDescription = 'description only for the response as a whole'
|
||||
|
||||
await test('description without x-response-description doubles as response description', async t => {
|
||||
// Given a /description endpoint with only a |description| field in its response schema
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/description', {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
description,
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
await fastify.ready()
|
||||
|
||||
// When the Swagger schema is generated
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
// Then the /description endpoint uses the |description| as both the description of the Response Object as well as of its Schema Object
|
||||
const responseObject = api.paths['/description'].get.responses['200']
|
||||
t.assert.ok(responseObject)
|
||||
t.assert.strictEqual(responseObject.description, description)
|
||||
t.assert.strictEqual(responseObject.schema.description, description)
|
||||
})
|
||||
|
||||
await test('description alongside x-response-description only describes response body', async t => {
|
||||
// Given a /responseDescription endpoint that also has a |'x-response-description'| field in its response schema
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/responseDescription', {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
'x-response-description': responseDescription,
|
||||
description,
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
await fastify.ready()
|
||||
|
||||
// When the Swagger schema is generated
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
// Then the /responseDescription endpoint uses the |responseDescription| only for the Response Object and the |description| only for the Schema Object
|
||||
const responseObject = api.paths['/responseDescription'].get.responses['200']
|
||||
t.assert.ok(responseObject)
|
||||
t.assert.strictEqual(responseObject.description, responseDescription)
|
||||
t.assert.strictEqual(responseObject.schema.description, description)
|
||||
t.assert.strictEqual(responseObject.schema.responseDescription, undefined)
|
||||
})
|
||||
})
|
||||
|
||||
test('support "default" parameter', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
description: 'Expected Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
},
|
||||
default: {
|
||||
description: 'Default Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
bar: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.responses.default)), {
|
||||
description: 'Default Response',
|
||||
schema: {
|
||||
description: 'Default Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
bar: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('fluent-json-schema', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
response: {
|
||||
200: S.object()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, { swagger: true })
|
||||
fastify.get('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].get
|
||||
t.assert.deepStrictEqual(definedPath.responses['200'].description, 'Default Response')
|
||||
})
|
||||
|
||||
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()
|
||||
await fastify.register(fastifySwagger, { swagger: true })
|
||||
fastify.post('/', opt, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].post
|
||||
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.parameters[0].schema)), {
|
||||
type: 'object',
|
||||
additionalProperties: { type: 'string' }
|
||||
})
|
||||
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.responses[200])), {
|
||||
description: 'Expected Response',
|
||||
schema: {
|
||||
description: 'Expected Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object',
|
||||
additionalProperties: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('support "const" keyword', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
constantProp: { const: 'my-const' },
|
||||
constantPropNull: { const: null },
|
||||
constantPropZero: { const: 0 },
|
||||
constantPropFalse: { const: false },
|
||||
constantPropEmptyString: { const: '' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.post('/', opt, () => {})
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].post
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.parameters[0].schema)), {
|
||||
type: 'object',
|
||||
properties: {
|
||||
obj: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
constantProp: {
|
||||
enum: ['my-const']
|
||||
},
|
||||
constantPropZero: {
|
||||
enum: [0]
|
||||
},
|
||||
constantPropNull: {
|
||||
enum: [null]
|
||||
},
|
||||
constantPropFalse: {
|
||||
enum: [false]
|
||||
},
|
||||
constantPropEmptyString: {
|
||||
enum: ['']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('support "description" keyword', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
description: 'Body description',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'number'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.post('/', opt, () => { })
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/'].post
|
||||
t.assert.deepStrictEqual(definedPath.parameters[0].description, 'Body description')
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.parameters[0].schema)), {
|
||||
type: 'object',
|
||||
description: 'Body description',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'number'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('no head routes by default', async (t) => {
|
||||
const fastify = Fastify({ exposeHeadRoutes: true })
|
||||
await fastify.register(fastifySwagger, {
|
||||
routePrefix: '/docs',
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.get('/with-head', {
|
||||
schema: {
|
||||
operationId: 'with-head',
|
||||
response: {
|
||||
200: {
|
||||
description: 'Expected Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
t.assert.deepStrictEqual(
|
||||
api.paths['/with-head'].get.responses['200'].description,
|
||||
'Expected Response'
|
||||
)
|
||||
t.assert.deepStrictEqual(
|
||||
api.paths['/with-head'].head,
|
||||
undefined
|
||||
)
|
||||
})
|
||||
|
||||
test('support "exposeHeadRoutes" option', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, {
|
||||
routePrefix: '/docs',
|
||||
exposeHeadRoutes: true,
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.get('/with-head', {
|
||||
schema: {
|
||||
operationId: 'with-head',
|
||||
response: {
|
||||
200: {
|
||||
description: 'Expected Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
t.assert.deepStrictEqual(
|
||||
api.paths['/with-head'].get.responses['200'].description,
|
||||
'Expected Response'
|
||||
)
|
||||
t.assert.deepStrictEqual(
|
||||
api.paths['/with-head'].head.responses['200'].description,
|
||||
'Expected Response'
|
||||
)
|
||||
})
|
||||
|
||||
test('support "exposeHeadRoutes" option at route level', async (t) => {
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger, {
|
||||
routePrefix: '/docs',
|
||||
exposeRoute: true
|
||||
})
|
||||
|
||||
fastify.get('/with-head', {
|
||||
schema: {
|
||||
operationId: 'with-head',
|
||||
response: {
|
||||
200: {
|
||||
description: 'Expected Response',
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
config: {
|
||||
swagger: {
|
||||
exposeHeadRoute: true
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
t.assert.deepStrictEqual(
|
||||
api.paths['/with-head'].get.responses['200'].description,
|
||||
'Expected Response'
|
||||
)
|
||||
t.assert.deepStrictEqual(
|
||||
api.paths['/with-head'].head.responses['200'].description,
|
||||
'Expected Response'
|
||||
)
|
||||
})
|
||||
|
||||
test('add default properties for url params when missing schema', async t => {
|
||||
const opt = {}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.get('/:userId', opt, () => { })
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/{userId}'].get
|
||||
|
||||
t.assert.deepStrictEqual(definedPath.parameters[0], {
|
||||
type: 'string',
|
||||
required: true,
|
||||
in: 'path',
|
||||
name: 'userId'
|
||||
})
|
||||
})
|
||||
|
||||
test('add default properties for url params when missing schema.params', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bio: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.post('/:userId', opt, () => { })
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
const api = await Swagger.validate(swaggerObject)
|
||||
|
||||
const definedPath = api.paths['/{userId}'].post
|
||||
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.parameters[0].schema)), {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bio: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
t.assert.deepStrictEqual(definedPath.parameters[1], {
|
||||
in: 'path',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
required: true
|
||||
})
|
||||
})
|
||||
|
||||
test('avoid overwriting params when schema.params is provided', async t => {
|
||||
const opt = {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
},
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bio: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fastify = Fastify()
|
||||
await fastify.register(fastifySwagger)
|
||||
fastify.post('/:userId', opt, () => { })
|
||||
await fastify.ready()
|
||||
|
||||
const swaggerObject = fastify.swagger()
|
||||
|
||||
const definedPath = swaggerObject.paths['/{userId}'].post
|
||||
|
||||
t.assert.deepStrictEqual(JSON.parse(JSON.stringify(definedPath.parameters[0].schema)), {
|
||||
type: 'object',
|
||||
properties: {
|
||||
bio: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
t.assert.deepStrictEqual(definedPath.parameters[1], {
|
||||
in: 'path',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
required: true
|
||||
})
|
||||
})
|
||||
414
backend/node_modules/@fastify/swagger/test/transform.test.js
generated
vendored
Normal file
414
backend/node_modules/@fastify/swagger/test/transform.test.js
generated
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
'use strict'
|
||||
|
||||
const { test } = require('node:test')
|
||||
const Fastify = require('fastify')
|
||||
const fastifySwagger = require('..')
|
||||
const Joi = require('joi')
|
||||
const Convert = require('joi-to-json')
|
||||
|
||||
const params = Joi
|
||||
.object()
|
||||
.keys({
|
||||
property: Joi.string().required()
|
||||
})
|
||||
const opts = {
|
||||
schema: { params }
|
||||
}
|
||||
const convertible = ['params', 'body', 'querystring']
|
||||
const validTransform = ({ schema, url }) => {
|
||||
const newSchema = Object.keys(schema).reduce((transformed, key) => {
|
||||
transformed[key] = convertible.includes(key)
|
||||
? Convert(schema[key])
|
||||
: schema[key]
|
||||
return transformed
|
||||
},
|
||||
{})
|
||||
return { schema: newSchema, url }
|
||||
}
|
||||
const valid = {
|
||||
transform: validTransform
|
||||
}
|
||||
|
||||
const invalid = {
|
||||
transform: 'wrong type'
|
||||
}
|
||||
|
||||
test('transform should fail with a value other than Function', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, invalid)
|
||||
|
||||
fastify.setValidatorCompiler(({ schema }) => params.validate(schema))
|
||||
fastify.get('/example', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.throws(fastify.swagger)
|
||||
})
|
||||
|
||||
test('transform should work with a Function', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, valid)
|
||||
|
||||
fastify.setValidatorCompiler(({ schema }) => params.validate(schema))
|
||||
fastify.get('/example', opts, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('transform can access route', async (t) => {
|
||||
t.plan(5)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '1.0.0' } },
|
||||
transform: ({ route }) => {
|
||||
t.assert.ok(route)
|
||||
t.assert.strictEqual(route.method, 'GET')
|
||||
t.assert.strictEqual(route.url, '/example')
|
||||
t.assert.strictEqual(route.constraints.version, '1.0.0')
|
||||
return { schema: route.schema, url: route.url }
|
||||
}
|
||||
})
|
||||
fastify.get('/example', { constraints: { version: '1.0.0' } }, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('transform can access openapi object', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '1.0.0' } },
|
||||
transform: ({ route, openapiObject }) => {
|
||||
t.assert.ok(openapiObject)
|
||||
t.assert.strictEqual(openapiObject.openapi, '3.0.3')
|
||||
t.assert.strictEqual(openapiObject.info.version, '1.0.0')
|
||||
return {
|
||||
schema: route.schema,
|
||||
url: route.url
|
||||
}
|
||||
}
|
||||
})
|
||||
fastify.get('/example', () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('transform can access swagger object', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: { info: { version: '1.0.0' } },
|
||||
transform: ({ route, swaggerObject }) => {
|
||||
t.assert.ok(swaggerObject)
|
||||
t.assert.strictEqual(swaggerObject.swagger, '2.0')
|
||||
t.assert.strictEqual(swaggerObject.info.version, '1.0.0')
|
||||
return {
|
||||
schema: route.schema,
|
||||
url: route.url
|
||||
}
|
||||
}
|
||||
})
|
||||
fastify.get('/example', () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('transform can hide routes based on openapi version', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '2.0.0' } },
|
||||
transform: ({ schema, route, openapiObject }) => {
|
||||
const transformedSchema = Object.assign({}, schema)
|
||||
if (route?.constraints?.version !== openapiObject.info.version) transformedSchema.hide = true
|
||||
return { schema: transformedSchema, url: route.url }
|
||||
}
|
||||
})
|
||||
fastify.get('/example', { constraints: { version: '1.0.0' } }, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(openapiObject.paths['/example'], undefined)
|
||||
})
|
||||
|
||||
test('endpoint transform should fail with a value other than Function', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {})
|
||||
|
||||
fastify.setValidatorCompiler(({ schema }) => params.validate(schema))
|
||||
fastify.get('/example', {
|
||||
...opts,
|
||||
config: {
|
||||
swaggerTransform: 'wrong type'
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.throws(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform should work with a Function', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, valid)
|
||||
|
||||
fastify.setValidatorCompiler(({ schema }) => params.validate(schema))
|
||||
fastify.get('/example', {
|
||||
...opts,
|
||||
config: { swaggerTransform: validTransform }
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform can access route', async (t) => {
|
||||
t.plan(5)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '1.0.0' } }
|
||||
})
|
||||
fastify.get('/example', {
|
||||
constraints: { version: '1.0.0' },
|
||||
config: {
|
||||
swaggerTransform: ({ route }) => {
|
||||
t.assert.ok(route)
|
||||
t.assert.strictEqual(route.method, 'GET')
|
||||
t.assert.strictEqual(route.url, '/example')
|
||||
t.assert.strictEqual(route.constraints.version, '1.0.0')
|
||||
return { schema: route.schema, url: route.url }
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform can access openapi object', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '1.0.0' } }
|
||||
})
|
||||
fastify.get('/example', {
|
||||
config: {
|
||||
swaggerTransform: ({ route, openapiObject }) => {
|
||||
t.assert.ok(openapiObject)
|
||||
t.assert.strictEqual(openapiObject.openapi, '3.0.3')
|
||||
t.assert.strictEqual(openapiObject.info.version, '1.0.0')
|
||||
return {
|
||||
schema: route.schema,
|
||||
url: route.url
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform can access swagger object', async (t) => {
|
||||
t.plan(4)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: { info: { version: '1.0.0' } }
|
||||
})
|
||||
fastify.get('/example', {
|
||||
config: {
|
||||
swaggerTransform: ({ route, swaggerObject }) => {
|
||||
t.assert.ok(swaggerObject)
|
||||
t.assert.strictEqual(swaggerObject.swagger, '2.0')
|
||||
t.assert.strictEqual(swaggerObject.info.version, '1.0.0')
|
||||
return {
|
||||
schema: route.schema,
|
||||
url: route.url
|
||||
}
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform can hide routes based on openapi version', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '2.0.0' } }
|
||||
})
|
||||
fastify.get('/example', {
|
||||
constraints: { version: '1.0.0' },
|
||||
config: {
|
||||
swaggerTransform: ({ schema, route, openapiObject }) => {
|
||||
const transformedSchema = Object.assign({}, schema)
|
||||
if (route?.constraints?.version !== openapiObject.info.version) transformedSchema.hide = true
|
||||
return { schema: transformedSchema, url: route.url }
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(openapiObject.paths['/example'], undefined)
|
||||
})
|
||||
|
||||
test('endpoint transform takes precedence over global swagger transform', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: { info: { version: '1.0.0' } },
|
||||
transform: ({ schema, url }) => {
|
||||
t.assert.fail('the global transform function should be ignored')
|
||||
return validTransform({ schema, url })
|
||||
}
|
||||
|
||||
})
|
||||
fastify.get('/example', {
|
||||
config: {
|
||||
swaggerTransform: ({ schema, route }) => {
|
||||
const transformedSchema = Object.assign({}, schema)
|
||||
t.assert.ok(transformedSchema)
|
||||
return { schema: transformedSchema, url: route.url }
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform takes precedence over global openapi transform', async (t) => {
|
||||
t.plan(2)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '2.0.0' } },
|
||||
transform: ({ schema, url }) => {
|
||||
t.assert.fail('the global transform function should be ignored')
|
||||
return validTransform({ schema, url })
|
||||
}
|
||||
|
||||
})
|
||||
fastify.get('/example', {
|
||||
config: {
|
||||
swaggerTransform: ({ schema, route }) => {
|
||||
const transformedSchema = Object.assign({}, schema)
|
||||
t.assert.ok(transformedSchema)
|
||||
return { schema: transformedSchema, url: route.url }
|
||||
}
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform with value "false" disables the global swagger transform', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: { info: { version: '1.0.0' } },
|
||||
transform: () => { throw Error('should not be run') }
|
||||
})
|
||||
fastify.get('/example/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
config: {
|
||||
swaggerTransform: false
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('endpoint transform with value "false" disables the global openapi transform', async (t) => {
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '2.0.0' } },
|
||||
transform: () => { throw Error('should not be run') }
|
||||
})
|
||||
fastify.get('/example/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
config: {
|
||||
swaggerTransform: false
|
||||
}
|
||||
}, () => {})
|
||||
|
||||
await fastify.ready()
|
||||
t.assert.doesNotThrow(fastify.swagger)
|
||||
})
|
||||
|
||||
test('transformObject can modify the openapi object', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
openapi: { info: { version: '2.0.0' } },
|
||||
transformObject: ({ openapiObject }) => {
|
||||
openapiObject.info.title = 'Transformed'
|
||||
return openapiObject
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
const openapiObject = fastify.swagger()
|
||||
t.assert.strictEqual(openapiObject.info.title, 'Transformed')
|
||||
})
|
||||
|
||||
test('transformObject can modify the swagger object', async (t) => {
|
||||
t.plan(1)
|
||||
const fastify = Fastify()
|
||||
|
||||
await fastify.register(fastifySwagger, {
|
||||
swagger: { info: { version: '2.0.0' } },
|
||||
transformObject: ({ swaggerObject }) => {
|
||||
swaggerObject.info.title = 'Transformed'
|
||||
return swaggerObject
|
||||
}
|
||||
})
|
||||
|
||||
await fastify.ready()
|
||||
const swaggerObject = fastify.swagger()
|
||||
t.assert.strictEqual(swaggerObject.info.title, 'Transformed')
|
||||
})
|
||||
163
backend/node_modules/@fastify/swagger/test/util.test.js
generated
vendored
Normal file
163
backend/node_modules/@fastify/swagger/test/util.test.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
'use strict'
|
||||
|
||||
const { test, describe } = require('node:test')
|
||||
const { formatParamUrl } = require('../lib/util/format-param-url')
|
||||
const { hasParams, matchParams } = require('../lib/util/match-params')
|
||||
const { generateParamsSchema, paramName } = require('../lib/util/generate-params-schema')
|
||||
const { shouldRouteHide } = require('../lib/util/should-route-hide')
|
||||
|
||||
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/{*}'],
|
||||
['/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}']
|
||||
]
|
||||
|
||||
describe('formatParamUrl', () => {
|
||||
for (const kase of cases) {
|
||||
test(`formatParamUrl ${kase}`, (t) => {
|
||||
t.assert.strictEqual(formatParamUrl(kase[0]), kase[1])
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('hasParams function', () => {
|
||||
test('should return false for empty url', (t) => {
|
||||
const url = ''
|
||||
const result = hasParams(url)
|
||||
t.assert.strictEqual(result, false)
|
||||
})
|
||||
|
||||
test('should return true for url with parameters', (t) => {
|
||||
const url = '/example/{userId}'
|
||||
const result = hasParams(url)
|
||||
t.assert.strictEqual(result, true)
|
||||
})
|
||||
|
||||
test('should return true for url with multiple parameters', (t) => {
|
||||
const url = '/example/{userId}/{secretToken}'
|
||||
const result = hasParams(url)
|
||||
t.assert.strictEqual(result, true)
|
||||
})
|
||||
|
||||
test('should return false for url without parameters', (t) => {
|
||||
const url = '/example/path'
|
||||
const result = hasParams(url)
|
||||
t.assert.strictEqual(result, false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('matchParams function', (t) => {
|
||||
test('should return an empty array for empty url', (t) => {
|
||||
const url = ''
|
||||
const result = matchParams(url)
|
||||
t.assert.deepStrictEqual(result, [])
|
||||
})
|
||||
|
||||
test('should return an array of matched parameters', (t) => {
|
||||
const url = '/example/{userId}/{secretToken}'
|
||||
const result = matchParams(url)
|
||||
t.assert.deepStrictEqual(result, ['{userId}', '{secretToken}'])
|
||||
})
|
||||
|
||||
test('should return an empty array for url without parameters', (t) => {
|
||||
const url = '/example/path'
|
||||
const result = matchParams(url)
|
||||
t.assert.deepStrictEqual(result, [])
|
||||
})
|
||||
})
|
||||
|
||||
describe('generateParamsSchema function', (t) => {
|
||||
const urlsToShemas = [
|
||||
[
|
||||
'/example/{userId}', {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'/example/{userId}/{secretToken}', {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
userId: {
|
||||
type: 'string'
|
||||
},
|
||||
secretToken: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'/example/near/{lat}-{lng}', {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
lat: {
|
||||
type: 'string'
|
||||
},
|
||||
lng: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
test('generateParamsSchema', (t) => {
|
||||
for (const [url, expectedSchema] of urlsToShemas) {
|
||||
const result = generateParamsSchema(url)
|
||||
|
||||
t.assert.deepStrictEqual(result, expectedSchema)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('paramName function', () => {
|
||||
test('should return the captured value from the param', (t) => {
|
||||
const param = '{userId}'
|
||||
const result = paramName(param)
|
||||
t.assert.strictEqual(result, 'userId')
|
||||
})
|
||||
|
||||
test('should return the same value if there are no captures', (t) => {
|
||||
const param = 'userId'
|
||||
const result = paramName(param)
|
||||
t.assert.strictEqual(result, 'userId')
|
||||
})
|
||||
})
|
||||
|
||||
describe('shouldRouteHide', () => {
|
||||
test('shouldRouteHide should return true for hidden route', (t) => {
|
||||
t.assert.ok(shouldRouteHide({ hide: true }, {}))
|
||||
})
|
||||
|
||||
test('shouldRouteHide should return true for hideUntagged', (t) => {
|
||||
t.assert.ok(shouldRouteHide({ tags: [] }, { hideUntagged: true }))
|
||||
})
|
||||
|
||||
test('shouldRouteHide should return true for hiddenTag', (t) => {
|
||||
t.assert.ok(shouldRouteHide({ tags: ['x-test'] }, { hiddenTag: 'x-test' }))
|
||||
})
|
||||
|
||||
test('shouldRouteHide should return false for non hidden route', (t) => {
|
||||
t.assert.equal(shouldRouteHide({}, {}), false)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user