@scalar/fastify-api-reference 1.38.1 → 1.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @scalar/fastify-api-reference
2
2
 
3
+ ## 1.39.1
4
+
5
+ ## 1.39.0
6
+
7
+ ### Patch Changes
8
+
9
+ - [#7148](https://github.com/scalar/scalar/pull/7148) [`155bb60`](https://github.com/scalar/scalar/commit/155bb60c2e6f45ec185efa1f7898f5a1fce5778b) Thanks [@marcalexiei](https://github.com/marcalexiei)! - fix(fastify-api-reference): remove uneeded async in plugin function
10
+
11
+ - [#7127](https://github.com/scalar/scalar/pull/7127) [`68aec7d`](https://github.com/scalar/scalar/commit/68aec7d4ba85826181fa42a86a8c6b99da732c81) Thanks [@marcalexiei](https://github.com/marcalexiei)! - fix(fastify-api-reference): account from plugin prefix in redirect without trailing slash
12
+
13
+ - [#7222](https://github.com/scalar/scalar/pull/7222) [`2902396`](https://github.com/scalar/scalar/commit/290239693e6ab8ace83bc9ce24b65dccf2419e17) Thanks [@inyourtime](https://github.com/inyourtime)! - fix(fastify): correct plugin callback signature
14
+
15
+ - [#7151](https://github.com/scalar/scalar/pull/7151) [`aa217db`](https://github.com/scalar/scalar/commit/aa217db09c6449c987c70e3f31ad76e61deaceb3) Thanks [@marcalexiei](https://github.com/marcalexiei)! - fix(fastify-api-reference): use `currentUrl.pathname` instead of deprecated `request.routerPath`
16
+
17
+ - [#7225](https://github.com/scalar/scalar/pull/7225) [`9530d16`](https://github.com/scalar/scalar/commit/9530d16986bbcb30b892618979c62997b015389c) Thanks [@inyourtime](https://github.com/inyourtime)! - fix(fastify): register Scalar UI route when only sources option is provided
18
+
19
+ - Updated dependencies [[`2239843`](https://github.com/scalar/scalar/commit/2239843150ed16d1ca35b0b1f8e90cd3e35be7ce), [`9661e81`](https://github.com/scalar/scalar/commit/9661e81907d1a9b74ba30f270f2d6c8e49834cd5), [`134ff5f`](https://github.com/scalar/scalar/commit/134ff5f32aa6842696bf146c7e0817b1662905eb), [`c84b7c5`](https://github.com/scalar/scalar/commit/c84b7c5e81be83dacbdfcbf9cb1e558dfdc3faa1), [`134ff5f`](https://github.com/scalar/scalar/commit/134ff5f32aa6842696bf146c7e0817b1662905eb), [`eba18d0`](https://github.com/scalar/scalar/commit/eba18d06267a163a8f91396a66f817100ee59461), [`a821986`](https://github.com/scalar/scalar/commit/a821986332141e69d26885b2d2b32eb0c49f416c), [`e23229d`](https://github.com/scalar/scalar/commit/e23229dfbd9613b5047b28b57901f2fc5a6e33e6)]:
20
+ - @scalar/openapi-parser@0.23.0
21
+ - @scalar/openapi-types@0.5.1
22
+ - @scalar/core@0.3.21
23
+
3
24
  ## 1.38.1
4
25
 
5
26
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"fastifyApiReference.d.ts","sourceRoot":"","sources":["../src/fastifyApiReference.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAI9F,OAAO,KAAK,EAA8D,0BAA0B,EAAE,MAAM,SAAS,CAAA;AAqCrH;;GAEG;AACH,eAAO,MAAM,WAAW,KAAK,CAAA;AAS7B,QAAA,MAAM,mBAAmB,sIAwMxB,CAAA;AAED,eAAe,mBAAmB,CAAA"}
1
+ {"version":3,"file":"fastifyApiReference.d.ts","sourceRoot":"","sources":["../src/fastifyApiReference.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAI9F,OAAO,KAAK,EAA8D,0BAA0B,EAAE,MAAM,SAAS,CAAA;AA0CrH;;GAEG;AACH,eAAO,MAAM,WAAW,KAAK,CAAA;AAS7B,QAAA,MAAM,mBAAmB,sIAyMxB,CAAA;AAED,eAAe,mBAAmB,CAAA"}
@@ -21,7 +21,7 @@ const DEFAULT_CONFIGURATION = {
21
21
  _integration: "fastify"
22
22
  };
23
23
  const fastifyApiReference = fp(
24
- async (fastify, options) => {
24
+ (fastify, options, next) => {
25
25
  const { configuration: givenConfiguration } = options;
26
26
  let configuration = {
27
27
  ...DEFAULT_CONFIGURATION,
@@ -54,11 +54,11 @@ const fastifyApiReference = fp(
54
54
  }
55
55
  return void 0;
56
56
  })();
57
- if (!specSource) {
57
+ if (!specSource && !configuration.sources) {
58
58
  fastify.log.warn(
59
- "[@scalar/fastify-api-reference] You didn't provide a `content` or `url`, and @fastify/swagger could not be found. Please provide one of these options."
59
+ "[@scalar/fastify-api-reference] You didn't provide a `content`, `url`, `sources` or @fastify/swagger could not be found. Please provide one of these options."
60
60
  );
61
- return;
61
+ return next();
62
62
  }
63
63
  const fileContent = getJavaScriptFile();
64
64
  const hooks = {};
@@ -70,39 +70,39 @@ const fastifyApiReference = fp(
70
70
  }
71
71
  }
72
72
  }
73
- const getSpecFilenameSlug = async (spec) => {
73
+ const getSpecFilenameSlug = (spec) => {
74
74
  return slug(spec?.specification?.info?.title ?? "spec");
75
75
  };
76
- const openApiSpecUrlJson = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).json}`;
77
- fastify.route({
78
- method: "GET",
79
- url: openApiSpecUrlJson,
80
- // @ts-ignore We don't know whether @fastify/swagger is loaded.
81
- schema: schemaToHideRoute,
82
- ...hooks,
83
- ...options.logLevel && { logLevel: options.logLevel },
84
- async handler(_, reply) {
85
- const spec = normalize(specSource.get());
86
- const filename = await getSpecFilenameSlug(spec);
87
- const json = JSON.parse(toJson(spec));
88
- return reply.header("Content-Type", "application/json").header("Content-Disposition", `filename=${filename}.json`).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "*").send(json);
89
- }
90
- });
91
- const openApiSpecUrlYaml = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).yaml}`;
92
- fastify.route({
93
- method: "GET",
94
- url: openApiSpecUrlYaml,
95
- // @ts-ignore We don't know whether @fastify/swagger is loaded.
96
- schema: schemaToHideRoute,
97
- ...hooks,
98
- ...options.logLevel && { logLevel: options.logLevel },
99
- async handler(_, reply) {
100
- const spec = normalize(specSource.get());
101
- const filename = await getSpecFilenameSlug(spec);
102
- const yaml = toYaml(spec);
103
- return reply.header("Content-Type", "application/yaml").header("Content-Disposition", `filename=${filename}.yaml`).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "*").send(yaml);
104
- }
105
- });
76
+ if (specSource) {
77
+ const openApiSpecUrlJson = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).json}`;
78
+ fastify.route({
79
+ method: "GET",
80
+ url: openApiSpecUrlJson,
81
+ schema: schemaToHideRoute,
82
+ ...hooks,
83
+ ...options.logLevel && { logLevel: options.logLevel },
84
+ handler(_, reply) {
85
+ const spec = normalize(specSource.get());
86
+ const filename = getSpecFilenameSlug(spec);
87
+ const json = JSON.parse(toJson(spec));
88
+ return reply.header("Content-Type", "application/json").header("Content-Disposition", `filename=${filename}.json`).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "*").send(json);
89
+ }
90
+ });
91
+ const openApiSpecUrlYaml = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).yaml}`;
92
+ fastify.route({
93
+ method: "GET",
94
+ url: openApiSpecUrlYaml,
95
+ schema: schemaToHideRoute,
96
+ ...hooks,
97
+ ...options.logLevel && { logLevel: options.logLevel },
98
+ handler(_, reply) {
99
+ const spec = normalize(specSource.get());
100
+ const filename = getSpecFilenameSlug(spec);
101
+ const yaml = toYaml(spec);
102
+ return reply.header("Content-Type", "application/yaml").header("Content-Disposition", `filename=${filename}.yaml`).header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "*").send(yaml);
103
+ }
104
+ });
105
+ }
106
106
  const ignoreTrailingSlash = (
107
107
  // @ts-expect-error We're still on Fastify 4, this is introduced in Fastify 5
108
108
  fastify.initialConfig?.routerOptions?.ignoreTrailingSlash === true || fastify.initialConfig?.ignoreTrailingSlash === true
@@ -111,12 +111,12 @@ const fastifyApiReference = fp(
111
111
  fastify.route({
112
112
  method: "GET",
113
113
  url: getRoutePrefix(options.routePrefix),
114
- // @ts-ignore We don't know whether @fastify/swagger is loaded.
115
114
  schema: schemaToHideRoute,
116
115
  ...hooks,
117
116
  ...options.logLevel && { logLevel: options.logLevel },
118
- handler(_, reply) {
119
- return reply.redirect(getRoutePrefix(options.routePrefix) + "/", 302);
117
+ handler(request, reply) {
118
+ const currentUrl = new URL(request.url, `${request.protocol}://${request.hostname}`);
119
+ return reply.redirect(`${currentUrl.pathname}/`, 301);
120
120
  }
121
121
  });
122
122
  }
@@ -124,16 +124,15 @@ const fastifyApiReference = fp(
124
124
  method: "GET",
125
125
  url: `${getRoutePrefix(options.routePrefix)}/`,
126
126
  // We don't know whether @fastify/swagger is registered, but it doesn't hurt to add a schema anyway.
127
- // @ts-ignore We don't know whether @fastify/swagger is loaded.
128
127
  schema: schemaToHideRoute,
129
128
  ...hooks,
130
129
  ...options.logLevel && { logLevel: options.logLevel },
131
- handler(_, reply) {
132
- const currentUrl = new URL(_.url, `${_.protocol}://${_.hostname}`);
130
+ handler(request, reply) {
131
+ const currentUrl = new URL(request.url, `${request.protocol}://${request.hostname}`);
133
132
  if (!currentUrl.pathname.endsWith("/")) {
134
133
  return reply.redirect(`${currentUrl.pathname}/`, 301);
135
134
  }
136
- if (specSource.type !== "url") {
135
+ if (specSource && specSource.type !== "url") {
137
136
  configuration = {
138
137
  ...configuration,
139
138
  // Use a relative URL in case we're proxied
@@ -156,7 +155,6 @@ const fastifyApiReference = fp(
156
155
  method: "GET",
157
156
  url: getJavaScriptUrl(options.routePrefix),
158
157
  // We don't know whether @fastify/swagger is registered, but it doesn't hurt to add a schema anyway.
159
- // @ts-ignore We don't know whether @fastify/swagger is loaded.
160
158
  schema: schemaToHideRoute,
161
159
  ...hooks,
162
160
  ...options.logLevel && { logLevel: options.logLevel },
@@ -164,6 +162,7 @@ const fastifyApiReference = fp(
164
162
  return reply.header("Content-Type", "application/javascript; charset=utf-8").send(fileContent);
165
163
  }
166
164
  });
165
+ next();
167
166
  },
168
167
  {
169
168
  name: "@scalar/fastify-api-reference"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/fastifyApiReference.ts"],
4
- "sourcesContent": ["import { getHtmlDocument } from '@scalar/core/libs/html-rendering'\nimport { normalize, toJson, toYaml } from '@scalar/openapi-parser'\nimport type { OpenAPI } from '@scalar/openapi-types'\nimport type { FastifyBaseLogger, FastifyTypeProviderDefault, RawServerDefault } from 'fastify'\nimport fp from 'fastify-plugin'\nimport { slug } from 'github-slugger'\n\nimport type { ApiReferenceConfiguration, FastifyApiReferenceHooksOptions, FastifyApiReferenceOptions } from './types'\nimport { getJavaScriptFile } from './utils/getJavaScriptFile'\n\n/**\n * Path to the bundled Scalar JavaScript file\n */\nconst RELATIVE_JAVASCRIPT_PATH = 'js/scalar.js'\n\n// This Schema is used to hide the route from the documentation.\n// https://github.com/fastify/fastify-swagger#hide-a-route\nconst schemaToHideRoute = {\n hide: true,\n}\n\nconst getRoutePrefix = (routePrefix?: string) => {\n const prefix = routePrefix ?? '/reference'\n\n // Remove trailing slash if present\n return prefix.endsWith('/') ? prefix.slice(0, -1) : prefix\n}\n\n/**\n * Get the endpoints for the OpenAPI specification.\n */\nconst getOpenApiDocumentEndpoints = (\n openApiDocumentEndpoints: FastifyApiReferenceOptions['openApiDocumentEndpoints'],\n) => {\n const { json = '/openapi.json', yaml = '/openapi.yaml' } = openApiDocumentEndpoints ?? {}\n return { json, yaml }\n}\n\n/**\n * Get the URL for the Scalar JavaScript file.\n */\nconst getJavaScriptUrl = (routePrefix?: string) =>\n `${getRoutePrefix(routePrefix)}/${RELATIVE_JAVASCRIPT_PATH}`.replace(/\\/\\//g, '/')\n\n/**\n * The custom theme for Fastify\n */\nexport const customTheme = ''\n\n/**\n * The default configuration for Fastify\n */\nconst DEFAULT_CONFIGURATION: Partial<ApiReferenceConfiguration> = {\n _integration: 'fastify',\n}\n\nconst fastifyApiReference = fp<\n FastifyApiReferenceOptions,\n RawServerDefault,\n FastifyTypeProviderDefault,\n FastifyBaseLogger\n>(\n async (fastify, options) => {\n const { configuration: givenConfiguration } = options\n\n // Merge the defaults\n let configuration = {\n ...DEFAULT_CONFIGURATION,\n ...givenConfiguration,\n }\n\n const specSource = (() => {\n const { content, url } = configuration ?? {}\n if (content) {\n return {\n type: 'content' as const,\n get: () => {\n if (typeof content === 'function') {\n return content()\n }\n return content\n },\n }\n }\n if (url) {\n return {\n type: 'url' as const,\n get: () => url,\n }\n }\n\n // Even if @fastify/swagger is loaded, when the `decorator` option is set, the `swagger` function is not available.\n if (fastify.hasPlugin('@fastify/swagger') && typeof fastify.swagger === 'function') {\n return {\n type: 'swagger' as const,\n get: () => fastify.swagger(),\n }\n }\n\n return void 0\n })()\n\n // If no OpenAPI specification is passed and @fastify/swagger isn't loaded, show a warning.\n if (!specSource) {\n fastify.log.warn(\n \"[@scalar/fastify-api-reference] You didn't provide a `content` or `url`, and @fastify/swagger could not be found. Please provide one of these options.\",\n )\n\n return\n }\n\n // Read the JavaScript file once.\n const fileContent = getJavaScriptFile()\n\n const hooks: FastifyApiReferenceHooksOptions = {}\n if (options.hooks) {\n const additionalHooks: (keyof FastifyApiReferenceHooksOptions)[] = ['onRequest', 'preHandler']\n\n for (const hook of additionalHooks) {\n if (options.hooks[hook]) {\n hooks[hook] = options.hooks[hook]\n }\n }\n }\n\n const getSpecFilenameSlug = async (spec: OpenAPI.Document) => {\n // Same GitHub Slugger and default file name as in `@scalar/api-reference`, when generating the download\n return slug(spec?.specification?.info?.title ?? 'spec')\n }\n\n const openApiSpecUrlJson = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).json}`\n fastify.route({\n method: 'GET',\n url: openApiSpecUrlJson,\n // @ts-ignore We don't know whether @fastify/swagger is loaded.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n async handler(_, reply) {\n const spec = normalize(specSource.get())\n const filename: string = await getSpecFilenameSlug(spec)\n const json = JSON.parse(toJson(spec)) // parsing minifies the JSON\n\n return reply\n .header('Content-Type', 'application/json')\n .header('Content-Disposition', `filename=${filename}.json`)\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', '*')\n .send(json)\n },\n })\n\n const openApiSpecUrlYaml = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).yaml}`\n fastify.route({\n method: 'GET',\n url: openApiSpecUrlYaml,\n // @ts-ignore We don't know whether @fastify/swagger is loaded.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n async handler(_, reply) {\n const spec = normalize(specSource.get())\n const filename: string = await getSpecFilenameSlug(spec)\n const yaml = toYaml(spec)\n return reply\n .header('Content-Type', 'application/yaml')\n .header('Content-Disposition', `filename=${filename}.yaml`)\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', '*')\n .send(yaml)\n },\n })\n\n // Redirect route without a trailing slash to force a trailing slash:\n // We need this so the request to the JS file is relative.\n\n // With ignoreTrailingSlash: true, fastify responds to both routes anyway.\n const ignoreTrailingSlash =\n // @ts-expect-error We're still on Fastify 4, this is introduced in Fastify 5\n fastify.initialConfig?.routerOptions?.ignoreTrailingSlash === true ||\n fastify.initialConfig?.ignoreTrailingSlash === true\n\n if (!ignoreTrailingSlash && getRoutePrefix(options.routePrefix)) {\n fastify.route({\n method: 'GET',\n url: getRoutePrefix(options.routePrefix),\n // @ts-ignore We don't know whether @fastify/swagger is loaded.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(_, reply) {\n return reply.redirect(getRoutePrefix(options.routePrefix) + '/', 302)\n },\n })\n }\n\n // If no theme is passed, use the default theme.\n fastify.route({\n method: 'GET',\n url: `${getRoutePrefix(options.routePrefix)}/`,\n // We don't know whether @fastify/swagger is registered, but it doesn't hurt to add a schema anyway.\n // @ts-ignore We don't know whether @fastify/swagger is loaded.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(_, reply) {\n // Redirect if it's the route without a slash\n const currentUrl = new URL(_.url, `${_.protocol}://${_.hostname}`)\n\n if (!currentUrl.pathname.endsWith('/')) {\n return reply.redirect(`${currentUrl.pathname}/`, 301)\n }\n\n /**\n * Regardless of where we source the spec from, provide it as a URL, to have the\n * download button point to the exposed endpoint.\n * If the URL is explicitly passed, defer to that URL instead.\n */\n if (specSource.type !== 'url') {\n configuration = {\n ...configuration,\n // Use a relative URL in case we're proxied\n url: `.${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).json}`,\n }\n }\n\n // Respond with the HTML document\n return reply.header('Content-Type', 'text/html; charset=utf-8').send(\n getHtmlDocument(\n {\n // We're using the bundled JS here by default, but the user can pass a CDN URL.\n cdn: RELATIVE_JAVASCRIPT_PATH,\n ...configuration,\n },\n customTheme,\n ),\n )\n },\n })\n\n fastify.route({\n method: 'GET',\n url: getJavaScriptUrl(options.routePrefix),\n // We don't know whether @fastify/swagger is registered, but it doesn't hurt to add a schema anyway.\n // @ts-ignore We don't know whether @fastify/swagger is loaded.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(_, reply) {\n return reply.header('Content-Type', 'application/javascript; charset=utf-8').send(fileContent)\n },\n })\n },\n {\n name: '@scalar/fastify-api-reference',\n },\n)\n\nexport default fastifyApiReference\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { getHtmlDocument } from '@scalar/core/libs/html-rendering'\nimport { normalize, toJson, toYaml } from '@scalar/openapi-parser'\nimport type { OpenAPI } from '@scalar/openapi-types'\nimport type { FastifyBaseLogger, FastifyTypeProviderDefault, RawServerDefault } from 'fastify'\nimport fp from 'fastify-plugin'\nimport { slug } from 'github-slugger'\n\nimport type { ApiReferenceConfiguration, FastifyApiReferenceHooksOptions, FastifyApiReferenceOptions } from './types'\nimport { getJavaScriptFile } from './utils/getJavaScriptFile'\n\n/**\n * Path to the bundled Scalar JavaScript file\n */\nconst RELATIVE_JAVASCRIPT_PATH = 'js/scalar.js'\n\n/**\n * This Schema is used to hide the route from the documentation.\n *\n * We don't know whether `@fastify/swagger` is registered, but it doesn't hurt to add a schema anyway.\n *\n * @see https://github.com/fastify/fastify-swagger#hide-a-route\n */\nconst schemaToHideRoute = {\n hide: true,\n}\n\nconst getRoutePrefix = (routePrefix?: string) => {\n const prefix = routePrefix ?? '/reference'\n\n // Remove trailing slash if present\n return prefix.endsWith('/') ? prefix.slice(0, -1) : prefix\n}\n\n/**\n * Get the endpoints for the OpenAPI specification.\n */\nconst getOpenApiDocumentEndpoints = (\n openApiDocumentEndpoints: FastifyApiReferenceOptions['openApiDocumentEndpoints'],\n) => {\n const { json = '/openapi.json', yaml = '/openapi.yaml' } = openApiDocumentEndpoints ?? {}\n return { json, yaml }\n}\n\n/**\n * Get the URL for the Scalar JavaScript file.\n */\nconst getJavaScriptUrl = (routePrefix?: string) =>\n `${getRoutePrefix(routePrefix)}/${RELATIVE_JAVASCRIPT_PATH}`.replace(/\\/\\//g, '/')\n\n/**\n * The custom theme for Fastify\n */\nexport const customTheme = ''\n\n/**\n * The default configuration for Fastify\n */\nconst DEFAULT_CONFIGURATION: Partial<ApiReferenceConfiguration> = {\n _integration: 'fastify',\n}\n\nconst fastifyApiReference = fp<\n FastifyApiReferenceOptions,\n RawServerDefault,\n FastifyTypeProviderDefault,\n FastifyBaseLogger\n>(\n (fastify, options, next) => {\n const { configuration: givenConfiguration } = options\n\n // Merge the defaults\n let configuration = {\n ...DEFAULT_CONFIGURATION,\n ...givenConfiguration,\n }\n\n const specSource = (() => {\n const { content, url } = configuration ?? {}\n if (content) {\n return {\n type: 'content' as const,\n get: () => {\n if (typeof content === 'function') {\n return content()\n }\n return content\n },\n }\n }\n if (url) {\n return {\n type: 'url' as const,\n get: () => url,\n }\n }\n\n // Even if @fastify/swagger is loaded, when the `decorator` option is set, the `swagger` function is not available.\n if (fastify.hasPlugin('@fastify/swagger') && typeof fastify.swagger === 'function') {\n return {\n type: 'swagger' as const,\n get: () => fastify.swagger(),\n }\n }\n\n return void 0\n })()\n\n // If no OpenAPI specification is passed and @fastify/swagger isn't loaded, show a warning.\n if (!specSource && !configuration.sources) {\n fastify.log.warn(\n \"[@scalar/fastify-api-reference] You didn't provide a `content`, `url`, `sources` or @fastify/swagger could not be found. Please provide one of these options.\",\n )\n\n return next()\n }\n\n // Read the JavaScript file once.\n const fileContent = getJavaScriptFile()\n\n const hooks: FastifyApiReferenceHooksOptions = {}\n if (options.hooks) {\n const additionalHooks: (keyof FastifyApiReferenceHooksOptions)[] = ['onRequest', 'preHandler']\n\n for (const hook of additionalHooks) {\n if (options.hooks[hook]) {\n hooks[hook] = options.hooks[hook]\n }\n }\n }\n\n const getSpecFilenameSlug = (spec: OpenAPI.Document) => {\n // Same GitHub Slugger and default file name as in `@scalar/api-reference`, when generating the download\n return slug(spec?.specification?.info?.title ?? 'spec')\n }\n\n // Only expose the endpoints if specSource is available\n if (specSource) {\n const openApiSpecUrlJson = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).json}`\n fastify.route({\n method: 'GET',\n url: openApiSpecUrlJson,\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(_, reply) {\n const spec = normalize(specSource.get())\n const filename = getSpecFilenameSlug(spec)\n const json = JSON.parse(toJson(spec)) // parsing minifies the JSON\n\n return reply\n .header('Content-Type', 'application/json')\n .header('Content-Disposition', `filename=${filename}.json`)\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', '*')\n .send(json)\n },\n })\n\n const openApiSpecUrlYaml = `${getRoutePrefix(options.routePrefix)}${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).yaml}`\n fastify.route({\n method: 'GET',\n url: openApiSpecUrlYaml,\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(_, reply) {\n const spec = normalize(specSource.get())\n const filename = getSpecFilenameSlug(spec)\n const yaml = toYaml(spec)\n return reply\n .header('Content-Type', 'application/yaml')\n .header('Content-Disposition', `filename=${filename}.yaml`)\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', '*')\n .send(yaml)\n },\n })\n }\n\n // Redirect route without a trailing slash to force a trailing slash:\n // We need this so the request to the JS file is relative.\n\n // With ignoreTrailingSlash: true, fastify responds to both routes anyway.\n const ignoreTrailingSlash =\n // @ts-expect-error We're still on Fastify 4, this is introduced in Fastify 5\n fastify.initialConfig?.routerOptions?.ignoreTrailingSlash === true ||\n fastify.initialConfig?.ignoreTrailingSlash === true\n\n if (!ignoreTrailingSlash && getRoutePrefix(options.routePrefix)) {\n fastify.route({\n method: 'GET',\n url: getRoutePrefix(options.routePrefix),\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(request, reply) {\n // we are in a route without a trailing slash so redirect directly to the one with a trailing slash\n const currentUrl = new URL(request.url, `${request.protocol}://${request.hostname}`)\n return reply.redirect(`${currentUrl.pathname}/`, 301)\n },\n })\n }\n\n // If no theme is passed, use the default theme.\n fastify.route({\n method: 'GET',\n url: `${getRoutePrefix(options.routePrefix)}/`,\n // We don't know whether @fastify/swagger is registered, but it doesn't hurt to add a schema anyway.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(request, reply) {\n // Redirect if it's the route without a slash\n const currentUrl = new URL(request.url, `${request.protocol}://${request.hostname}`)\n if (!currentUrl.pathname.endsWith('/')) {\n return reply.redirect(`${currentUrl.pathname}/`, 301)\n }\n\n /**\n * Regardless of where we source the spec from, provide it as a URL, to have the\n * download button point to the exposed endpoint.\n * If the URL is explicitly passed, defer to that URL instead.\n */\n if (specSource && specSource.type !== 'url') {\n configuration = {\n ...configuration,\n // Use a relative URL in case we're proxied\n url: `.${getOpenApiDocumentEndpoints(options.openApiDocumentEndpoints).json}`,\n }\n }\n\n // Respond with the HTML document\n return reply.header('Content-Type', 'text/html; charset=utf-8').send(\n getHtmlDocument(\n {\n // We're using the bundled JS here by default, but the user can pass a CDN URL.\n cdn: RELATIVE_JAVASCRIPT_PATH,\n ...configuration,\n },\n customTheme,\n ),\n )\n },\n })\n\n fastify.route({\n method: 'GET',\n url: getJavaScriptUrl(options.routePrefix),\n // We don't know whether @fastify/swagger is registered, but it doesn't hurt to add a schema anyway.\n schema: schemaToHideRoute,\n ...hooks,\n ...(options.logLevel && { logLevel: options.logLevel }),\n handler(_, reply) {\n return reply.header('Content-Type', 'application/javascript; charset=utf-8').send(fileContent)\n },\n })\n\n next()\n },\n {\n name: '@scalar/fastify-api-reference',\n },\n)\n\nexport default fastifyApiReference\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }