@orpc/openapi 1.14.6 → 2.0.0-beta.10

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.
Files changed (48) hide show
  1. package/README.md +78 -110
  2. package/dist/adapters/fetch/index.d.mts +20 -16
  3. package/dist/adapters/fetch/index.d.ts +20 -16
  4. package/dist/adapters/fetch/index.mjs +24 -8
  5. package/dist/adapters/node/index.d.mts +8 -13
  6. package/dist/adapters/node/index.d.ts +8 -13
  7. package/dist/adapters/node/index.mjs +10 -7
  8. package/dist/adapters/standard/index.d.mts +46 -16
  9. package/dist/adapters/standard/index.d.ts +46 -16
  10. package/dist/adapters/standard/index.mjs +9 -6
  11. package/dist/extensions/route.d.mts +43 -0
  12. package/dist/extensions/route.d.ts +43 -0
  13. package/dist/extensions/route.mjs +14 -0
  14. package/dist/helpers/index.d.mts +51 -0
  15. package/dist/helpers/index.d.ts +51 -0
  16. package/dist/helpers/index.mjs +39 -0
  17. package/dist/index.d.mts +111 -108
  18. package/dist/index.d.ts +111 -108
  19. package/dist/index.mjs +922 -33
  20. package/dist/plugins/index.d.mts +55 -51
  21. package/dist/plugins/index.d.ts +55 -51
  22. package/dist/plugins/index.mjs +147 -142
  23. package/dist/shared/openapi.7vgmPxca.d.ts +82 -0
  24. package/dist/shared/openapi.B2SK0ZAr.mjs +359 -0
  25. package/dist/shared/openapi.B9PQzqBn.mjs +49 -0
  26. package/dist/shared/openapi.BQzzr4-4.d.ts +299 -0
  27. package/dist/shared/openapi.BcEtAxQj.d.mts +299 -0
  28. package/dist/shared/openapi.Bt87OzTt.mjs +131 -0
  29. package/dist/shared/openapi.C7m7NAmH.d.mts +142 -0
  30. package/dist/shared/openapi.C7m7NAmH.d.ts +142 -0
  31. package/dist/shared/openapi.CTlpLuKN.mjs +318 -0
  32. package/dist/shared/openapi.CX6Ri5dP.d.mts +82 -0
  33. package/dist/shared/openapi.CYgMBSUF.d.mts +18 -0
  34. package/dist/shared/openapi.CYgMBSUF.d.ts +18 -0
  35. package/dist/shared/openapi.DmAa7YPO.mjs +275 -0
  36. package/package.json +30 -24
  37. package/dist/adapters/aws-lambda/index.d.mts +0 -20
  38. package/dist/adapters/aws-lambda/index.d.ts +0 -20
  39. package/dist/adapters/aws-lambda/index.mjs +0 -18
  40. package/dist/adapters/fastify/index.d.mts +0 -23
  41. package/dist/adapters/fastify/index.d.ts +0 -23
  42. package/dist/adapters/fastify/index.mjs +0 -18
  43. package/dist/shared/openapi.BB-W-NKv.mjs +0 -204
  44. package/dist/shared/openapi.BGy4N6eR.d.mts +0 -120
  45. package/dist/shared/openapi.BGy4N6eR.d.ts +0 -120
  46. package/dist/shared/openapi.BwdtJjDu.mjs +0 -878
  47. package/dist/shared/openapi.DwaweYRb.d.mts +0 -54
  48. package/dist/shared/openapi.DwaweYRb.d.ts +0 -54
