Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 140 additions & 149 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { FastifyDynamicSwaggerOptions, FastifyStaticSwaggerOptions } from '@fastify/swagger'
import type {
FastifyPluginAsync,
FastifyPluginCallback,
onRequestHookHandler,
preHandlerHookHandler,
RouteOptions,
Expand All @@ -19,9 +19,9 @@ declare module 'fastify' {
* fastify.getDocumentSources({ swaggerUI: true })
* ```
*/
getDocumentSources: (() => Array<fastifyMultipleSwagger.DocumentSource>) &
((opts: { scalar: true }) => Array<fastifyMultipleSwagger.ScalarSource>) &
((opts: { swaggerUI: true }) => Array<fastifyMultipleSwagger.SwaggerUISource>)
getDocumentSources: (() => Array<DocumentSource>) &
((opts: { scalar: true }) => Array<ScalarSource>) &
((opts: { swaggerUI: true }) => Array<SwaggerUISource>)

/**
* Returns a swagger document by documentRef
Expand All @@ -47,158 +47,149 @@ declare module 'fastify' {
}
}

type FastifyMultipleSwagger =
FastifyPluginAsync<fastifyMultipleSwagger.FastifyMultipleSwaggerOptions>
export type FastifyMultipleSwagger = FastifyPluginCallback<FastifyMultipleSwaggerOptions>

declare namespace fastifyMultipleSwagger {
export interface FastifyMultipleSwaggerOptions {
/**
* Array of document configurations or documentRef names (required)
*/
documents: Array<string | DocumentConfig>
/**
* Default documentRef name for routes without explicit documentRef
* @default undefined
*/
defaultDocumentRef?: string
/**
* Global prefix for all document routes (json and yaml)
*/
routePrefix?: `/${string}`
}

export type SwaggerOptions =
| FastifyStaticSwaggerOptions
| Omit<FastifyDynamicSwaggerOptions, 'decorator'>

export interface DocumentConfig {
/**
* Unique reference name for the Swagger document
*/
documentRef: string
/**
* URL path prefix used to match routes to this Swagger document
*
* If a route starts with this prefix, it will be associated with this document.
*
* Example:
* ```js
* urlPrefix: '/admin'
* // Routes like /admin/users or /admin/settings will be matched to this document
* urlPrefix: ['/admin', '/customer']
* // Routes like /admin/settings or /customer/profile will be matched to this document
* ```
*/
urlPrefix?: `/${string}` | Array<`/${string}`>
/**
* Determines how routes are matched to this Swagger document.
*
* @example
* ```js
* routeSelector: (routeOptions, url) => {
* return routeOptions.config?.documentRef === 'foo' && url.startsWith('/foo')
* }
* ```
*/
routeSelector?: (routeOptions: RouteOptions, url: string) => boolean
/**
* Configuration for exposing JSON/YAML routes
* Can be boolean or object with `json` and `yaml` as booleans or strings
* If `json` and `yaml` are strings, they will be used as route paths
*
* @default true
*
* @example
* ```js
* exposeRoute: {
* json: '/swagger.json',
* yaml: '/swagger.yaml',
* }
*
* exposeRoute: {
* json: '/swagger.json',
* yaml: false,
* }
* ```
*/
exposeRoute?: ExposeRouteOptions
/**
* Configuration passed to @fastify/swagger
* @see https://github.com/fastify/fastify-swagger?tab=readme-ov-file#api
*/
swaggerOptions?: SwaggerOptions
/**
* Display name for the UI providers
*/
name?: string
/**
* Additional metadata for UI providers configuration
*/
meta?: {
[key: string]: any
}
/**
* The hooks to use for this document
*
* @example
* ```js
* hooks: {
* onRequest: (req, _reply, done) => {
* console.log(req.url)
* done()
* },
* }
* ```
}
*/
hooks?: HooksOptions
}

export type ExposeRouteOptions =
| {
json?: string | boolean
yaml?: string | boolean
}
| boolean
export interface FastifyMultipleSwaggerOptions {
/**
* Array of document configurations or documentRef names (required)
*/
documents: Array<string | DocumentConfig>
/**
* Default documentRef name for routes without explicit documentRef
* @default undefined
*/
defaultDocumentRef?: string
/**
* Global prefix for all document routes (json and yaml)
*/
routePrefix?: `/${string}`
}

export type DocumentSource = {
/**
* Unique reference name for the Swagger document
*/
documentRef: string
/**
* Url for JSON route
* @default `/doc-${index}/json`
*/
json: string | null
/**
* Url for YAML route
* @default `/doc-${index}/yaml`
*/
yaml: string | null
}
export type SwaggerOptions =
| FastifyStaticSwaggerOptions
| Omit<FastifyDynamicSwaggerOptions, 'decorator'>

export type ScalarSource = {
url: string
title: string
export interface DocumentConfig {
/**
* Unique reference name for the Swagger document
*/
documentRef: string
/**
* URL path prefix used to match routes to this Swagger document
*
* If a route starts with this prefix, it will be associated with this document.
*
* Example:
* ```js
* urlPrefix: '/admin'
* // Routes like /admin/users or /admin/settings will be matched to this document
* urlPrefix: ['/admin', '/customer']
* // Routes like /admin/settings or /customer/profile will be matched to this document
* ```
*/
urlPrefix?: `/${string}` | Array<`/${string}`>
/**
* Determines how routes are matched to this Swagger document.
*
* @example
* ```js
* routeSelector: (routeOptions, url) => {
* return routeOptions.config?.documentRef === 'foo' && url.startsWith('/foo')
* }
* ```
*/
routeSelector?: (routeOptions: RouteOptions, url: string) => boolean
/**
* Configuration for exposing JSON/YAML routes
* Can be boolean or object with `json` and `yaml` as booleans or strings
* If `json` and `yaml` are strings, they will be used as route paths
*
* @default true
*
* @example
* ```js
* exposeRoute: {
* json: '/swagger.json',
* yaml: '/swagger.yaml',
* }
*
* exposeRoute: {
* json: '/swagger.json',
* yaml: false,
* }
* ```
*/
exposeRoute?: ExposeRouteOptions
/**
* Configuration passed to @fastify/swagger
* @see https://github.com/fastify/fastify-swagger?tab=readme-ov-file#api
*/
swaggerOptions?: SwaggerOptions
/**
* Display name for the UI providers
*/
name?: string
/**
* Additional metadata for UI providers configuration
*/
meta?: {
[key: string]: any
}
/**
* The hooks to use for this document
*
* @example
* ```js
* hooks: {
* onRequest: (req, _reply, done) => {
* console.log(req.url)
* done()
* },
* }
* ```
*/
hooks?: HooksOptions
}

export type SwaggerUISource = {
url: string
name: string
}
export type ExposeRouteOptions =
| {
json?: string | boolean
yaml?: string | boolean
}
| boolean

export type HooksOptions = Partial<{
onRequest?: onRequestHookHandler
preHandler?: preHandlerHookHandler
}>
export type DocumentSource = {
/**
* Unique reference name for the Swagger document
*/
documentRef: string
/**
* Url for JSON route
* @default `/doc-${index}/json`
*/
json: string | null
/**
* Url for YAML route
* @default `/doc-${index}/yaml`
*/
yaml: string | null
}

export const fastifyMultipleSwagger: FastifyMultipleSwagger
export { fastifyMultipleSwagger as default }
export type ScalarSource = {
url: string
title: string
[key: string]: any
}

declare function fastifyMultipleSwagger(
...params: Parameters<FastifyMultipleSwagger>
): ReturnType<FastifyMultipleSwagger>
export = fastifyMultipleSwagger
export type SwaggerUISource = {
url: string
name: string
}

export type HooksOptions = Partial<{
onRequest?: onRequestHookHandler
preHandler?: preHandlerHookHandler
}>

export declare const fastifyMultipleSwagger: FastifyMultipleSwagger
export default fastifyMultipleSwagger
20 changes: 10 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'

const fp = require('fastify-plugin')
const { getExposeRouteOptions, getDecoratorName } = require('./lib/utils')
import fp from 'fastify-plugin'
import routePlugin from './lib/route.js'
import swaggerPlugin from './lib/swagger.js'
import { getDecoratorName, getExposeRouteOptions } from './lib/utils.js'

/**
* @type {import('fastify').FastifyPluginCallback<import('.').FastifyMultipleSwaggerOptions>}
Expand All @@ -24,7 +24,7 @@ function plugin(fastify, opts, next) {
const swaggerDecorator = getDecoratorName(normalizedOptions.documentRef)

// Register swagger instance
fastify.register(require('./lib/swagger'), {
fastify.register(swaggerPlugin, {
...normalizedOptions,
defaultDocumentRef: opts.defaultDocumentRef,
swaggerDecorator,
Expand All @@ -34,7 +34,7 @@ function plugin(fastify, opts, next) {
const routePrefix = opts.routePrefix

// Register route for json/yaml
fastify.register(require('./lib/route'), {
fastify.register(routePlugin, {
...opts,
prefix: routePrefix,
...routeConfig,
Expand Down Expand Up @@ -115,7 +115,7 @@ function normalizeDocumentOptions(documentOptions) {

/**
* @typedef {Object} RouteConfig
* @property {import('./lib/utils').ExposeRouteOptions} exposeRoute - The expose route options
* @property {import('./lib/utils.js').ExposeRouteOptions} exposeRoute - The expose route options
* @property {string} jsonPath - The path to the JSON documentation
* @property {string} yamlPath - The path to the YAML documentation
*/
Expand Down Expand Up @@ -180,6 +180,6 @@ const fastifyMultipleSwagger = fp(plugin, {
fastify: '5.x',
name: 'fastify-multiple-swagger',
})
module.exports = fastifyMultipleSwagger
module.exports.default = fastifyMultipleSwagger
module.exports.fastifyMultipleSwagger = fastifyMultipleSwagger

export { fastifyMultipleSwagger }
export default fastifyMultipleSwagger
4 changes: 1 addition & 3 deletions lib/route.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
'use strict'

/**
* @type {import('fastify').FastifyPluginCallback<>}
*/
module.exports = (fastify, opts, next) => {
export default function routePlugin(fastify, opts, next) {
const hooks = Object.create(null)
if (opts.hooks) {
const additionalHooks = ['onRequest', 'preHandler']
Expand Down
9 changes: 4 additions & 5 deletions lib/swagger.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
'use strict'
import swagger from '@fastify/swagger'
import fp from 'fastify-plugin'

const fp = require('fastify-plugin')

module.exports = fp((fastify, opts, next) => {
export default fp((fastify, opts, next) => {
if (fastify.hasDecorator(opts.swaggerDecorator)) {
return next(new Error(`documentRef "${opts.documentRef}" already exists`))
}
Expand Down Expand Up @@ -33,7 +32,7 @@ module.exports = fp((fastify, opts, next) => {
const options = opts.swaggerOptions || {}
const { transform: transformFunc, ...swaggerOptions } = options

fastify.register(require('@fastify/swagger'), {
fastify.register(swagger, {
transform: (args) => {
// First call transform option if provided
const result = transformFunc ? transformFunc(args) : { schema: args.schema, url: args.url }
Expand Down
Loading
Loading