@@ -1,86 +1,90 @@
1
- import { OpenAPI } from '@orpc/contract';
2
- import { Context, HTTPPath, Router } from '@orpc/server';
3
- import { StandardHandlerInterceptorOptions, StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
1
+ import { Context } from '@orpc/server';
2
+ import { StandardHandlerPlugin, StandardHandlerRoutingInterceptorOptions, StandardHandlerOptions } from '@orpc/server/standard';
4
3
  import { Value, Promisable } from '@orpc/shared';
5
- import { O as OpenAPIGeneratorOptions, a as OpenAPIGeneratorGenerateOptions } from '../shared/openapi.BGy4N6eR.mjs';
6
- import '@orpc/openapi-client/standard';
7
- import 'json-schema-typed/draft-2020-12';
4
+ import { ApiReferenceConfiguration } from '@scalar/api-reference';
5
+ import { StandardUrl } from '@standardserver/core';
6
+ import { SwaggerUIOptions } from 'swagger-ui';
7
+ import { a as OpenAPIDocument } from '../shared/openapi.CYgMBSUF.mjs';
8
+ import '@hey-api/spec-types';
9
+ import '@orpc/client';
8
10
 
9
- interface OpenAPIReferencePluginOptions<T extends Context> extends OpenAPIGeneratorOptions {
11
+ type OpenAPIReferenceHandlerPluginProvider = 'scalar' | 'swagger';
12
+ interface OpenAPIReferenceHandlerPluginScalarConfig extends Partial<ApiReferenceConfiguration> {
13
+ }
14
+ interface OpenAPIReferenceHandlerPluginSwaggerConfig extends Partial<Omit<SwaggerUIOptions, 'dom_id' | 'presets' | 'plugins'>> {
15
+ dom_id?: undefined | never;
16
+ presets?: undefined | `SwaggerUIBundle.${string}`[];
17
+ plugins?: undefined | `SwaggerUIBundle.${string}`[];
18
+ }
19
+ interface OpenAPIReferenceHandlerPluginOptions<T extends Context, TProvider extends OpenAPIReferenceHandlerPluginProvider> {
10
20
  /**
11
- * Options to pass to the OpenAPI generate.
12
- *
21
+ * A static or dynamic OpenAPI document to serve.
22
+ * Receives routing interceptor options when provided as a function.
13
23
  */
14
- specGenerateOptions?: Value<Promisable<OpenAPIGeneratorGenerateOptions>, [StandardHandlerInterceptorOptions<T>]>;
24
+ spec: Value<Promisable<OpenAPIDocument>, [StandardHandlerRoutingInterceptorOptions<T>]>;
15
25
  /**
16
26
  * The URL path at which to serve the OpenAPI JSON.
17
27
  *
18
28
  * @default '/spec.json'
19
29
  */
20
- specPath?: HTTPPath;
30
+ specPath?: StandardUrl;
21
31
  /**
22
- * The URL path at which to serve the API reference UI.
32
+ * The UI provider to use for rendering the API reference.
23
33
  *
24
- * @default '/'
34
+ * @default 'scalar'
25
35
  */
26
- docsPath?: HTTPPath;
36
+ provider?: TProvider;
27
37
  /**
28
- * The document title for the API reference UI.
29
- *
30
- * @default 'API Reference'
38
+ * Provider-specific configuration passed directly to the chosen UI library.
39
+ * Options differ depending on `provider`.
31
40
  */
32
- docsTitle?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
41
+ providerConfig?: undefined | (TProvider extends 'swagger' ? OpenAPIReferenceHandlerPluginSwaggerConfig : OpenAPIReferenceHandlerPluginScalarConfig);
33
42
  /**
34
- * The UI library to use for rendering the API reference.
43
+ * URL for the provider's main script bundle.
35
44
  *
36
- * @default 'scalar'
45
+ * @default 'https://cdn.jsdelivr.net/npm/@scalar/api-reference' | 'https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js'
37
46
  */
38
- docsProvider?: 'scalar' | 'swagger';
47
+ providerScriptUrl?: undefined | string;
39
48
  /**
40
- * Arbitrary configuration object for the UI.
41
- */
42
- docsConfig?: Value<Promisable<Record<string, unknown>>, [StandardHandlerInterceptorOptions<T>]>;
43
- /**
44
- * HTML to inject into the <head> of the docs page.
45
- *
46
- * @warning This is not escaped special characters, so must be used with caution to avoid XSS vulnerabilities.
49
+ * URL for the provider's stylesheet.
47
50
  *
48
- * @default ''
51
+ * @default undefined | 'https://unpkg.com/swagger-ui-dist/swagger-ui.css'
49
52
  */
50
- docsHead?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
53
+ providerCssUrl?: undefined | string;
51
54
  /**
52
- * URL of the external script bundle for the reference UI.
55
+ * The URL path at which to serve the API reference UI.
53
56
  *
54
- * - For Scalar: defaults to 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
55
- * - For Swagger UI: defaults to 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-bundle.js'
57
+ * @default '/'
56
58
  */
57
- docsScriptUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
59
+ docsPath?: StandardUrl;
58
60
  /**
59
- * URL of the external CSS bundle for the reference UI (used by Swagger UI).
61
+ * The document title for the API reference UI.
60
62
  *
61
- * @default 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui.css' (if swagger)
63
+ * @default spec.info.title
62
64
  */
63
- docsCssUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
65
+ docsTitle?: Value<Promisable<string>, [StandardHandlerRoutingInterceptorOptions<T>]>;
64
66
  /**
65
- * Override function to generate the full HTML for the docs page.
67
+ * Raw HTML to inject into the `<head>` of the API reference page.
68
+ * Useful for custom stylesheets, meta tags, or scripts.
69
+ *
70
+ * @default ''
66
71
  */
67
- renderDocsHtml?: (specUrl: string, title: string, head: string, scriptUrl: string, config: Record<string, unknown> | undefined, spec: OpenAPI.Document, docsProvider: 'scalar' | 'swagger', cssUrl: string | undefined) => string;
72
+ docsHead?: Value<Promisable<string>, [StandardHandlerRoutingInterceptorOptions<T>]>;
68
73
  }
69
- declare class OpenAPIReferencePlugin<T extends Context> implements StandardHandlerPlugin<T> {
70
- private readonly generator;
71
- private readonly specGenerateOptions;
74
+ declare class OpenAPIReferenceHandlerPlugin<T extends Context, TProvider extends OpenAPIReferenceHandlerPluginProvider> implements StandardHandlerPlugin<T> {
75
+ name: string;
76
+ private readonly spec;
72
77
  private readonly specPath;
78
+ private readonly provider;
79
+ private readonly providerConfig;
80
+ private readonly providerScriptUrl;
81
+ private readonly providerCssUrl;
73
82
  private readonly docsPath;
74
83
  private readonly docsTitle;
75
84
  private readonly docsHead;
76
- private readonly docsProvider;
77
- private readonly docsScriptUrl;
78
- private readonly docsCssUrl;
79
- private readonly docsConfig;
80
- private readonly renderDocsHtml;
81
- constructor(options?: OpenAPIReferencePluginOptions<T>);
82
- init(options: StandardHandlerOptions<T>, router: Router<any, T>): void;
85
+ constructor(options: OpenAPIReferenceHandlerPluginOptions<T, TProvider>);
86
+ init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
83
87
  }
84
88
 
85
- export { OpenAPIReferencePlugin };
86
- export type { OpenAPIReferencePluginOptions };
89
+ export { OpenAPIReferenceHandlerPlugin };
90
+ export type { OpenAPIReferenceHandlerPluginOptions, OpenAPIReferenceHandlerPluginProvider, OpenAPIReferenceHandlerPluginScalarConfig, OpenAPIReferenceHandlerPluginSwaggerConfig };
@@ -1,86 +1,90 @@
1
- import { OpenAPI } from '@orpc/contract';
2
- import { Context, HTTPPath, Router } from '@orpc/server';
3
- import { StandardHandlerInterceptorOptions, StandardHandlerPlugin, StandardHandlerOptions } from '@orpc/server/standard';
1
+ import { Context } from '@orpc/server';
2
+ import { StandardHandlerPlugin, StandardHandlerRoutingInterceptorOptions, StandardHandlerOptions } from '@orpc/server/standard';
4
3
  import { Value, Promisable } from '@orpc/shared';
5
- import { O as OpenAPIGeneratorOptions, a as OpenAPIGeneratorGenerateOptions } from '../shared/openapi.BGy4N6eR.js';
6
- import '@orpc/openapi-client/standard';
7
- import 'json-schema-typed/draft-2020-12';
4
+ import { ApiReferenceConfiguration } from '@scalar/api-reference';
5
+ import { StandardUrl } from '@standardserver/core';
6
+ import { SwaggerUIOptions } from 'swagger-ui';
7
+ import { a as OpenAPIDocument } from '../shared/openapi.CYgMBSUF.js';
8
+ import '@hey-api/spec-types';
9
+ import '@orpc/client';
8
10
 
9
- interface OpenAPIReferencePluginOptions<T extends Context> extends OpenAPIGeneratorOptions {
11
+ type OpenAPIReferenceHandlerPluginProvider = 'scalar' | 'swagger';
12
+ interface OpenAPIReferenceHandlerPluginScalarConfig extends Partial<ApiReferenceConfiguration> {
13
+ }
14
+ interface OpenAPIReferenceHandlerPluginSwaggerConfig extends Partial<Omit<SwaggerUIOptions, 'dom_id' | 'presets' | 'plugins'>> {
15
+ dom_id?: undefined | never;
16
+ presets?: undefined | `SwaggerUIBundle.${string}`[];
17
+ plugins?: undefined | `SwaggerUIBundle.${string}`[];
18
+ }
19
+ interface OpenAPIReferenceHandlerPluginOptions<T extends Context, TProvider extends OpenAPIReferenceHandlerPluginProvider> {
10
20
  /**
11
- * Options to pass to the OpenAPI generate.
12
- *
21
+ * A static or dynamic OpenAPI document to serve.
22
+ * Receives routing interceptor options when provided as a function.
13
23
  */
14
- specGenerateOptions?: Value<Promisable<OpenAPIGeneratorGenerateOptions>, [StandardHandlerInterceptorOptions<T>]>;
24
+ spec: Value<Promisable<OpenAPIDocument>, [StandardHandlerRoutingInterceptorOptions<T>]>;
15
25
  /**
16
26
  * The URL path at which to serve the OpenAPI JSON.
17
27
  *
18
28
  * @default '/spec.json'
19
29
  */
20
- specPath?: HTTPPath;
30
+ specPath?: StandardUrl;
21
31
  /**
22
- * The URL path at which to serve the API reference UI.
32
+ * The UI provider to use for rendering the API reference.
23
33
  *
24
- * @default '/'
34
+ * @default 'scalar'
25
35
  */
26
- docsPath?: HTTPPath;
36
+ provider?: TProvider;
27
37
  /**
28
- * The document title for the API reference UI.
29
- *
30
- * @default 'API Reference'
38
+ * Provider-specific configuration passed directly to the chosen UI library.
39
+ * Options differ depending on `provider`.
31
40
  */
32
- docsTitle?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
41
+ providerConfig?: undefined | (TProvider extends 'swagger' ? OpenAPIReferenceHandlerPluginSwaggerConfig : OpenAPIReferenceHandlerPluginScalarConfig);
33
42
  /**
34
- * The UI library to use for rendering the API reference.
43
+ * URL for the provider's main script bundle.
35
44
  *
36
- * @default 'scalar'
45
+ * @default 'https://cdn.jsdelivr.net/npm/@scalar/api-reference' | 'https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js'
37
46
  */
38
- docsProvider?: 'scalar' | 'swagger';
47
+ providerScriptUrl?: undefined | string;
39
48
  /**
40
- * Arbitrary configuration object for the UI.
41
- */
42
- docsConfig?: Value<Promisable<Record<string, unknown>>, [StandardHandlerInterceptorOptions<T>]>;
43
- /**
44
- * HTML to inject into the <head> of the docs page.
45
- *
46
- * @warning This is not escaped special characters, so must be used with caution to avoid XSS vulnerabilities.
49
+ * URL for the provider's stylesheet.
47
50
  *
48
- * @default ''
51
+ * @default undefined | 'https://unpkg.com/swagger-ui-dist/swagger-ui.css'
49
52
  */
50
- docsHead?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
53
+ providerCssUrl?: undefined | string;
51
54
  /**
52
- * URL of the external script bundle for the reference UI.
55
+ * The URL path at which to serve the API reference UI.
53
56
  *
54
- * - For Scalar: defaults to 'https://cdn.jsdelivr.net/npm/@scalar/api-reference'
55
- * - For Swagger UI: defaults to 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-bundle.js'
57
+ * @default '/'
56
58
  */
57
- docsScriptUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
59
+ docsPath?: StandardUrl;
58
60
  /**
59
- * URL of the external CSS bundle for the reference UI (used by Swagger UI).
61
+ * The document title for the API reference UI.
60
62
  *
61
- * @default 'https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui.css' (if swagger)
63
+ * @default spec.info.title
62
64
  */
63
- docsCssUrl?: Value<Promisable<string>, [StandardHandlerInterceptorOptions<T>]>;
65
+ docsTitle?: Value<Promisable<string>, [StandardHandlerRoutingInterceptorOptions<T>]>;
64
66
  /**
65
- * Override function to generate the full HTML for the docs page.
67
+ * Raw HTML to inject into the `<head>` of the API reference page.
68
+ * Useful for custom stylesheets, meta tags, or scripts.
69
+ *
70
+ * @default ''
66
71
  */
67
- renderDocsHtml?: (specUrl: string, title: string, head: string, scriptUrl: string, config: Record<string, unknown> | undefined, spec: OpenAPI.Document, docsProvider: 'scalar' | 'swagger', cssUrl: string | undefined) => string;
72
+ docsHead?: Value<Promisable<string>, [StandardHandlerRoutingInterceptorOptions<T>]>;
68
73
  }
69
- declare class OpenAPIReferencePlugin<T extends Context> implements StandardHandlerPlugin<T> {
70
- private readonly generator;
71
- private readonly specGenerateOptions;
74
+ declare class OpenAPIReferenceHandlerPlugin<T extends Context, TProvider extends OpenAPIReferenceHandlerPluginProvider> implements StandardHandlerPlugin<T> {
75
+ name: string;
76
+ private readonly spec;
72
77
  private readonly specPath;
78
+ private readonly provider;
79
+ private readonly providerConfig;
80
+ private readonly providerScriptUrl;
81
+ private readonly providerCssUrl;
73
82
  private readonly docsPath;
74
83
  private readonly docsTitle;
75
84
  private readonly docsHead;
76
- private readonly docsProvider;
77
- private readonly docsScriptUrl;
78
- private readonly docsCssUrl;
79
- private readonly docsConfig;
80
- private readonly renderDocsHtml;
81
- constructor(options?: OpenAPIReferencePluginOptions<T>);
82
- init(options: StandardHandlerOptions<T>, router: Router<any, T>): void;
85
+ constructor(options: OpenAPIReferenceHandlerPluginOptions<T, TProvider>);
86
+ init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
83
87
  }
84
88
 
85
- export { OpenAPIReferencePlugin };
86
- export type { OpenAPIReferencePluginOptions };
89
+ export { OpenAPIReferenceHandlerPlugin };
90
+ export type { OpenAPIReferenceHandlerPluginOptions, OpenAPIReferenceHandlerPluginProvider, OpenAPIReferenceHandlerPluginScalarConfig, OpenAPIReferenceHandlerPluginSwaggerConfig };
@@ -1,157 +1,162 @@
1
- import { stringifyJSON, once, value } from '@orpc/shared';
2
- import { O as OpenAPIGenerator } from '../shared/openapi.BwdtJjDu.mjs';
3
- import '@orpc/client';
4
- import '@orpc/client/standard';
5
- import '@orpc/contract';
6
- import '@orpc/openapi-client/standard';
7
- import '@orpc/server';
8
- import 'json-schema-typed/draft-2020-12';
1
+ import { toArray, matchesHttpPath, mergeHttpPath, getOpenTelemetryConfig, value, stringifyJSON } from '@orpc/shared';
9
2
 
10
- class OpenAPIReferencePlugin {
11
- generator;
12
- specGenerateOptions;
3
+ class OpenAPIReferenceHandlerPlugin {
4
+ name = "~openapi-reference";
5
+ spec;
13
6
  specPath;
7
+ provider;
8
+ providerConfig;
9
+ providerScriptUrl;
10
+ providerCssUrl;
14
11
  docsPath;
15
12
  docsTitle;
16
13
  docsHead;
17
- docsProvider;
18
- docsScriptUrl;
19
- docsCssUrl;
20
- docsConfig;
21
- renderDocsHtml;
22
- constructor(options = {}) {
23
- this.specGenerateOptions = options.specGenerateOptions;
14
+ constructor(options) {
15
+ this.spec = options.spec;
16
+ this.specPath = options.specPath ?? "/spec.json";
17
+ this.provider = options.provider ?? "scalar";
18
+ this.providerConfig = options.providerConfig;
19
+ this.providerScriptUrl = options.providerScriptUrl;
20
+ this.providerCssUrl = options.providerCssUrl;
21
+ this.docsTitle = options.docsTitle;
24
22
  this.docsPath = options.docsPath ?? "/";
25
- this.docsTitle = options.docsTitle ?? "API Reference";
26
- this.docsConfig = options.docsConfig ?? void 0;
27
- this.docsProvider = options.docsProvider ?? "scalar";
28
- this.docsScriptUrl = options.docsScriptUrl ?? (this.docsProvider === "swagger" ? "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js" : "https://cdn.jsdelivr.net/npm/@scalar/api-reference");
29
- this.docsCssUrl = options.docsCssUrl ?? (this.docsProvider === "swagger" ? "https://unpkg.com/swagger-ui-dist/swagger-ui.css" : void 0);
30
23
  this.docsHead = options.docsHead ?? "";
31
- this.specPath = options.specPath ?? "/spec.json";
32
- this.generator = new OpenAPIGenerator(options);
33
- const escapeHtmlEntities = (s) => s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
34
- const escapeJsonForHtml = (obj) => stringifyJSON(obj).replace(/&/g, "\\u0026").replace(/'/g, "\\u0027").replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/\//g, "\\u002F");
35
- this.renderDocsHtml = options.renderDocsHtml ?? ((specUrl, title, head, scriptUrl, config, spec, docsProvider, cssUrl) => {
36
- let body;
37
- if (docsProvider === "swagger") {
38
- const swaggerConfig = {
39
- dom_id: "#app",
40
- spec,
41
- deepLinking: true,
42
- presets: [
43
- "SwaggerUIBundle.presets.apis",
44
- "SwaggerUIBundle.presets.standalone"
45
- ],
46
- plugins: [
47
- "SwaggerUIBundle.plugins.DownloadUrl"
48
- ],
49
- ...config
50
- };
51
- body = `
52
- <body>
53
- <div id="app"></div>
24
+ }
25
+ init(options) {
26
+ return {
27
+ ...options,
28
+ routingInterceptors: [
29
+ // Run after user-provided routing interceptors so they can capture the ui/spec responses
30
+ ...toArray(options.routingInterceptors),
31
+ async ({ next, ...routingInterceptorOptions }) => {
32
+ const result = await next();
33
+ if (result.matched || routingInterceptorOptions.request.method !== "GET") {
34
+ return result;
35
+ }
36
+ const isSpecPath = matchesHttpPath(
37
+ routingInterceptorOptions.request.url,
38
+ routingInterceptorOptions.prefix ? mergeHttpPath(routingInterceptorOptions.prefix, this.specPath) : this.specPath
39
+ );
40
+ const isDocsPath = matchesHttpPath(
41
+ routingInterceptorOptions.request.url,
42
+ routingInterceptorOptions.prefix ? mergeHttpPath(routingInterceptorOptions.prefix, this.docsPath) : this.docsPath
43
+ );
44
+ if (!isSpecPath && !isDocsPath) {
45
+ return result;
46
+ }
47
+ const span = getOpenTelemetryConfig()?.trace.getActiveSpan();
48
+ const spec = await value(this.spec, routingInterceptorOptions);
49
+ if (isSpecPath) {
50
+ span?.updateName(`${routingInterceptorOptions.request.method} ${routingInterceptorOptions.request.url} (openapi spec)`);
51
+ const specFile = new File([stringifyJSON(spec)], `${spec.info.title}.json`, {
52
+ type: "application/json"
53
+ });
54
+ return { matched: true, response: { status: 200, headers: {}, body: specFile } };
55
+ }
56
+ span?.updateName(`${routingInterceptorOptions.request.method} ${routingInterceptorOptions.request.url} (${this.provider} ui)`);
57
+ const docsTitle = await value(this.docsTitle, routingInterceptorOptions) ?? spec.info.title;
58
+ const docsHead = await value(this.docsHead, routingInterceptorOptions);
59
+ let html;
60
+ if (this.provider === "swagger") {
61
+ const scriptUrl = this.providerScriptUrl ?? "https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js";
62
+ const cssUrl = this.providerCssUrl ?? "https://unpkg.com/swagger-ui-dist/swagger-ui.css";
63
+ const config = {
64
+ dom_id: "#app",
65
+ spec,
66
+ deepLinking: true,
67
+ presets: [
68
+ "SwaggerUIBundle.presets.apis",
69
+ "SwaggerUIBundle.presets.standalone"
70
+ ],
71
+ plugins: [
72
+ "SwaggerUIBundle.plugins.DownloadUrl"
73
+ ],
74
+ ...this.providerConfig
75
+ };
76
+ html = `
77
+ <!doctype html>
78
+ <html>
79
+ <head>
80
+ <meta charset="utf-8" />
81
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
82
+ <title>${escapeHtmlEntities(docsTitle)}</title>
83
+ <link rel="stylesheet" type="text/css" href="${escapeHtmlEntities(cssUrl)}" />
84
+ ${docsHead}
85
+ </head>
86
+ <body>
87
+ <div id="app"></div>
54
88
 
55
- <script src="${escapeHtmlEntities(scriptUrl)}"><\/script>
89
+ <script src="${escapeHtmlEntities(scriptUrl)}"><\/script>
56
90
 
57
- <!-- IMPORTANT: assign to a variable first to prevent ), ( in values breaking the call expression. -->
58
- <!-- IMPORTANT: escapeJsonForHtml ensures <, > cannot terminate the <\/script> tag prematurely. -->
59
- <script>
60
- const swaggerConfig = ${escapeJsonForHtml(swaggerConfig).replace(/"(SwaggerUIBundle\.[^"]+)"/g, "$1")}
91
+ <!-- IMPORTANT: assign to a variable first to prevent ), ( in values breaking the call expression. -->
92
+ <!-- IMPORTANT: escapeJsonForHtml ensures <, > cannot terminate the <\/script> tag prematurely. -->
93
+ <script>
94
+ const swaggerConfig = ${escapeJsonForHtml(config).replace(/"(SwaggerUIBundle\.[.a-zA-Z0-9]+)"/g, "$1")}
61
95
 
62
- window.onload = () => {
63
- window.ui = SwaggerUIBundle(swaggerConfig)
64
- }
65
- <\/script>
66
- </body>
67
- `;
68
- } else {
69
- const scalarConfig = {
70
- content: stringifyJSON(spec),
71
- ...config
72
- };
73
- body = `
74
- <body>
75
- <div id="app"></div>
76
-
77
- <script src="${escapeHtmlEntities(scriptUrl)}"><\/script>
78
-
79
- <!-- IMPORTANT: assign to a variable first to prevent ), ( in values breaking the call expression. -->
80
- <!-- IMPORTANT: escapeJsonForHtml ensures <, > cannot terminate the <\/script> tag prematurely. -->
81
- <script>
82
- const scalarConfig = ${escapeJsonForHtml(scalarConfig)}
96
+ window.onload = () => {
97
+ window.ui = SwaggerUIBundle(swaggerConfig)
98
+ }
99
+ <\/script>
100
+ </body>
101
+ </html>
102
+ `;
103
+ } else {
104
+ const scriptUrl = this.providerScriptUrl ?? "https://cdn.jsdelivr.net/npm/@scalar/api-reference";
105
+ const cssUrl = this.providerCssUrl;
106
+ const config = {
107
+ content: stringifyJSON(spec),
108
+ ...this.providerConfig
109
+ };
110
+ html = `
111
+ <!doctype html>
112
+ <html>
113
+ <head>
114
+ <meta charset="utf-8" />
115
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
116
+ <title>${escapeHtmlEntities(docsTitle)}</title>
117
+ ${cssUrl ? `<link rel="stylesheet" type="text/css" href="${escapeHtmlEntities(cssUrl)}" />` : ""}
118
+ ${docsHead}
119
+ </head>
120
+ <body>
121
+ <div id="app"></div>
122
+
123
+ <script src="${escapeHtmlEntities(scriptUrl)}"><\/script>
124
+
125
+ <!-- IMPORTANT: assign to a variable first to prevent ), ( in values breaking the call expression. -->
126
+ <!-- IMPORTANT: escapeJsonForHtml ensures <, > cannot terminate the <\/script> tag prematurely. -->
127
+ <script>
128
+ const scalarConfig = ${escapeJsonForHtml(config)}
83
129
 
84
- Scalar.createApiReference('#app', scalarConfig)
85
- <\/script>
86
- </body>
87
- `;
88
- }
89
- return `
90
- <!doctype html>
91
- <html>
92
- <head>
93
- <meta charset="utf-8" />
94
- <meta name="viewport" content="width=device-width, initial-scale=1" />
95
- <title>${escapeHtmlEntities(title)}</title>
96
- ${cssUrl ? `<link rel="stylesheet" type="text/css" href="${escapeHtmlEntities(cssUrl)}" />` : ""}
97
- ${head}
98
- </head>
99
- ${body}
100
- </html>
101
- `;
102
- });
103
- }
104
- init(options, router) {
105
- options.interceptors ??= [];
106
- options.interceptors.push(async (options2) => {
107
- const res = await options2.next();
108
- if (res.matched || options2.request.method !== "GET") {
109
- return res;
110
- }
111
- const prefix = options2.prefix ?? "";
112
- const requestPathname = options2.request.url.pathname.replace(/\/$/, "") || "/";
113
- const docsUrl = new URL(`${prefix}${this.docsPath}`.replace(/\/$/, ""), options2.request.url.origin);
114
- const specUrl = new URL(`${prefix}${this.specPath}`.replace(/\/$/, ""), options2.request.url.origin);
115
- const generateSpec = once(async () => {
116
- return await this.generator.generate(router, {
117
- servers: [{ url: new URL(prefix, options2.request.url.origin).toString() }],
118
- ...await value(this.specGenerateOptions, options2)
119
- });
120
- });
121
- if (requestPathname === specUrl.pathname) {
122
- const spec = await generateSpec();
123
- return {
124
- matched: true,
125
- response: {
126
- status: 200,
127
- headers: {},
128
- body: new File([stringifyJSON(spec)], "spec.json", { type: "application/json" })
129
- }
130
- };
131
- }
132
- if (requestPathname === docsUrl.pathname) {
133
- const html = this.renderDocsHtml(
134
- specUrl.toString(),
135
- await value(this.docsTitle, options2),
136
- await value(this.docsHead, options2),
137
- await value(this.docsScriptUrl, options2),
138
- await value(this.docsConfig, options2),
139
- await generateSpec(),
140
- this.docsProvider,
141
- await value(this.docsCssUrl, options2)
142
- );
143
- return {
144
- matched: true,
145
- response: {
146
- status: 200,
147
- headers: {},
148
- body: new File([html], "api-reference.html", { type: "text/html" })
130
+ Scalar.createApiReference('#app', scalarConfig)
131
+ <\/script>
132
+ </body>
133
+ </html>
134
+ `;
149
135
  }
150
- };
151
- }
152
- return res;
153
- });
136
+ const htmlBlob = new Blob([html], {
137
+ type: "text/html"
138
+ });
139
+ return {
140
+ matched: true,
141
+ response: {
142
+ status: 200,
143
+ headers: {
144
+ "content-disposition": []
145
+ // disable auto-gen header
146
+ },
147
+ body: htmlBlob
148
+ }
149
+ };
150
+ }
151
+ ]
152
+ };
154
153
  }
155
154
  }
155
+ function escapeHtmlEntities(s) {
156
+ return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
157
+ }
158
+ function escapeJsonForHtml(obj) {
159
+ return stringifyJSON(obj).replace(/&/g, "\\u0026").replace(/'/g, "\\u0027").replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/\//g, "\\u002F");
160
+ }
156
161
 
157
- export { OpenAPIReferencePlugin };
162
+ export { OpenAPIReferenceHandlerPlugin };