@redocly/redoc-reef 0.140.0-next.7 → 0.140.0-next.8

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,28 @@
1
1
  # @redocly/redoc-reef
2
2
 
3
+ ## 0.140.0-next.8
4
+
5
+ ### Patch Changes
6
+
7
+ - dc825f9c248: Improved keyboard navigation in catalog entity version history.
8
+ The arrow keys open the version list and move between versions, the `Escape` key closes the list, and the focused version shows a focus ring.
9
+ - fee19712620: Fixed an issue where reaction-specific reasons in page feedback forms did not use the configured labels or components.
10
+ - fee19712620: Fixed an issue where the `rating` and `sentiment` page feedback forms accepted invalid email addresses without prompting users to correct them.
11
+ - fee19712620: Improved page feedback forms so that screen readers announce the comment and email fields with their labels.
12
+ - fee19712620: Fixed the `mood` form to show its reaction-specific default comment label when `comment` is not configured.
13
+ - fee19712620: Fixed an issue where the `sentiment` and `mood` page feedback forms sent the reasons a user selected for one reaction after they switched to another reaction.
14
+ - fee19712620: Fixed the **Cancel** button in the `scale` page feedback form so it uses the same translation key as other feedback forms. If you translated `feedback.settings.comment.cancel` for this button, move that translation to `feedback.cancel`.
15
+ - 5dbc15ee73c: Fixed a security vulnerability that could allow a request to the Docs MCP server to consume excessive memory.
16
+ - Updated dependencies [dc825f9c248]
17
+ - Updated dependencies [fee19712620]
18
+ - Updated dependencies [fee19712620]
19
+ - Updated dependencies [fee19712620]
20
+ - Updated dependencies [fee19712620]
21
+ - Updated dependencies [fee19712620]
22
+ - Updated dependencies [fee19712620]
23
+ - @redocly/theme@0.72.0-next.5
24
+ - @redocly/api-docs@0.5.0-next.6
25
+
3
26
  ## 0.140.0-next.7
4
27
 
5
28
  ### Minor Changes
@@ -147,6 +170,17 @@
147
170
  - Updated dependencies [cc40376e265]
148
171
  - @redocly/api-docs@0.5.0-next.0
149
172
 
173
+ ## 0.139.4
174
+
175
+ ### Patch Changes
176
+
177
+ - 3a1bc71aaf5: Fixed an issue in OpenAPI docs where the page of a schema that other schemas extend through `allOf` never finished rendering when its properties reached schemas that refer back to those extensions.
178
+ - 3a1bc71aaf5: Fixed an issue in OpenAPI docs where a page never finished rendering when two discriminator schemas listed the same variants and both declared the properties the variants inherit.
179
+ - 460fdd452f2: Fixed an issue where the Docs MCP server in projects with large configurations used too much memory and responded slowly.
180
+ - Updated dependencies [3a1bc71aaf5]
181
+ - Updated dependencies [3a1bc71aaf5]
182
+ - @redocly/api-docs@0.4.2
183
+
150
184
  ## 0.139.3
151
185
 
152
186
  ### Patch Changes
@@ -1,2 +1,2 @@
1
- export declare function useGlobalData(): import("../../types/global-data").GlobalData;
1
+ export declare function useGlobalData(): import("../../types").GlobalData;
2
2
  //# sourceMappingURL=useGlobalData.d.ts.map
@@ -1,4 +1,4 @@
1
1
  export declare function usePostMessage(): {
2
- sendMessage: (message: import("../../types/post-message").OutgoingMessage) => void;
2
+ sendMessage: (message: import("../../types").OutgoingMessage) => void;
3
3
  };
4
4
  //# sourceMappingURL=use-post-message.d.ts.map
@@ -53,6 +53,7 @@ declare function loadEnvConfig(): {
53
53
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
54
54
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
55
55
  REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED: boolean | undefined;
56
+ REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED: boolean | undefined;
56
57
  SEARCH_DEV_REINIT?: string | undefined;
57
58
  SEARCH_DEV_DEBUG: boolean;
58
59
  REDOCLY_SKIP_TYPESENSE_INDEXING: boolean;
@@ -134,6 +135,7 @@ export declare const envConfig: {
134
135
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
135
136
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
136
137
  REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED: boolean | undefined;
138
+ REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED: boolean | undefined;
137
139
  SEARCH_DEV_REINIT?: string | undefined;
138
140
  SEARCH_DEV_DEBUG: boolean;
139
141
  REDOCLY_SKIP_TYPESENSE_INDEXING: boolean;
@@ -96,6 +96,10 @@ export declare const envSchema: z.ZodObject<{
96
96
  false: "false";
97
97
  true: "true";
98
98
  }>>, z.ZodTransform<boolean | undefined, "false" | "true" | undefined>>;
99
+ REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED: z.ZodPipe<z.ZodOptional<z.ZodEnum<{
100
+ false: "false";
101
+ true: "true";
102
+ }>>, z.ZodTransform<boolean | undefined, "false" | "true" | undefined>>;
99
103
  SEARCH_DEV_REINIT: z.ZodOptional<z.ZodString>;
100
104
  SEARCH_DEV_DEBUG: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
101
105
  false: "false";
@@ -31,5 +31,9 @@ export declare const featureFlagsSchema: z.ZodObject<{
31
31
  false: "false";
32
32
  true: "true";
33
33
  }>>, z.ZodTransform<boolean | undefined, "false" | "true" | undefined>>;
34
+ REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED: z.ZodPipe<z.ZodOptional<z.ZodEnum<{
35
+ false: "false";
36
+ true: "true";
37
+ }>>, z.ZodTransform<boolean | undefined, "false" | "true" | undefined>>;
34
38
  }, z.core.$strip>;
35
39
  //# sourceMappingURL=feature-flags.d.ts.map
@@ -1 +1 @@
1
- import{z as _}from"zod";import{envBooleanStringOptional as E}from"../../utils/envs/env-boolean-string.js";const o=_.object({NEW_CATALOG_ENABLED:E(),NEW_SCORECARDS_ENABLED:E(),ENABLE_COMMENTS:_.string().optional(),REDOCLY_EXP_DISABLE_MD_VALIDATION:E(),ENABLE_SOURCE_MAPS:E(),PLAN_GATES:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_ENABLED:E(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT:_.string().optional(),REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED:E()});export{o as featureFlagsSchema};
1
+ import{z as _}from"zod";import{envBooleanStringOptional as E}from"../../utils/envs/env-boolean-string.js";const o=_.object({NEW_CATALOG_ENABLED:E(),NEW_SCORECARDS_ENABLED:E(),ENABLE_COMMENTS:_.string().optional(),REDOCLY_EXP_DISABLE_MD_VALIDATION:E(),ENABLE_SOURCE_MAPS:E(),PLAN_GATES:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_ENABLED:E(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT:_.string().optional(),REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED:E(),REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED:E()});export{o as featureFlagsSchema};
@@ -0,0 +1,22 @@
1
+ import type { RbacScopeItems } from '@redocly/config';
2
+ import type { BundledApiDefinition } from './loader.js';
3
+ /** What the download route needs to apply the API page's access rule to one definition. */
4
+ export type ApiDefinitionAccess = {
5
+ /** Content-relative source file (`customOutputRelativeFile || relativePath`). */
6
+ sourcePath: string;
7
+ /** The API's base page slug, e.g. `/apis/internal`. */
8
+ slug: string;
9
+ /** `apis.<name>.rbac`; replaces the content rule when present. */
10
+ rbac?: RbacScopeItems;
11
+ };
12
+ /**
13
+ * The key of the definition that a download of `stem` on the GraphQL route (`/_spec-gql`) or
14
+ * on a bundle route (`/_bundle`, `/_spec`) describes; `stem` is the request path after the
15
+ * route prefix without its extension (`apis/museum` for `apis/museum.yaml`), so one bundle
16
+ * answers under `.json`, `.yaml` and `.yml`. A schema and a bundle of one stem have distinct keys.
17
+ */
18
+ export declare function requestDefinitionAccessKey(isGraphql: boolean, stem: string): string;
19
+ /** The key of `definition` in the access map; undefined for one under the public static folder. */
20
+ export declare function definitionAccessKey(definition: Pick<BundledApiDefinition, 'relativePath' | 'type'>): string | undefined;
21
+ export declare function describeDefinitionAccess(definition: BundledApiDefinition, basePath: string): ApiDefinitionAccess;
22
+ //# sourceMappingURL=definition-access.d.ts.map
@@ -0,0 +1 @@
1
+ import{PUBLIC_STATIC_FOLDER as o}from"../../constants/common.js";import{removeTrailingSlash as i}from"../../../utils/url/remove-trailing-slash.js";import{resolveConfigRbac as n}from"./utils/resolve-config-rbac.js";import{replaceFileExtension as c}from"./utils/replace-file-extension.js";function s(e,r){return`${e?"graphql":"bundle"}:${r}`}function f(e){if(!e.relativePath.startsWith(o+"/"))return s(e.type==="graphql",c(e.relativePath,""))}function m(e,r){const t=n(e.config);return{sourcePath:e.customOutputRelativeFile||e.relativePath,slug:i(r),...t===void 0?{}:{rbac:t}}}export{f as definitionAccessKey,m as describeDefinitionAccess,s as requestDefinitionAccessKey};
@@ -1 +1 @@
1
- import{REDOCLY_ROUTE_RBAC as T,REDOCLY_TEAMS_RBAC as A}from"@redocly/config";import{mcpTagSchemas as rt,schemaDefinitionTag as at,markdocParser as U}from"@redocly/api-docs";import{withPathPrefix as $}from"@redocly/theme/core/utils";import{API_DOCS_TEMPLATE_ID as j,GRAPHQL_SPEC_SLUG as st,PUBLIC_RBAC_SCOPE_ITEM as N}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as it,PUBLIC_API_DEFINITIONS_FOLDER as nt}from"../../constants/common.js";import{API_DOCS_SHARED_DATA_PREFIX as k}from"../../constants/plugins/api-docs.js";import{fromCurrentDir as ct}from"../../utils/paths.js";import{normalizeRouteSlug as pt}from"../../../utils/path/normalize-route-slug.js";import{removeTrailingSlash as ut}from"../../../utils/url/remove-trailing-slash.js";import{isTranslationFallback as lt}from"../../fs/utils/is-translation-fallback.js";import{createSlugify as dt}from"../create-slugify.js";import{apiDocLoader as mt,apiDocsLoader as ft}from"./loader.js";import{getTemplatePath as V}from"./get-template-path.js";import{getDefinitionSourcePaths as gt,storeDefinitionBundles as ht}from"./store-definition-bundles.js";import{telemetryTraceStep as St}from"../../../cli/telemetry/helpers/trace-step.js";import{searchResolver as Dt}from"./search/search-resolver.js";import{getAiDocumentsStore as Pt}from"./search/get-ai-search-documents.js";import{getApiConfigByPath as yt}from"../get-api-config.js";import{getRouteSlugsForPath as It}from"../utils.js";import{collectItemRoutes as At}from"./utils/collect-item-routes.js";import{isChunkCurrent as vt}from"./utils/decorators.js";import{applyNavItemToRoot as bt}from"./utils/apply-nav-item-to-root.js";import{buildRoutesMapping as Rt}from"./utils/build-routes-mapping.js";import{buildItemPositions as _t}from"./utils/build-item-positions.js";import{resolveApiDocTitle as Ct}from"./utils/resolve-api-doc-title.js";import{resolveConfigRbac as W}from"./utils/resolve-config-rbac.js";import{relativePathToBaseSlug as Tt}from"./utils/relative-path-to-base-slug.js";import{normalizeApiVersion as wt}from"./utils/normalize-api-version.js";import{importApiDocsBuilder as Q}from"./import-api-docs-builder.js";import{envConfig as G}from"../../config/env-config.js";import{logger as Et}from"../../tools/notifiers/logger.js";const O="openapi-spec-download",kt={asyncapi:"AsyncAPI Docs",graphql:"GraphQL Docs",openapi:"OpenAPI Docs"};async function fe(){let e=[],r=new Map;const s=new WeakMap;let n=new Set,m={},b={};function Y(o,S,v){const I=s.get(o)??new Map;s.set(o,I);const D=S??"";return I.get(D)===v?!1:(I.set(D,v),!0)}return{id:"api-docs",requiredEntitlements:["openapi","asyncapi","graphql"],loaders:{"api-doc":mt,"api-docs":ft},processContent:async(o,S)=>{await St("com.redocly.build.plugin.apiDocs",async()=>{o.createRequestHandler(O,ct(import.meta.url,"./spec-download.api.js")),o.addApiRoute({slug:nt+"/*",requestHandlerId:O,httpMethod:"all",[A]:N,getStaticData:async()=>({props:{definitionSourcePaths:b}})}),o.addApiRoute({slug:it+"/*",requestHandlerId:O,httpMethod:"all",[A]:N,getStaticData:async()=>({props:{definitionSourcePaths:b}})}),o.addApiRoute({slug:st+"/*",requestHandlerId:O,httpMethod:"all",[A]:N,getStaticData:async()=>({props:{}})});const v=o.createTemplate(j,V("../../../client/templates/api-docs/template.js")),I=o.registerServerPropsGetter(j,V("./get-server-props.js")),D=await S.getConfig();r=new Map,m={};const P=await o.loadApiDocuments(S);ht(P,o.outdir),b=gt(P);const w=!!D.plugins?.some(t=>typeof t=="string"&&t.startsWith("@redocly/portal-plugin-async-api/"));w&&P.some(t=>t.type==="asyncapi")&&Et.warn("The plugin '@redocly/portal-plugin-async-api' is deprecated. Please remove it from your config to use built-in AsyncAPI docs.");const c=w?P.filter(t=>t.type!=="asyncapi"):P;e=c.map(({markdocChunks:t,relativePath:y,isVirtual:p,customOutputRelativeFile:a,realRelativePath:h})=>({chunks:t??[],relativePath:y,realRelativePath:h,isVirtual:a!=null||p}));const{buildItems:i}=await Q(o.serverOutDir),f=(await S.cache.load("content-slugs","content-slugs")).data,g=dt(f),F=t=>pt(g(t));for(const t of c){const y=t.customOutputRelativeFile||t.relativePath,p=F(y);Mt(t,p);const{items:a,store:h}=await i({type:t.type,document:t.document,options:t.options,basePath:p,markdownParser:U}),R=`${k}${t.relativePath}`,M=G.isDevelopMode?t.relativePath:void 0,u=Bt(t.document),_=u?.["x-metadata"],C=t.isVirtual?void 0:_?.apiId,L={document:t,basePath:p,sourcePath:M,apiId:C,build:{items:a,store:h}};await o.createSharedData(R,z(L,a,h));const X=W(t.config),B=!!t.options.excludeFromSearch,J=t.type==="openapi",Z=At(a,X),tt=lt(t),d=Z.map(l=>{const x=l.metadata?.seo,E={fsPath:y,templateId:v,sharedData:[{key:"apiDocsStore",id:R}],serverPropsGetterIds:[I],excludeFromSearch:B,getStaticData:Ft(l.label,x,tt),[A]:l[A]};return Object.assign(E,Lt(l.link,p)),J&&l.httpVerb&&(E.httpVerb=l.httpVerb,E.metadata={subType:"openapi-operation"}),E});if(!d.length)continue;const H=Ct(u,t.type,a),et=wt(u?.version),q={type:t.type,title:H,version:et,description:typeof u?.description=="string"?u.description:void 0,summary:typeof u?.summary=="string"?u.summary:void 0,...u?.["x-metadata"]&&typeof u["x-metadata"]=="object"?u["x-metadata"]:{}};d[0]={...d[0],metadata:q,hasClientRoutes:!0,getSidebar:(l,x)=>bt(K(a),p,x),getNavText:()=>H??kt[t.type]??"API Docs",getSearchDocuments:Dt(a,q,o.getSearchFacets,o.setSearchFacets,B,h,t.document),getAiDocumentsStore:Pt({getBuild:()=>L.build,metadata:q,document:t.document,specType:t.type,excludeFromSearch:B,basePath:p,getSearchFacets:o.getSearchFacets,markdocTags:{...rt,schemaDefinition:at}})};const ot=d[0];d[0]=d[d.length-1],d[d.length-1]=ot;for(const l of d)o.addRoute(l);if(C){const l=yt(t.config?.apis,t.realRelativePath);m[C]={[A]:l.rbac,[T]:{fsPath:y}}}r.set(R,L)}})},afterRoutesCreated:async(o,S)=>{const{buildItems:v,simplifyAstStructure:I}=await Q(o.serverOutDir),D=new Set,P=new Set;for(const{chunks:c,relativePath:i,isVirtual:f}of e){const g=`${k}${i}`,F=It(o.getAllRoutes(),i);for(const{node:t,markdown:y,pointer:p,key:a,relativePath:h}of c){const{ast:R,compoundHash:M}=await o.parseMarkdoc({input:{content:y,relativePath:h,isVirtual:f},resource:p,context:S,deps:{sharedDataIds:[`${k}${h}`],routeSlugs:F}});if(D.add(p),!(a==="graphql-docs"?t?.description?.value!==void 0:!!a&&vt(t,a,y))||!Y(t,a,M))continue;P.add(g);const _=I(R);if(a==="graphql-docs"){t.description&&(t.description.value=_);const C=`${k}${h}`;Ot(r.get(C),_)}else a&&(t[a]=_)}}const w=n.difference(D);for(const c of w)S.cache.delete(c);n=D,Object.entries(m).forEach(([c,i])=>{const f=i[T]?.fsPath;if(!f)return;const g=o.getRouteByFsPath(f)?.baseSlug;m[c]={...i,[T]:{...i[T],slug:g},slug:g}}),o.setGlobalData({apiProducts:m});for(const[c,i]of r){if(!P.has(c))continue;const{items:f,store:g}=await v({type:i.document.type,document:i.document.document,options:i.document.options,basePath:i.basePath,markdownParser:U});i.build={items:f,store:g},await o.createSharedData(c,z(i,f,g))}}}}function z({document:e,basePath:r,sourcePath:s,apiId:n},m,b){return{[A]:W(e.config),[T]:{slug:ut(r),fsPath:e.customOutputRelativeFile||e.relativePath},items:m,store:b,options:e.options,baseSlug:r,routesMapping:G.isDevelopMode?Rt(m,r):{},graphqlPositions:G.isDevelopMode&&e.type==="graphql"?_t(m,r):void 0,sourcePath:s,apiId:n}}function Ot(e,r){e?.document.type!=="graphql"||!e.document.options||(e.document.options.info={...e.document.options.info||{},description:r})}function Ft(e,r,s){return async function(n){return{...s?{isTranslationFallback:!0}:{},props:{settings:{baseUrlPath:$(n.baseSlug)},disableAutoScroll:!0,seo:{title:e,...r}}}}}function Mt(e,r){const s=e.options?.mockServer,n=$(`/_mock${Tt(e.relativePath)}`);s?.url===n&&(e.options={...e.options,mockServer:{...s,url:$(`/_mock${r}`)}})}function Lt(e,r){if(e===r)return{};const s=r==="/"?"/":`${r}/`;if(e.startsWith(s)){const n=e.slice(s.length);return n?{slugSuffix:n}:{}}return{slug:e}}function Bt(e){if(e&&typeof e=="object"&&"info"in e)return e.info}function K(e){return e.map(({content:r,items:s,...n})=>({...n,...s&&{items:K(s)}}))}export{fe as apiDocsPlugin,Lt as toRouteSlugFields};
1
+ import{REDOCLY_ROUTE_RBAC as T,REDOCLY_TEAMS_RBAC as v}from"@redocly/config";import{mcpTagSchemas as rt,schemaDefinitionTag as at,markdocParser as U}from"@redocly/api-docs";import{withPathPrefix as $}from"@redocly/theme/core/utils";import{API_DOCS_TEMPLATE_ID as j,GRAPHQL_SPEC_SLUG as st,PUBLIC_RBAC_SCOPE_ITEM as N}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as it,PUBLIC_API_DEFINITIONS_FOLDER as nt}from"../../constants/common.js";import{API_DOCS_SHARED_DATA_PREFIX as O}from"../../constants/plugins/api-docs.js";import{fromCurrentDir as ct}from"../../utils/paths.js";import{normalizeRouteSlug as pt}from"../../../utils/path/normalize-route-slug.js";import{removeTrailingSlash as ut}from"../../../utils/url/remove-trailing-slash.js";import{isTranslationFallback as lt}from"../../fs/utils/is-translation-fallback.js";import{createSlugify as dt}from"../create-slugify.js";import{apiDocLoader as mt,apiDocsLoader as ft}from"./loader.js";import{getTemplatePath as V}from"./get-template-path.js";import{storeDefinitionBundles as gt}from"./store-definition-bundles.js";import{definitionAccessKey as ht,describeDefinitionAccess as Dt}from"./definition-access.js";import{telemetryTraceStep as St}from"../../../cli/telemetry/helpers/trace-step.js";import{searchResolver as Pt}from"./search/search-resolver.js";import{getAiDocumentsStore as yt}from"./search/get-ai-search-documents.js";import{getApiConfigByPath as At}from"../get-api-config.js";import{getRouteSlugsForPath as It}from"../utils.js";import{collectItemRoutes as vt}from"./utils/collect-item-routes.js";import{isChunkCurrent as bt}from"./utils/decorators.js";import{applyNavItemToRoot as Rt}from"./utils/apply-nav-item-to-root.js";import{buildRoutesMapping as _t}from"./utils/build-routes-mapping.js";import{buildItemPositions as Ct}from"./utils/build-item-positions.js";import{resolveApiDocTitle as Tt}from"./utils/resolve-api-doc-title.js";import{resolveConfigRbac as K}from"./utils/resolve-config-rbac.js";import{relativePathToBaseSlug as wt}from"./utils/relative-path-to-base-slug.js";import{normalizeApiVersion as Et}from"./utils/normalize-api-version.js";import{importApiDocsBuilder as W}from"./import-api-docs-builder.js";import{envConfig as G}from"../../config/env-config.js";import{logger as kt}from"../../tools/notifiers/logger.js";const F="openapi-spec-download",Ot={asyncapi:"AsyncAPI Docs",graphql:"GraphQL Docs",openapi:"OpenAPI Docs"};async function he(){let e=[],r=new Map;const s=new WeakMap;let n=new Set,f={},A={};function Y(o,S,b){const I=s.get(o)??new Map;s.set(o,I);const P=S??"";return I.get(P)===b?!1:(I.set(P,b),!0)}return{id:"api-docs",requiredEntitlements:["openapi","asyncapi","graphql"],loaders:{"api-doc":mt,"api-docs":ft},processContent:async(o,S)=>{await St("com.redocly.build.plugin.apiDocs",async()=>{o.createRequestHandler(F,ct(import.meta.url,"./spec-download.api.js")),o.addApiRoute({slug:nt+"/*",requestHandlerId:F,httpMethod:"all",[v]:N,getStaticData:async()=>({props:{definitionAccess:A}})}),o.addApiRoute({slug:it+"/*",requestHandlerId:F,httpMethod:"all",[v]:N,getStaticData:async()=>({props:{definitionAccess:A}})}),o.addApiRoute({slug:st+"/*",requestHandlerId:F,httpMethod:"all",[v]:N,getStaticData:async()=>({props:{definitionAccess:A}})});const b=o.createTemplate(j,V("../../../client/templates/api-docs/template.js")),I=o.registerServerPropsGetter(j,V("./get-server-props.js")),P=await S.getConfig();r=new Map,f={};const y=await o.loadApiDocuments(S);gt(y,o.outdir),A={};const w=!!P.plugins?.some(t=>typeof t=="string"&&t.startsWith("@redocly/portal-plugin-async-api/"));w&&y.some(t=>t.type==="asyncapi")&&kt.warn("The plugin '@redocly/portal-plugin-async-api' is deprecated. Please remove it from your config to use built-in AsyncAPI docs.");const p=w?y.filter(t=>t.type!=="asyncapi"):y;e=p.map(({markdocChunks:t,relativePath:u,isVirtual:c,customOutputRelativeFile:a,realRelativePath:D})=>({chunks:t??[],relativePath:u,realRelativePath:D,isVirtual:a!=null||c}));const{buildItems:i}=await W(o.serverOutDir),g=(await S.cache.load("content-slugs","content-slugs")).data,h=dt(g),E=t=>pt(h(t));for(const t of y){const u=ht(t);if(u===void 0)continue;const c=E(t.customOutputRelativeFile||t.relativePath);A[u]=Dt(t,c)}for(const t of p){const u=t.customOutputRelativeFile||t.relativePath,c=E(u);Lt(t,c);const{items:a,store:D}=await i({type:t.type,document:t.document,options:t.options,basePath:c,markdownParser:U}),R=`${O}${t.relativePath}`,M=G.isDevelopMode?t.relativePath:void 0,l=qt(t.document),_=l?.["x-metadata"],C=t.isVirtual?void 0:_?.apiId,L={document:t,basePath:c,sourcePath:M,apiId:C,build:{items:a,store:D}};await o.createSharedData(R,Q(L,a,D));const X=K(t.config),B=!!t.options.excludeFromSearch,J=t.type==="openapi",Z=vt(a,X),tt=lt(t),m=Z.map(d=>{const x=d.metadata?.seo,k={fsPath:u,templateId:b,sharedData:[{key:"apiDocsStore",id:R}],serverPropsGetterIds:[I],excludeFromSearch:B,getStaticData:Mt(d.label,x,tt),[v]:d[v]};return Object.assign(k,Bt(d.link,c)),J&&d.httpVerb&&(k.httpVerb=d.httpVerb,k.metadata={subType:"openapi-operation"}),k});if(!m.length)continue;const H=Tt(l,t.type,a),et=Et(l?.version),q={type:t.type,title:H,version:et,description:typeof l?.description=="string"?l.description:void 0,summary:typeof l?.summary=="string"?l.summary:void 0,...l?.["x-metadata"]&&typeof l["x-metadata"]=="object"?l["x-metadata"]:{}};m[0]={...m[0],metadata:q,hasClientRoutes:!0,getSidebar:(d,x)=>Rt(z(a),c,x),getNavText:()=>H??Ot[t.type]??"API Docs",getSearchDocuments:Pt(a,q,o.getSearchFacets,o.setSearchFacets,B,D,t.document),getAiDocumentsStore:yt({getBuild:()=>L.build,metadata:q,document:t.document,specType:t.type,excludeFromSearch:B,basePath:c,getSearchFacets:o.getSearchFacets,markdocTags:{...rt,schemaDefinition:at}})};const ot=m[0];m[0]=m[m.length-1],m[m.length-1]=ot;for(const d of m)o.addRoute(d);if(C){const d=At(t.config?.apis,t.realRelativePath);f[C]={[v]:d.rbac,[T]:{fsPath:u}}}r.set(R,L)}})},afterRoutesCreated:async(o,S)=>{const{buildItems:b,simplifyAstStructure:I}=await W(o.serverOutDir),P=new Set,y=new Set;for(const{chunks:p,relativePath:i,isVirtual:g}of e){const h=`${O}${i}`,E=It(o.getAllRoutes(),i);for(const{node:t,markdown:u,pointer:c,key:a,relativePath:D}of p){const{ast:R,compoundHash:M}=await o.parseMarkdoc({input:{content:u,relativePath:D,isVirtual:g},resource:c,context:S,deps:{sharedDataIds:[`${O}${D}`],routeSlugs:E}});if(P.add(c),!(a==="graphql-docs"?t?.description?.value!==void 0:!!a&&bt(t,a,u))||!Y(t,a,M))continue;y.add(h);const _=I(R);if(a==="graphql-docs"){t.description&&(t.description.value=_);const C=`${O}${D}`;Ft(r.get(C),_)}else a&&(t[a]=_)}}const w=n.difference(P);for(const p of w)S.cache.delete(p);n=P,Object.entries(f).forEach(([p,i])=>{const g=i[T]?.fsPath;if(!g)return;const h=o.getRouteByFsPath(g)?.baseSlug;f[p]={...i,[T]:{...i[T],slug:h},slug:h}}),o.setGlobalData({apiProducts:f});for(const[p,i]of r){if(!y.has(p))continue;const{items:g,store:h}=await b({type:i.document.type,document:i.document.document,options:i.document.options,basePath:i.basePath,markdownParser:U});i.build={items:g,store:h},await o.createSharedData(p,Q(i,g,h))}}}}function Q({document:e,basePath:r,sourcePath:s,apiId:n},f,A){return{[v]:K(e.config),[T]:{slug:ut(r),fsPath:e.customOutputRelativeFile||e.relativePath},items:f,store:A,options:e.options,baseSlug:r,routesMapping:G.isDevelopMode?_t(f,r):{},graphqlPositions:G.isDevelopMode&&e.type==="graphql"?Ct(f,r):void 0,sourcePath:s,apiId:n}}function Ft(e,r){e?.document.type!=="graphql"||!e.document.options||(e.document.options.info={...e.document.options.info||{},description:r})}function Mt(e,r,s){return async function(n){return{...s?{isTranslationFallback:!0}:{},props:{settings:{baseUrlPath:$(n.baseSlug)},disableAutoScroll:!0,seo:{title:e,...r}}}}}function Lt(e,r){const s=e.options?.mockServer,n=$(`/_mock${wt(e.relativePath)}`);s?.url===n&&(e.options={...e.options,mockServer:{...s,url:$(`/_mock${r}`)}})}function Bt(e,r){if(e===r)return{};const s=r==="/"?"/":`${r}/`;if(e.startsWith(s)){const n=e.slice(s.length);return n?{slugSuffix:n}:{}}return{slug:e}}function qt(e){if(e&&typeof e=="object"&&"info"in e)return e.info}function z(e){return e.map(({content:r,items:s,...n})=>({...n,...s&&{items:z(s)}}))}export{he as apiDocsPlugin,Bt as toRouteSlugFields};
@@ -1 +1 @@
1
- import*as F from"node:path";import{findFirstBinding as P,markdocParser as _}from"@redocly/api-docs";import{combineUrls as i}from"@redocly/theme/core/openapi";import{withPathPrefix as k}from"@redocly/theme/core/utils";import{GRAPHQL_SPEC_SLUG as w}from"../../../constants/common.js";import{PUBLIC_API_DEFINITIONS_FOLDER as f}from"../../constants/common.js";import{envConfig as L}from"../../config/env-config.js";import{deepMerge as M}from"../../../utils/object/deep-merge.js";import{normalizeFeedbackOptions as A}from"./utils/normalize-feedback-options.js";import{replaceFileExtension as g}from"./utils/replace-file-extension.js";import{relativePathToBaseSlug as B}from"./utils/relative-path-to-base-slug.js";const R={tags:{},nodes:{},components:{}};function D(o,r){if(!(o?.off!==!0))return o;const t=B(r);return{url:k(`/_mock${t}`),position:"first",description:"Mock server",...o}}function I(o,r){return(r==="graphql"?[i(w,`${g(o,F.posix.extname(o))}?download`)]:[i(f,`${g(o,".json")}?download`),i(f,`${g(o,".yaml")}?download`)]).map(t=>({url:k(t)}))}function j(o,r,m){const{rootConfig:t,config:c,apiConfig:s,mergedConfig:e,relativePath:l}=m,a=M(t?.[o]||{},c[o]||{},s[o]||s.theme?.[o]||{}),b=r["x-feedback"]||a.feedback||c.feedback,S=!!e[o]?.excludeFromSearch||!!e.theme?.[o]?.excludeFromSearch||!!t?.[o]?.excludeFromSearch||!!t?.theme?.[o]?.excludeFromSearch,x=e.rbac||s.rbac,p=A(b),u=c.metadata,C={...p&&{feedback:p},mockServer:D(e?.mockServer||t?.mockServer,l),disableRouter:!0,downloadUrls:a.downloadUrls||I(l,o),excludeFromSearch:S,rbac:x,markdownParser:_,replayFeatures:{graphql:L.REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED??!1}};let d;if(o==="graphql"){const n=a;d={title:n.info?.title,...u,...n.metadata??{}}}else{const n=r.info,E=n?.["x-metadata"];d={title:n?.title,description:n?.description,...o==="openapi"&&{summary:n?.summary},...u,...E}}o==="openapi"&&a.showSchemaCatalogLinks&&(r["x-schema-catalog-link"]=i(f,l));const O=a.markdocOptions??R,h={...a,...C,specType:o,markdocOptions:O,metadata:d};return o==="asyncapi"&&(h.protocol=P(r)??void 0),h}export{I as buildDownloadUrls,j as createOptions};
1
+ import*as O from"node:path";import{findFirstBinding as A,markdocParser as F}from"@redocly/api-docs";import{combineUrls as i}from"@redocly/theme/core/openapi";import{withPathPrefix as k}from"@redocly/theme/core/utils";import{GRAPHQL_SPEC_SLUG as L}from"../../../constants/common.js";import{PUBLIC_API_DEFINITIONS_FOLDER as f}from"../../constants/common.js";import{envConfig as E}from"../../config/env-config.js";import{deepMerge as w}from"../../../utils/object/deep-merge.js";import{normalizeFeedbackOptions as B}from"./utils/normalize-feedback-options.js";import{replaceFileExtension as p}from"./utils/replace-file-extension.js";import{relativePathToBaseSlug as M}from"./utils/relative-path-to-base-slug.js";const R={tags:{},nodes:{},components:{}};function D(o,r){if(!(o?.off!==!0))return o;const a=M(r);return{url:k(`/_mock${a}`),position:"first",description:"Mock server",...o}}function I(o,r){return(r==="graphql"?[i(L,`${p(o,O.posix.extname(o))}?download`)]:[i(f,`${p(o,".json")}?download`),i(f,`${p(o,".yaml")}?download`)]).map(a=>({url:k(a)}))}function X(o,r,m){const{rootConfig:a,config:s,apiConfig:c,mergedConfig:e,relativePath:l}=m,n=w(a?.[o]||{},s[o]||{},c[o]||c.theme?.[o]||{}),S=r["x-feedback"]||n.feedback||s.feedback,b=!!e[o]?.excludeFromSearch||!!e.theme?.[o]?.excludeFromSearch||!!a?.[o]?.excludeFromSearch||!!a?.theme?.[o]?.excludeFromSearch,_=e.rbac||c.rbac,g=B(S),u=s.metadata,x={...g&&{feedback:g},mockServer:D(e?.mockServer||a?.mockServer,l),disableRouter:!0,downloadUrls:n.downloadUrls||I(l,o),excludeFromSearch:b,rbac:_,markdownParser:F,replayFeatures:{graphql:E.REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED??!1,asyncapi:E.REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED??!1}};let d;if(o==="graphql"){const t=n;d={title:t.info?.title,...u,...t.metadata??{}}}else{const t=r.info,P=t?.["x-metadata"];d={title:t?.title,description:t?.description,...o==="openapi"&&{summary:t?.summary},...u,...P}}o==="openapi"&&n.showSchemaCatalogLinks&&(r["x-schema-catalog-link"]=i(f,l));const C=n.markdocOptions??R,h={...n,...x,specType:o,markdocOptions:C,metadata:d};return o==="asyncapi"&&(h.protocol=A(r)??void 0),h}export{I as buildDownloadUrls,X as createOptions};
@@ -1 +1 @@
1
- import e from"node:path";import{existsSync as f}from"node:fs";import{readFile as w}from"node:fs/promises";import g from"js-yaml";import{withoutPathPrefix as T}from"@redocly/theme/core/utils";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_API_DEFINITIONS_FOLDER as A}from"../../constants/common.js";import{GRAPHQL_SPEC_SLUG as U}from"../../../constants/common.js";import{canDownloadApiDefinition as B,filterDataByAccessDeep as G}from"../../utils/rbac.js";import{API_DOWNLOAD_PREFIXES as W}from"../../utils/is-api-download-link.js";import{decodeRequestPath as X}from"../../utils/decode-request-path.js";import{replaceFileExtension as $}from"./utils/replace-file-extension.js";const v=[".json",".yaml",".yml"],H=[".graphql",".gql"];function F(r,o){const t=e.parse(r);return e.join(t.dir,t.name+o)}const J=async(r,o,t)=>{const{isAuthenticated:c,teams:d,claims:{email:m}}=o.user,_=new URL(r.url),n=X(T(_.pathname));if(n===void 0||n.endsWith("/"))return new Response("Bad Request",{status:400});const i=W.find(a=>n.startsWith(`${a}/`));if(i===void 0)return new Response("Not found",{status:404});const p=i===U,s=n.slice(i.length),l=e.extname(s);if(!(p?H:v).includes(l))return new Response("Not found",{status:404});const{rbac:h={},requiresLogin:P=!1}=o.config.access||{},y=t.props?.definitionSourcePaths??{},E=p?void 0:y[$(s.slice(1),"")],D=E?`${i}/${E}`:n;if(!B(D,h,P,{isAuthenticated:c,email:m,teams:d}))return new Response("Unauthorized",{status:c?403:401});const u=t.props?.outdir||"";if(p){const a=e.join(u,A,s);if(!f(a))return new Response("Not found",{status:404});const j=await w(a,"utf-8");return new Response(j,{headers:{"Content-Type":"application/graphql"}})}const R=e.join(u,A,F(s,".json")),N=e.join(u,C,F(s,".json")),S=f(R),x=f(N);if(!S&&!x)return new Response("Not found",{status:404});const O=await w(S?R:N,"utf-8"),L=JSON.parse(O),I=G(L,{isAuthenticated:c,email:m,teams:d},h,P),q=l===".yaml"?g.dump(I):JSON.stringify(I,null,2);return new Response(q,{headers:{"Content-Type":l===".yaml"?"application/yaml":"application/json"}})};var oe=J;export{oe as default};
1
+ import e from"node:path";import{existsSync as u}from"node:fs";import{readFile as I}from"node:fs/promises";import L from"js-yaml";import{withoutPathPrefix as j}from"@redocly/theme/core/utils";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as g,PUBLIC_API_DEFINITIONS_FOLDER as w}from"../../constants/common.js";import{GRAPHQL_SPEC_SLUG as T}from"../../../constants/common.js";import{requestDefinitionAccessKey as C}from"./definition-access.js";import{canDownloadApiDefinition as U,filterDataByAccessDeep as B}from"../../utils/rbac.js";import{API_DOWNLOAD_PREFIXES as G}from"../../utils/is-api-download-link.js";import{decodeRequestPath as W}from"../../utils/decode-request-path.js";import{replaceFileExtension as X}from"./utils/replace-file-extension.js";const v=[".json",".yaml",".yml"],H=[".graphql",".gql"];function F(r,o){const t=e.parse(r);return e.join(t.dir,t.name+o)}const J=async(r,o,t)=>{const{isAuthenticated:a,teams:m,claims:{email:d}}=o.user,S=new URL(r.url),n=W(j(S.pathname));if(n===void 0||n.endsWith("/"))return new Response("Bad Request",{status:400});const c=G.find(i=>n.startsWith(`${i}/`));if(c===void 0)return new Response("Not found",{status:404});const p=c===T,s=n.slice(c.length),l=e.extname(s);if(!(p?H:v).includes(l))return new Response("Not found",{status:404});const{rbac:h={},requiresLogin:P=!1}=o.config.access||{},y=(t.props?.definitionAccess??{})[C(p,X(s.slice(1),""))];if(!U(n,h,P,{isAuthenticated:a,email:d,teams:m},y))return new Response("Unauthorized",{status:a?403:401});const f=t.props?.outdir||"";if(p){const i=e.join(f,w,s);if(!u(i))return new Response("Not found",{status:404});const q=await I(i,"utf-8");return new Response(q,{headers:{"Content-Type":"application/graphql"}})}const E=e.join(f,w,F(s,".json")),R=e.join(f,g,F(s,".json")),A=u(E),D=u(R);if(!A&&!D)return new Response("Not found",{status:404});const _=await I(A?E:R,"utf-8"),x=JSON.parse(_),N=B(x,{isAuthenticated:a,email:d,teams:m},h,P),O=l===".yaml"?L.dump(N):JSON.stringify(N,null,2);return new Response(O,{headers:{"Content-Type":l===".yaml"?"application/yaml":"application/json"}})};var ie=J;export{ie as default};
@@ -1,9 +1,3 @@
1
1
  import type { BundledApiDefinition } from './loader.js';
2
- /**
3
- * Source file of each OpenAPI/AsyncAPI bundle, keyed by the bundle path without its extension
4
- * (`apis/museum` for `apis/museum.yaml`): the download route serves one bundle under `.json`,
5
- * `.yaml` and `.yml`, and access rules name the source file.
6
- */
7
- export declare function getDefinitionSourcePaths(definitions: BundledApiDefinition[]): Record<string, string>;
8
2
  export declare function storeDefinitionBundles(definitions: BundledApiDefinition[], outDir: string): void;
9
3
  //# sourceMappingURL=store-definition-bundles.d.ts.map
@@ -1 +1 @@
1
- import{writeFileSync as h}from"fs";import m from"path";import{print as u}from"graphql";import{PUBLIC_API_DEFINITIONS_FOLDER as d,PUBLIC_STATIC_FOLDER as a}from"../../constants/common.js";import{logger as g}from"../../tools/notifiers/logger.js";import{ensureDir as P}from"../../utils/fs.js";import{replaceFileExtension as l}from"./utils/replace-file-extension.js";const f=new Map;function _(o){const t={};for(const{relativePath:i,type:n}of o)n==="graphql"||i.startsWith(a+"/")||(t[l(i,"")]=i);return t}function E(o,t){const i=d.slice(1);try{for(const n of o){const{document:s,relativePath:e,hash:r,type:p}=n;if(f.get(e)!==r){if(p==="graphql"){c({outDir:t,definitionFolder:i,relativePath:e,definitionString:u(s)}),f.set(e,r);continue}if(e.startsWith(a+"/")){c({outDir:t,definitionFolder:".",relativePath:e.replace(a+"/",""),definitionString:JSON.stringify(s,null,2)}),f.set(e,r);continue}c({outDir:t,definitionFolder:i,relativePath:l(e,".json"),definitionString:JSON.stringify(s,null,2)}),f.set(e,r)}}}catch(n){g.error("failed to store definition bundles",n)}}function c({outDir:o,definitionString:t,relativePath:i,definitionFolder:n}){h(P(m.resolve(o,`${n}/${i}`)),t,"utf8")}export{_ as getDefinitionSourcePaths,E as storeDefinitionBundles};
1
+ import{writeFileSync as m}from"fs";import p from"path";import{print as d}from"graphql";import{PUBLIC_API_DEFINITIONS_FOLDER as h,PUBLIC_STATIC_FOLDER as a}from"../../constants/common.js";import{logger as u}from"../../tools/notifiers/logger.js";import{ensureDir as g}from"../../utils/fs.js";import{replaceFileExtension as S}from"./utils/replace-file-extension.js";const r=new Map;function D(f,t){const n=h.slice(1);try{for(const e of f){const{document:s,relativePath:i,hash:o,type:c}=e;if(r.get(i)!==o){if(c==="graphql"){l({outDir:t,definitionFolder:n,relativePath:i,definitionString:d(s)}),r.set(i,o);continue}if(i.startsWith(a+"/")){l({outDir:t,definitionFolder:".",relativePath:i.replace(a+"/",""),definitionString:JSON.stringify(s,null,2)}),r.set(i,o);continue}l({outDir:t,definitionFolder:n,relativePath:S(i,".json"),definitionString:JSON.stringify(s,null,2)}),r.set(i,o)}}}catch(e){u.error("failed to store definition bundles",e)}}function l({outDir:f,definitionString:t,relativePath:n,definitionFolder:e}){m(g(p.resolve(f,`${e}/${n}`)),t,"utf8")}export{D as storeDefinitionBundles};
@@ -1 +1 @@
1
- import{logger as A}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as N}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as M,getInternalOrigin as L}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as B,DEFAULT_ANONYMOUS_VISITOR_TEAM as H,RbacFeatures as j}from"../../../../constants/common.js";import{isObject as V}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as $}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as G}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as J}from"@modelcontextprotocol/server";import{createDocsMcpServer as K}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as Y,filterGraphqlDescriptionsByRbac as z}from"../utils.js";import{userSubject as W}from"../gateway-mcp/subject.js";import{ipRateLimitKey as X}from"../gateway-mcp/rate-limit/utils/ip-key.js";import{McpClientInputError as Q,createMethodNotAllowedError as Z,withErrorHandling as q}from"./errors.js";import{constructForbiddenResponse as x,constructInvalidTokenResponse as ee,constructUnauthorizedResponse as re,handleMcpAuth as oe}from"../auth/auth-handlers.js";import{isAssistantAnonymousToken as se}from"../auth/assistant-anonymous-token.js";import{shouldHandleMcpAuth as ne}from"../../../utils/rbac/should-handle-mcp-auth.js";import{extractTokenFromAuthHeader as ie}from"../utils/jwt.js";import{resolveMcpClient as te}from"../utils/mcp-client.js";import{randomUUID as ce}from"../../../utils/crypto/random-uuid.js";import{getPublicMcpEndpointStatus as ae}from"../utils/public-endpoint.js";import{narrowMcpConfigForCaller as pe}from"../gateway-mcp/caller-api-calls.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as de,SSE_KEEPALIVE_INTERVAL_MS as le}from"../constants.js";import{withPathPrefix as me}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as fe}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as ue}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as ge}from"../../../constants/rbac.js";const E="X-Redocly-AI-Metadata";function he(r){if(r)try{const e=JSON.parse(r);if(V(e))return e;A.warn(`Ignoring ${E} header: not a JSON object.`)}catch{A.warn(`Ignoring ${E} header: invalid JSON.`)}}function Ae(r,e){return new URL(r).searchParams.get("mode")==="tools"?"tools":e}function I(){return{...ge,email:"",idpAccessToken:void 0,idpId:void 0}}const Me=async(r,e,i)=>{const t=!!e?.config?.access?.requiresLogin,c=e?.config?.access?.rbac||{},y=i?.props?.config?.mcpMode??"tools",p=Ae(r.url,y),C=i?.props?.config?.gatewayFetchBudgetPerExec??B.budgetPerExec,U=i?.props?.config?.searchIgnoredRoutes??[],o=i,R=!!o?.props?.config?.isPublicEndpoint;let u;const T=r.headers.get("Authorization");if(R)e.user=I();else if(ne(t,c)){const{isAuthenticated:n,isTokenValid:d,isFirstPartyAnonymous:g,currentUser:l,accessToken:h}=await oe(r,e);if(g)e.user=I();else if(n)l&&(e.user=l),u=h;else{const a=M(r),m=ae(e.config)==="served"?`${a}${me(fe)}`:void 0;return d===!1?ee(a,m):re(a,m)}}else if(T){const n=ie(T)??void 0;u=(n?await se(n):!1)?void 0:n}const w={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[H],claims:e.user?.claims??{}};return ue(j.MCP,w,c,t)?await q(async()=>{const n=p==="code"&&(i?.props?.config?.elicitationEnabled??!1);if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP client (VS Code, Cursor, Claude Code, etc.) using this URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return Z();const d=o?.props?.config?.apiDescriptionsMap||{},g=o?.props?.config?.graphqlDescriptions||[],l=o?.props?.config?.mcpDocsServerName||de,{config:{mcp:h={}}}=e,a=Y(d,e.user,c,t),m=z(g,e.user,c,t),P=e.config.products?Object.values(e.config.products).map(s=>s?.name):[],D=h.docs?.name||l,f=he(r.headers.get(E)),_=o?.props?.tools||[],O=o?.props?.skillsBaseUrl||M(r),F=$(o?.props?.skills||[],e.user,c,t).map(s=>({slug:s.slug,name:s.name,description:s.description,content:s.content,uri:G(O,s.slug)})),S=await Ee(r),b=o?.props?.fetchCountSecret,k={name:D,tools:_,skills:F,context:{...e,config:{...e.config,mcp:pe(e.config.mcp,f)},configFile:o?.props?.configFile,accessToken:u,outdir:e.outdir||"",baseUrl:e.baseUrl||M(r),internalBaseUrl:L(r),apiDescriptionsMap:a,graphqlDescriptions:m,products:P,metadata:f,mcpMode:p,elicitationEnabled:n,gatewayFetchBudgetPerExec:C,fetchCountRequest:p==="code"&&b?{caller:{subject:W(e.user),ip:X(r)},secret:b}:void 0,searchIgnoredRoutes:U,clientIp:N(r),...te(r),requestId:ce(),messageId:typeof f?.messageId=="string"?f.messageId:void 0}},v=await K({...k,getKv:e.getKv});return await J(async()=>v,{keepAliveMs:le,onerror:s=>A.warn(`MCP handler: ${s.message}`)}).fetch(r,S!==void 0?{parsedBody:S}:void 0)},p):x()};async function Ee(r){try{return await r.json()}catch(e){throw new Q(e instanceof Error?e.message:String(e),{cause:e})}}var ze=Me;export{ze as default};
1
+ import{logger as A}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as v}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as M,getInternalOrigin as N}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as L,DEFAULT_ANONYMOUS_VISITOR_TEAM as B,RbacFeatures as H}from"../../../../constants/common.js";import{isObject as j}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as V}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as $}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as Y}from"@modelcontextprotocol/server";import{createDocsMcpServer as G}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as J,filterGraphqlDescriptionsByRbac as K}from"../utils.js";import{userSubject as z}from"../gateway-mcp/subject.js";import{ipRateLimitKey as X}from"../gateway-mcp/rate-limit/utils/ip-key.js";import{createMethodNotAllowedError as Q,withErrorHandling as W}from"./errors.js";import{constructForbiddenResponse as Z,constructInvalidTokenResponse as q,constructUnauthorizedResponse as x,handleMcpAuth as ee}from"../auth/auth-handlers.js";import{isAssistantAnonymousToken as oe}from"../auth/assistant-anonymous-token.js";import{shouldHandleMcpAuth as re}from"../../../utils/rbac/should-handle-mcp-auth.js";import{extractTokenFromAuthHeader as se}from"../utils/jwt.js";import{resolveMcpClient as ie}from"../utils/mcp-client.js";import{randomUUID as ne}from"../../../utils/crypto/random-uuid.js";import{getPublicMcpEndpointStatus as te}from"../utils/public-endpoint.js";import{narrowMcpConfigForCaller as ce}from"../gateway-mcp/caller-api-calls.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as ae,SSE_KEEPALIVE_INTERVAL_MS as pe}from"../constants.js";import{withPathPrefix as de}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as le}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as me}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as fe}from"../../../constants/rbac.js";const E="X-Redocly-AI-Metadata",ue=1024*1024;function ge(o){if(o)try{const e=JSON.parse(o);if(j(e))return e;A.warn(`Ignoring ${E} header: not a JSON object.`)}catch{A.warn(`Ignoring ${E} header: invalid JSON.`)}}function he(o,e){return new URL(o).searchParams.get("mode")==="tools"?"tools":e}function b(){return{...fe,email:"",idpAccessToken:void 0,idpId:void 0}}const Ae=async(o,e,n)=>{const t=!!e?.config?.access?.requiresLogin,c=e?.config?.access?.rbac||{},I=n?.props?.config?.mcpMode??"tools",p=he(o.url,I),U=n?.props?.config?.gatewayFetchBudgetPerExec??L.budgetPerExec,R=n?.props?.config?.searchIgnoredRoutes??[],r=n,C=!!r?.props?.config?.isPublicEndpoint;let u;const T=o.headers.get("Authorization");if(C)e.user=b();else if(re(t,c)){const{isAuthenticated:i,isTokenValid:d,isFirstPartyAnonymous:g,currentUser:l,accessToken:h}=await ee(o,e);if(g)e.user=b();else if(i)l&&(e.user=l),u=h;else{const a=M(o),m=te(e.config)==="served"?`${a}${de(le)}`:void 0;return d===!1?q(a,m):x(a,m)}}else if(T){const i=se(T)??void 0;u=(i?await oe(i):!1)?void 0:i}const _={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[B],claims:e.user?.claims??{}};return me(H.MCP,_,c,t)?await W(async()=>{const i=p==="code"&&(n?.props?.config?.elicitationEnabled??!1);if(o.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP client (VS Code, Cursor, Claude Code, etc.) using this URL: ${o.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(o.method!=="POST")return Q();const d=r?.props?.config?.apiDescriptionsMap||{},g=r?.props?.config?.graphqlDescriptions||[],l=r?.props?.config?.mcpDocsServerName||ae,{config:{mcp:h={}}}=e,a=J(d,e.user,c,t),m=K(g,e.user,c,t),y=e.config.products?Object.values(e.config.products).map(s=>s?.name):[],D=h.docs?.name||l,f=ge(o.headers.get(E)),P=r?.props?.tools||[],O=r?.props?.skillsBaseUrl||M(o),w=V(r?.props?.skills||[],e.user,c,t).map(s=>({slug:s.slug,name:s.name,description:s.description,content:s.content,uri:$(O,s.slug)})),S=r?.props?.fetchCountSecret,F={name:D,tools:P,skills:w,context:{...e,config:{...e.config,mcp:ce(e.config.mcp,f)},configFile:r?.props?.configFile,accessToken:u,outdir:e.outdir||"",baseUrl:e.baseUrl||M(o),internalBaseUrl:N(o),apiDescriptionsMap:a,graphqlDescriptions:m,products:y,metadata:f,mcpMode:p,elicitationEnabled:i,gatewayFetchBudgetPerExec:U,fetchCountRequest:p==="code"&&S?{caller:{subject:z(e.user),ip:X(o)},secret:S}:void 0,searchIgnoredRoutes:R,clientIp:v(o),...ie(o),requestId:ne(),messageId:typeof f?.messageId=="string"?f.messageId:void 0}},k=await G({...F,getKv:e.getKv});return await Y(async()=>k,{keepAliveMs:pe,maxRequestBodySize:ue,onerror:s=>A.warn(`MCP handler: ${s.message}`)}).fetch(o)},p):Z()};var Je=Ae;export{Je as default};
@@ -12,11 +12,6 @@ export declare class McpError extends Error {
12
12
  constructor(code: McpErrorCodeTypes, message: string, data?: unknown, requestId?: string | number | null);
13
13
  createErrorResponse(): Response;
14
14
  }
15
- export declare class McpClientInputError extends Error {
16
- constructor(message: string, options?: {
17
- cause?: unknown;
18
- });
19
- }
20
15
  export declare function createMethodNotAllowedError(requestId?: string | number | null): Response;
21
16
  export declare function createInternalServerError(error: Error | string, requestId?: string | number | null): Response;
22
17
  export declare function withErrorHandling<T>(operation: () => Promise<T>, mode?: McpMode): Promise<T | Response>;
@@ -1 +1 @@
1
- import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as o,McpServerType as i}from"../constants.js";import{serverAttributes as d}from"../utils/telemetry-attributes.js";class n extends Error{code;data;requestId;constructor(t,r,s,a){super(r),this.name="McpError",this.code=t,this.data=s,this.requestId=a}createErrorResponse(){const t={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},r=u(this.code);return new Response(JSON.stringify(t),{status:r,headers:{"Content-Type":"application/json"}})}}class p extends Error{constructor(t,r){super(t,r),this.name="McpClientInputError"}}function u(e){switch(e){case o.InvalidRequest:case o.InvalidParams:return 400;case o.MethodNotFound:return 404;case o.ServerError:return 405;case o.InternalError:default:return 500}}function f(e){return new n(o.ServerError,"Method not allowed",void 0,e).createErrorResponse()}function l(e,t){const r=e instanceof Error?e.message:String(e);return new n(o.InternalError,"Internal server error mcp",r,t).createErrorResponse()}async function M(e,t="tools"){try{return await e()}catch(r){return c.sendMcpErrorMessage([{...d(i.Docs),message:r?.message||"",stack:r?.stack||"",error_class:r instanceof p?"client_error":"server_error",mode:t}]),l(r)}}export{p as McpClientInputError,n as McpError,l as createInternalServerError,f as createMethodNotAllowedError,M as withErrorHandling};
1
+ import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as o,McpServerType as d}from"../constants.js";import{serverAttributes as i}from"../utils/telemetry-attributes.js";class n extends Error{code;data;requestId;constructor(t,e,s,a){super(e),this.name="McpError",this.code=t,this.data=s,this.requestId=a}createErrorResponse(){const t={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},e=p(this.code);return new Response(JSON.stringify(t),{status:e,headers:{"Content-Type":"application/json"}})}}function p(r){switch(r){case o.InvalidRequest:case o.InvalidParams:return 400;case o.MethodNotFound:return 404;case o.ServerError:return 405;case o.InternalError:default:return 500}}function h(r){return new n(o.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function u(r,t){const e=r instanceof Error?r.message:String(r);return new n(o.InternalError,"Internal server error mcp",e,t).createErrorResponse()}async function f(r,t="tools"){try{return await r()}catch(e){return c.sendMcpErrorMessage([{...i(d.Docs),message:e?.message||"",stack:e?.stack||"",error_class:"server_error",mode:t}]),u(e)}}export{n as McpError,u as createInternalServerError,h as createMethodNotAllowedError,f as withErrorHandling};
@@ -1 +1 @@
1
- import{secretStore as d}from"../gateway-mcp/secret-store.js";import{rejectCredential as _}from"../gateway-mcp/credential-validation.js";import{buildAllowedHostMatchers as C}from"../gateway-mcp/fetch/allowed-hosts.js";import{assertUrlAllowed as A}from"../gateway-mcp/fetch/ssrf-guard.js";import{readCappedBody as T,getDefaultAgent as P}from"../gateway-mcp/fetch/fetch-bridge.js";import{logger as x}from"../../../tools/notifiers/logger.js";import{FORM_ACTIONS as k}from"./credentials-page/constants.js";import{credentialSchemesOf as w,schemeFieldName as f}from"./credentials-page/form-contract.js";import{formPage as N}from"./credentials-page/form-page.js";import{htmlDocument as O}from"./credentials-page/layout.js";import{declinedPage as R,expiredPage as I,outcomePage as j}from"./credentials-page/outcome-pages.js";const D={"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","X-Frame-Options":"DENY","Referrer-Policy":"no-referrer","Content-Security-Policy":"default-src 'none'; style-src 'unsafe-inline'; img-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'"},$=3e4,F=64*1024,M=/^bearer\s+/i,U=/^\d+$/,B=async(e,t,o)=>{const n=await t.getKv(),r=L(e,t.baseUrl,o);if(e.method==="GET"){const i=new URL(e.url).searchParams.get("token")??"",c=await d.peekElicitation(n,i);return c?S({kv:n,site:r,token:i,target:c},{},200):p(r)}if(e.method==="POST"){const i=await e.formData(),c=u(i,"token"),a=await d.peekElicitation(n,c);if(!a)return p(r);const s={kv:n,site:r,token:c,target:a,form:i};switch(u(i,"action")){case k.remove:return b(s,z(a,u(i,"scheme")));case k.removeAll:return b(s,w(a));case k.decline:return K(s);default:return H(s)}}return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, POST"}})};async function H(e){const{target:t,form:o}=e,n=w(t),r=n.map((s,l)=>u(o,f("client_id",l)).trim()),i=s=>S(e,{error:s,clientIds:r},400),c=X(n,o);if("error"in c)return i(c.error);if(c.writes.length===0)return i(G(n));const a=[];for(const s of c.writes){if(s.kind!=="exchange"){a.push(s);continue}const l=await J(s.auth,s.clientId,s.clientSecret);if(!l.ok)return x.warn(`gateway oauth2 client_credentials exchange failed for ${t.api}: ${l.reason}`),i(E(n,s.schemeIndex,"client_id","We could not exchange those client credentials for a token. Check the client ID and secret, then try again."));a.push({kind:"set",scheme:s.scheme,secret:l.secret})}return v(e,a)}function X(e,t){const o=[];for(const[n,r]of e.entries()){const i=u(t,f("secret",n)).trim();if(i){const s=_(r.auth,i);if(s)return{error:E(e,n,"secret",s)};o.push({kind:"set",scheme:r.name,secret:W(r.auth,i)});continue}if(r.auth.kind!=="oauth2ClientCredentials")continue;const c=u(t,f("client_id",n)).trim(),a=u(t,f("client_secret",n)).trim();if(c&&a)o.push({kind:"exchange",scheme:r.name,schemeIndex:n,auth:r.auth,clientId:c,clientSecret:a});else if(c||a)return{error:E(e,n,c?"client_secret":"client_id","Enter both the client ID and the client secret, or leave both blank.")}}return{writes:o}}function G(e){return e.length>1?{message:"Fill in at least one credential before saving."}:{message:e[0].auth.kind==="oauth2ClientCredentials"?"Enter an access token, or the client ID and the client secret, before saving.":"Enter a value before saving.",schemeIndex:0,field:"secret"}}function E(e,t,o,n){return{message:e.length>1?`${e[t].name}: ${n}`:n,schemeIndex:t,field:o}}async function b(e,t){const{kv:o,target:n}=e,r=await d.getStoredSchemes(o,n.subject,n.api),i=t.filter(c=>r[c.name]).map(c=>({kind:"remove",scheme:c.name}));return i.length===0?S(e,{error:{message:"No credential is stored there, so there is nothing to remove."}},400):v(e,i)}function z(e,t){const o=U.test(t)?w(e)[Number(t)]:void 0;return o?[o]:[]}async function K({kv:e,site:t,token:o}){return await d.consumeElicitation(e,o)?h(t,R(),200):p(t)}async function v({kv:e,site:t,token:o},n){const r=await d.consumeElicitation(e,o);if(!r)return p(t);for(const a of n)a.kind==="remove"?await d.deleteSecret(e,r.subject,r.api,a.scheme):await d.setSecret(e,r.subject,r.api,a.scheme,a.secret);const i=await d.getStoredSchemes(e,r.subject,r.api),c={action:n.some(a=>a.kind==="set")?"saved":"removed",schemes:n.map(a=>a.scheme),stored:Object.keys(i).sort()};return h(t,j(r,c),200)}async function S({kv:e,site:t,token:o,target:n},r,i){const c=await d.getStoredSchemes(e,n.subject,n.api);return h(t,N({site:t,target:n,token:o,stored:c,...r}),i)}function L(e,t,o){const n=o?.props?.branding??{},r=t&&URL.canParse(t)?t:e.url;return{...n,host:new URL(r).host}}async function J(e,t,o){try{const n=C([{url:e.tokenUrl}]),r=A(e.tokenUrl,n),i=new AbortController,c=setTimeout(()=>i.abort(),$);let a;try{a=await fetch(r,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"client_credentials",client_id:t,client_secret:o}),redirect:"manual",signal:i.signal,dispatcher:P()})}finally{clearTimeout(c)}if(!a.ok)return m(`token endpoint returned ${a.status}`);let s;try{s=await T(a,F)}catch{return m("token response exceeded the size cap")}let l;try{l=JSON.parse(s)}catch{return m("token response was not valid JSON")}const y=typeof l=="object"&&l!==null&&"access_token"in l?l.access_token:void 0,g=typeof y=="string"?y.trim():"";return g?_(e,g)?m("token response had an access_token that cannot be sent in a header"):{ok:!0,secret:{header:"Authorization",value:`Bearer ${g}`}}:m("token response had no access_token")}catch(n){return m(n instanceof Error?n.message:String(n))}}function m(e){return{ok:!1,reason:e}}function u(e,t){const o=e.get(t);return typeof o=="string"?o:""}function h(e,t,o){return new Response(O(t,e.colorScheme),{status:o,headers:D})}function p(e){return h(e,I(),404)}function W(e,t){return e.kind==="apiKey"?{header:e.header,value:t}:e.kind==="cookie"?{header:"Cookie",value:`${e.name}=${t}`}:e.kind==="bearer"||e.kind==="oauth2ClientCredentials"?{header:"Authorization",value:Y(t)}:{header:"Authorization",value:t}}function Y(e){return`Bearer ${e.replace(M,"")}`}var ie=B;export{ie as default};
1
+ import{readRequestBody as C}from"@modelcontextprotocol/server";import{secretStore as d}from"../gateway-mcp/secret-store.js";import{rejectCredential as _}from"../gateway-mcp/credential-validation.js";import{buildAllowedHostMatchers as T}from"../gateway-mcp/fetch/allowed-hosts.js";import{assertUrlAllowed as A}from"../gateway-mcp/fetch/ssrf-guard.js";import{readCappedBody as R,getDefaultAgent as P}from"../gateway-mcp/fetch/fetch-bridge.js";import{logger as x}from"../../../tools/notifiers/logger.js";import{FORM_ACTIONS as k}from"./credentials-page/constants.js";import{credentialSchemesOf as w,schemeFieldName as f}from"./credentials-page/form-contract.js";import{formPage as O}from"./credentials-page/form-page.js";import{htmlDocument as N}from"./credentials-page/layout.js";import{declinedPage as I,expiredPage as j,outcomePage as D}from"./credentials-page/outcome-pages.js";const $={"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","X-Frame-Options":"DENY","Referrer-Policy":"no-referrer","Content-Security-Policy":"default-src 'none'; style-src 'unsafe-inline'; img-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'"},M=3e4,B=64*1024,F=64*1024,U=/^bearer\s+/i,X=/^\d+$/,H=async(e,t,o)=>{const n=await t.getKv(),r=J(e,t.baseUrl,o);if(e.method==="GET"){const i=new URL(e.url).searchParams.get("token")??"",a=await d.peekElicitation(n,i);return a?E({kv:n,site:r,token:i,target:a},{},200):p(r)}if(e.method==="POST"){const i=await C(e,F);if(i.tooLarge)return new Response("Payload Too Large",{status:413});const a=await new Response(i.text,{headers:{"Content-Type":e.headers.get("content-type")??""}}).formData(),c=u(a,"token"),s=await d.peekElicitation(n,c);if(!s)return p(r);const l={kv:n,site:r,token:c,target:s,form:a};switch(u(a,"action")){case k.remove:return b(l,K(s,u(a,"scheme")));case k.removeAll:return b(l,w(s));case k.decline:return Y(l);default:return L(l)}}return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, POST"}})};async function L(e){const{target:t,form:o}=e,n=w(t),r=n.map((s,l)=>u(o,f("client_id",l)).trim()),i=s=>E(e,{error:s,clientIds:r},400),a=G(n,o);if("error"in a)return i(a.error);if(a.writes.length===0)return i(z(n));const c=[];for(const s of a.writes){if(s.kind!=="exchange"){c.push(s);continue}const l=await W(s.auth,s.clientId,s.clientSecret);if(!l.ok)return x.warn(`gateway oauth2 client_credentials exchange failed for ${t.api}: ${l.reason}`),i(y(n,s.schemeIndex,"client_id","We could not exchange those client credentials for a token. Check the client ID and secret, then try again."));c.push({kind:"set",scheme:s.scheme,secret:l.secret})}return v(e,c)}function G(e,t){const o=[];for(const[n,r]of e.entries()){const i=u(t,f("secret",n)).trim();if(i){const s=_(r.auth,i);if(s)return{error:y(e,n,"secret",s)};o.push({kind:"set",scheme:r.name,secret:Q(r.auth,i)});continue}if(r.auth.kind!=="oauth2ClientCredentials")continue;const a=u(t,f("client_id",n)).trim(),c=u(t,f("client_secret",n)).trim();if(a&&c)o.push({kind:"exchange",scheme:r.name,schemeIndex:n,auth:r.auth,clientId:a,clientSecret:c});else if(a||c)return{error:y(e,n,a?"client_secret":"client_id","Enter both the client ID and the client secret, or leave both blank.")}}return{writes:o}}function z(e){return e.length>1?{message:"Fill in at least one credential before saving."}:{message:e[0].auth.kind==="oauth2ClientCredentials"?"Enter an access token, or the client ID and the client secret, before saving.":"Enter a value before saving.",schemeIndex:0,field:"secret"}}function y(e,t,o,n){return{message:e.length>1?`${e[t].name}: ${n}`:n,schemeIndex:t,field:o}}async function b(e,t){const{kv:o,target:n}=e,r=await d.getStoredSchemes(o,n.subject,n.api),i=t.filter(a=>r[a.name]).map(a=>({kind:"remove",scheme:a.name}));return i.length===0?E(e,{error:{message:"No credential is stored there, so there is nothing to remove."}},400):v(e,i)}function K(e,t){const o=X.test(t)?w(e)[Number(t)]:void 0;return o?[o]:[]}async function Y({kv:e,site:t,token:o}){return await d.consumeElicitation(e,o)?h(t,I(),200):p(t)}async function v({kv:e,site:t,token:o},n){const r=await d.consumeElicitation(e,o);if(!r)return p(t);for(const c of n)c.kind==="remove"?await d.deleteSecret(e,r.subject,r.api,c.scheme):await d.setSecret(e,r.subject,r.api,c.scheme,c.secret);const i=await d.getStoredSchemes(e,r.subject,r.api),a={action:n.some(c=>c.kind==="set")?"saved":"removed",schemes:n.map(c=>c.scheme),stored:Object.keys(i).sort()};return h(t,D(r,a),200)}async function E({kv:e,site:t,token:o,target:n},r,i){const a=await d.getStoredSchemes(e,n.subject,n.api);return h(t,O({site:t,target:n,token:o,stored:a,...r}),i)}function J(e,t,o){const n=o?.props?.branding??{},r=t&&URL.canParse(t)?t:e.url;return{...n,host:new URL(r).host}}async function W(e,t,o){try{const n=T([{url:e.tokenUrl}]),r=A(e.tokenUrl,n),i=new AbortController,a=setTimeout(()=>i.abort(),M);let c;try{c=await fetch(r,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"client_credentials",client_id:t,client_secret:o}),redirect:"manual",signal:i.signal,dispatcher:P()})}finally{clearTimeout(a)}if(!c.ok)return m(`token endpoint returned ${c.status}`);let s;try{s=await R(c,B)}catch{return m("token response exceeded the size cap")}let l;try{l=JSON.parse(s)}catch{return m("token response was not valid JSON")}const S=typeof l=="object"&&l!==null&&"access_token"in l?l.access_token:void 0,g=typeof S=="string"?S.trim():"";return g?_(e,g)?m("token response had an access_token that cannot be sent in a header"):{ok:!0,secret:{header:"Authorization",value:`Bearer ${g}`}}:m("token response had no access_token")}catch(n){return m(n instanceof Error?n.message:String(n))}}function m(e){return{ok:!1,reason:e}}function u(e,t){const o=e.get(t);return typeof o=="string"?o:""}function h(e,t,o){return new Response(N(t,e.colorScheme),{status:o,headers:$})}function p(e){return h(e,j(),404)}function Q(e,t){return e.kind==="apiKey"?{header:e.header,value:t}:e.kind==="cookie"?{header:"Cookie",value:`${e.name}=${t}`}:e.kind==="bearer"||e.kind==="oauth2ClientCredentials"?{header:"Authorization",value:V(t)}:{header:"Authorization",value:t}}function V(e){return`Bearer ${e.replace(U,"")}`}var de=H;export{de as default};
@@ -1,3 +1,3 @@
1
- import{McpServer as U}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as _,MCP_TOOL_WORKER_KEY as O}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as F}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as L,stripAuthRequiredMeta as E,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{acceptedCredentialsLink as D,buildCredentialsAcceptedHint as K,buildCredentialsToolHint as j,buildUpstreamCredentialFallback as q,buildUpstreamCredentialInputRequired as v,credentialElicitationAnswer as H,dedupeElicitation as N,isStatelessRequest as P,schemeLabelOf as $,supportsUrlElicitation as B}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as y,resolveUpstreamApiAuth as W}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as G,resolveSecretSubject as V}from"../gateway-mcp/subject.js";import{toWorkerContext as Y}from"../workers/worker-context.js";const J=6e4;function de(e,t){return new U({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function pe(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,u=P(s.mcpReq),a=i?V(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const c=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await F.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let l;const d=async()=>{l=await c();const m={toolName:r,args:n,context:Y({...e,upstreamSecrets:l}),extra:te(s)};return await _.exec(O,[m],{timeout:J})};let p=await d();const f=L(p);if(f.length>0&&i&&!o)return E(R(p,[{type:"text",text:G}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${u?"2026-07-28":"2025"} clientElicitation=${Q(t)}`);const m=await t.getKv(),h=await X(e,f),w=f.map(C=>Z(C,h)),k=z(l),g=u?await x(e,s,w,o,m,k,h,t):await ee(e,w,o,m,k,h);switch(g.kind){case"inputRequired":return g.result;case"retry":p=await d();break;case"prependText":p=R(p,[{type:"text",text:g.text},...p.content]);break;case"none":break}}return E(p)}}function R(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function Q(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function X(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await W(e,n));return r}function Z(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??y};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function z(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function I(e,t){return e.status===401&&!t.has(b(e))}function T(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?$(r.schemes,n):void 0}function M(e,t){return e.map(r=>j(r,T(r,t))).join(`
1
+ import{McpServer as C}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as U,MCP_TOOL_WORKER_KEY as O}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as L}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as F,stripAuthRequiredMeta as k,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{acceptedCredentialsLink as D,buildCredentialsAcceptedHint as K,buildCredentialsToolHint as N,buildUpstreamCredentialFallback as q,buildUpstreamCredentialInputRequired as j,credentialElicitationAnswer as P,dedupeElicitation as v,isStatelessRequest as H,schemeLabelOf as $,supportsUrlElicitation as B}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as y,resolveUpstreamApiAuth as W}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as G,resolveSecretSubject as V}from"../gateway-mcp/subject.js";import{toWorkerContext as X}from"../workers/worker-context.js";const Y=6e4,J=1e4;function de(e,t){return new C({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},maxToolInputElements:J,...t?{instructions:t}:{}})}function me(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,u=H(s.mcpReq),a=i?V(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const c=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await L.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let l;const p=async()=>{l=await c();const m={toolName:r,args:n,context:X({...e,upstreamSecrets:l}),extra:re(s)};return await U.exec(O,[m],{timeout:Y})};let d=await p();const f=F(d);if(f.length>0&&i&&!o)return k(T(d,[{type:"text",text:G}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${u?"2026-07-28":"2025"} clientElicitation=${Q(t)}`);const m=await t.getKv(),h=await Z(e,f),w=f.map(_=>x(_,h)),E=z(l),g=u?await ee(e,s,w,o,m,E,h,t):await te(e,w,o,m,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":d=await p();break;case"prependText":d=T(d,[{type:"text",text:g.text},...d.content]);break;case"none":break}}return k(d)}}function T(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function Q(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function Z(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await W(e,n));return r}function x(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??y};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function z(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function I(e,t){return e.status===401&&!t.has(b(e))}function R(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?$(r.schemes,n):void 0}function M(e,t){return e.map(r=>N(r,R(r,t))).join(`
2
2
 
3
- `)}function A(e,t,r,n,s){const[i,...u]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??y,c=i.schemes&&i.schemes.length>1?i.schemes:void 0,l=c?void 0:T(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...l?{schemeLabel:l}:{},...c?{acceptedSchemes:c}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:u.map(d=>d.name)}}}async function x(e,t,r,n,s,i,u,a){const o=H(t.mcpReq.inputResponses);if(o==="declined")return{kind:"none"};const c=r.filter(d=>I(d,i));if(c.length===0)return{kind:"prependText",text:M(r,u)};if(o==="accepted"){const d=await D(t.mcpReq.requestState(),{kv:s,subject:n,baseUrl:e.baseUrl??"",apis:c.map(f=>f.api)}),p=d?.apiName??c[0].name;return{kind:"prependText",text:K(p,d?.url)}}const l=A(e,c,n,s,u);return B(a?.getClientCapabilities())?{kind:"inputRequired",result:await v(l)}:{kind:"prependText",text:await q(l)}}async function ee(e,t,r,n,s,i){const u=t.filter(c=>I(c,s));if(u.length===0)return{kind:"prependText",text:M(t,i)};const a=A(e,u,r,n,i);return{kind:"prependText",text:await N(`${r}:${b(u[0])}`,()=>q(a))}}function te(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function me(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,fetchCountRequest:e.fetchCountRequest,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,requestId:e.requestId,messageId:e.messageId,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,configFile:e.configFile,fs:void 0}}export{de as createMcpServer,pe as createToolDispatch,me as extractSerializableContext};
3
+ `)}function A(e,t,r,n,s){const[i,...u]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??y,c=i.schemes&&i.schemes.length>1?i.schemes:void 0,l=c?void 0:R(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...l?{schemeLabel:l}:{},...c?{acceptedSchemes:c}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:u.map(p=>p.name)}}}async function ee(e,t,r,n,s,i,u,a){const o=P(t.mcpReq.inputResponses);if(o==="declined")return{kind:"none"};const c=r.filter(p=>I(p,i));if(c.length===0)return{kind:"prependText",text:M(r,u)};if(o==="accepted"){const p=await D(t.mcpReq.requestState(),{kv:s,subject:n,baseUrl:e.baseUrl??"",apis:c.map(f=>f.api)}),d=p?.apiName??c[0].name;return{kind:"prependText",text:K(d,p?.url)}}const l=A(e,c,n,s,u);return B(a?.getClientCapabilities())?{kind:"inputRequired",result:await j(l)}:{kind:"prependText",text:await q(l)}}async function te(e,t,r,n,s,i){const u=t.filter(c=>I(c,s));if(u.length===0)return{kind:"prependText",text:M(t,i)};const a=A(e,u,r,n,i);return{kind:"prependText",text:await v(`${r}:${b(u[0])}`,()=>q(a))}}function re(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function fe(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,fetchCountRequest:e.fetchCountRequest,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,requestId:e.requestId,messageId:e.messageId,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,configFile:e.configFile,fs:void 0}}export{de as createMcpServer,me as createToolDispatch,fe as extractSerializableContext};
@@ -1,5 +1,5 @@
1
1
  declare const colorsAreEnabled: boolean;
2
- declare const red: import("colorette").Color, green: import("colorette").Color, bold: import("colorette").Color, blue: import("colorette").Color, gray: import("colorette").Color, yellow: import("colorette").Color, cyan: import("colorette").Color;
2
+ declare const { red, green, bold, blue, gray, yellow, cyan }: import("colorette").Colorette;
3
3
  declare const stripColors: (input: string) => string;
4
4
  export { red, gray, green, blue, bold, yellow, cyan, colorsAreEnabled, stripColors };
5
5
  //# sourceMappingURL=colors.d.ts.map
@@ -1 +1 @@
1
- import*as o from"dotenv";import*as n from"path";import{simpleGit as p}from"simple-git";import{envConfig as s,reloadEnvConfig as c,setEnv as m}from"../../config/env-config.js";import{readEnvVariable as f}from"../../utils/envs/read-env-variable.js";import{sanitizeBranchName as E}from"../../utils/envs/sanitize-branch-name.js";async function l(e){try{return(await p(e??process.cwd()).revparse(["--abbrev-ref","HEAD"])).trim()}catch{return""}}const h=["REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED"];async function N(e){const a=Object.fromEntries(h.map(t=>[t,f(t)]));o.config({path:n.resolve(e??"",".env")}),c();const i=s.PUBLIC_REDOCLY_BRANCH_NAME||await l(e);if(i){const t=E(i);o.config({path:n.resolve(e??"",`.env.branch.${t}`),override:!0}),c()}const v=s.REDOCLY_ENV;let r;switch(v){case"production":r=".env.production";break;case"preview":r=".env.preview";break;default:r=".env.development";break}o.config({path:n.resolve(e??"",r),override:!0}),m(a)}export{N as loadEnvVariables};
1
+ import*as o from"dotenv";import*as n from"path";import{simpleGit as E}from"simple-git";import{envConfig as s,reloadEnvConfig as c,setEnv as p}from"../../config/env-config.js";import{readEnvVariable as m}from"../../utils/envs/read-env-variable.js";import{sanitizeBranchName as f}from"../../utils/envs/sanitize-branch-name.js";async function l(e){try{return(await E(e??process.cwd()).revparse(["--abbrev-ref","HEAD"])).trim()}catch{return""}}const _=["REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED","REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED"];async function d(e){const a=Object.fromEntries(_.map(t=>[t,m(t)]));o.config({path:n.resolve(e??"",".env")}),c();const i=s.PUBLIC_REDOCLY_BRANCH_NAME||await l(e);if(i){const t=f(i);o.config({path:n.resolve(e??"",`.env.branch.${t}`),override:!0}),c()}const v=s.REDOCLY_ENV;let r;switch(v){case"production":r=".env.production";break;case"preview":r=".env.preview";break;default:r=".env.development";break}o.config({path:n.resolve(e??"",r),override:!0}),p(a)}export{d as loadEnvVariables};
@@ -2,6 +2,7 @@ import '../node-crypto-polyfill.js';
2
2
  import { REDOCLY_TEAMS_RBAC, REDOCLY_ROUTE_RBAC } from '@redocly/config';
3
3
  import type { RbacConfig, RbacScopeItems, RedoclyConfig, SsoConfig } from '@redocly/config';
4
4
  import type { AuthDetails } from '../types';
5
+ import type { ApiDefinitionAccess } from '../plugins/api-docs/definition-access.js';
5
6
  import type { ContentFs } from '../fs/content-fs.js';
6
7
  import type { RbacFeatures } from '../../constants/common.js';
7
8
  export type ProjectRole = 'NONE' | 'READ' | 'TRIAGE' | 'WRITE' | 'MAINTAIN' | 'ADMIN';
@@ -33,7 +34,7 @@ export declare function canDownloadApiDefinition(pathname: string, rbacConfig: R
33
34
  isAuthenticated?: boolean;
34
35
  email?: string;
35
36
  teams?: string[];
36
- }): boolean;
37
+ }, definitionAccess?: ApiDefinitionAccess): boolean;
37
38
  export declare function canAccessAsset(pathname: string, rbacConfig: RbacConfig, requiresLogin: boolean, directoryPaths: Record<string, string>, user?: {
38
39
  isAuthenticated?: boolean;
39
40
  email?: string;
@@ -1 +1 @@
1
- import R from"path";import T from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as L,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as U,PUBLIC_MCP_ROUTE as k}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as w}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as D,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as x,GRAPHQL_SPEC_SLUG as B}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as g,PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_ASSETS_FOLDER as b,RUNTIME_RESOURCES_DIR as $,SCORECARD_CLASSIC_FOLDER as W,SITEMAP_FILE_NAME as v,LLMS_TXT_FILE_NAME as Y}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as G}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as H}from"../constants/rbac.js";import{removeTrailingSlash as P}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as z}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as K}from"../../utils/path/parse-path-versions.js";import{reporter as V}from"../tools/notifiers/reporter.js";import{bold as J}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as Q}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as X}from"../../utils/guards/is-truthy.js";import{isPathInFolder as I}from"../../utils/path/is-path-in-folder.js";import{canExpandConfig as Z,expandRbacConfig as q,getTeamFolderDefaults as tt,parseTeamFoldersTemplate as et,parseTeamNameTemplate as rt}from"./rbac-expand.js";import{getUserParamsFromCookies as nt}from"../web-server/auth.js";import{getDeeperGlobPattern as ot}from"./globs.js";import{EntitlementsProvider as st}from"../entitlements/entitlements-provider.js";const j=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],ct=new Set(["x-parsed-md-description","x-parsed-md-summary"]),it=new Set(Object.values(w).map(t=>P(t.split(":")[0])));function wt(t,e){const r=j.indexOf(t.toUpperCase()),n=j.indexOf(e.toUpperCase());return r>n?t:e}const _={};function F(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=_[d]??T(a);_[d]=p;const E=`fsPath:${a}`,S=_[E]??T(z(a));return _[E]=S,!!(n&&p(n))||!!(o&&S(o))};if(ut(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[x]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>T.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=ot(h,u[a]);return r[h.input]}function N(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function Bt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?N(o,e.teams):!0}function bt(t,e){return O(t,H,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&it.has(P(t.slug))||(t.slug===U||t.slug===k||t.slug===G)&&st.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=q(r,e.teams||[]),s=t[L]||F(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:N(s,e?.teams||[],e?.email)}function $t(t,e,r,n){if(!t.startsWith(C)&&!t.startsWith(g))return!0;const o=t.replace(new RegExp(`^${C}/`),"").replace(new RegExp(`^${g}/`),"").replace(new RegExp(`^${B}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function Wt(t,e,r,n,o){if(!I(t,b))return[`/${v}`,`/${Y}`].includes(t)||[$,W].some(E=>I(t,E));const s=t.match(/\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function vt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await nt(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==D):f=[D],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function M(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=M(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===L||c===A)continue;if(ct.has(c)){s[c]=t[c];continue}const i=M(t[c],e,r,n);if(!t.link&&(c==="items"||c==="menu"&&t.type==="tab")&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&at(i)&&ft(i)}return o?void 0:s}return t}function Yt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Gt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===x?[[s,c]]:[[s,c]].concat(t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c]))),o=Object.fromEntries(n);return{...e,content:o}}async function Ht(t,e){if(!e)return{};const r={},n=new Set(t.scan().flatMap(({relativePath:o})=>{const{versionFolderPath:s}=K(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[Q(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function at(t){return m(t)&&Object.keys(t).length>0}function ft(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function ut(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const lt=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},zt=async t=>{if(t){if(Object.keys(t).length===0)return{};if(lt(t))return mt(t);await V.panicOnContentError(`You are using an incorrect format of ${J("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},mt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=P(n);r[o]=e.content[n]}e.content=r}return e};function Kt(t,e){const r=t.fsPath,n=t.slug,o=[],s=Z(e)&&(r||n)?et(e,[r,n].filter(X)):null;if(s){const i=e?.teamNamePatterns?.map(f=>f.replace("{teamPathSegment}",s.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i)}const c=F(s?{content:{...tt(e),...e.content}}:e,t);return o.push(...pt(c)),ht(e,o)}function pt(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function ht(t,e){return e.map(n=>rt(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{j as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Gt as applyL10nToRbacConfig,Wt as canAccessAsset,Bt as canAccessFeature,O as canAccessResource,$t as canDownloadApiDefinition,ht as expandTeamsForRead,pt as extractTeamsFromScopeItems,M as filterDataByAccessDeep,vt as getAuthDetailsFromCookies,wt as getHigherRole,Kt as getRbacTeamsListForResource,F as getScopeItemsForResource,N as hasScopeAccess,lt as isRbacConfigValid,bt as isResourcePubliclyAccessible,mt as normalizeRbacConfig,zt as parseRbacConfig,Yt as parseTeamClaimToArray,Ht as resolveDirectoryHashes};
1
+ import y from"path";import O from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as T,REDOCLY_ROUTE_RBAC as R}from"@redocly/config";import{MCP_ROUTE as U,PUBLIC_MCP_ROUTE as k}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as w}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as D,PUBLIC_RBAC_SCOPE_ITEM as _,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as x,GRAPHQL_SPEC_SLUG as B}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as g,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as b,RUNTIME_RESOURCES_DIR as $,SCORECARD_CLASSIC_FOLDER as W,SITEMAP_FILE_NAME as v,LLMS_TXT_FILE_NAME as Y}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as G}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as H}from"../constants/rbac.js";import{removeTrailingSlash as S}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as z}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as K}from"../../utils/path/parse-path-versions.js";import{reporter as V}from"../tools/notifiers/reporter.js";import{bold as J}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as Q}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as X}from"../../utils/guards/is-truthy.js";import{isPathInFolder as C}from"../../utils/path/is-path-in-folder.js";import{canExpandConfig as Z,expandRbacConfig as q,getTeamFolderDefaults as tt,parseTeamFoldersTemplate as et,parseTeamNameTemplate as rt}from"./rbac-expand.js";import{getUserParamsFromCookies as nt}from"../web-server/auth.js";import{getDeeperGlobPattern as ot}from"./globs.js";import{EntitlementsProvider as st}from"../entitlements/entitlements-provider.js";const j=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],ct=new Set(["x-parsed-md-description","x-parsed-md-summary"]),at=new Set(Object.values(w).map(t=>S(t.split(":")[0])));function wt(t,e){const r=j.indexOf(t.toUpperCase()),n=j.indexOf(e.toUpperCase());return r>n?t:e}const P={};function F(t,e){if(!t?.content)return _;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return _;const s=f=>{const E=`slug:${f}`,p=P[E]??O(f);P[E]=p;const A=`fsPath:${f}`,L=P[A]??O(z(f));return P[A]=L,!!(n&&p(n))||!!(o&&L(o))};if(ut(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[x]||_;const i=Object.keys(r).filter(f=>s(f));if(i.length==0)return _;const u=i.map(f=>O.scan(f,{tokens:!0,parts:!0}));let h=u[0];for(let f=1;f<u.length;f++)h=ot(h,u[f]);return r[h.input]}function N(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function Bt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?N(o,e.teams):!0}function bt(t,e){return d(t,H,e.access?.rbac||{},e.access?.requiresLogin||!1)}function d(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&at.has(S(t.slug))||(t.slug===U||t.slug===k||t.slug===G)&&st.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=q(r,e.teams||[]),s=t[T]||F(o,t[R]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:N(s,e?.teams||[],e?.email)}function $t(t,e,r,n,o){if(!t.startsWith(I)&&!t.startsWith(g))return!0;if(o){const u={[T]:o.rbac,[R]:{slug:o.slug,fsPath:o.sourcePath}};return d(u,n,e,r)}const s=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${g}/`),"").replace(new RegExp(`^${B}/`),""),a=s==="."?"":s,i={[R]:{slug:t,fsPath:a},slug:t};return d(i,n,e,r)}function Wt(t,e,r,n,o){if(!C(t,b))return[`/${v}`,`/${Y}`].includes(t)||[$,W].some(A=>C(t,A));const s=t.match(/\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:a,ext:i}=y.parse(t),u=a.split(".")[0],h=i.split(".").join(""),E=c==="."?"":c,p={[R]:{slug:t,fsPath:y.posix.join(E,`${u}.${h}`)},slug:t};return d(p,o,e,r)}async function vt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await nt(t,e),{teams:a=[]}=c;let i;return r?i=a.filter(u=>u!==D):i=[D],{isAuthenticated:r,idpAccessToken:n,teams:i,claims:c}}function M(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=M(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!d(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===T||c===R)continue;if(ct.has(c)){s[c]=t[c];continue}const a=M(t[c],e,r,n);if(!t.link&&(c==="items"||c==="menu"&&t.type==="tab")&&Array.isArray(a)&&a.length===0&&t[c].length!==0){o=!0;continue}a!==void 0&&(s[c]=a),c==="paths"&&it(a)&&ft(a)}return o?void 0:s}return t}function Yt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Gt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===x?[[s,c]]:[[s,c]].concat(t.localeFolders.map(a=>[s.startsWith("/")?`/${a.toLocaleLowerCase()}${s}`:y.posix.join(t.localizationFolder,a,s),c]))),o=Object.fromEntries(n);return{...e,content:o}}async function Ht(t,e){if(!e)return{};const r={},n=new Set(t.scan().flatMap(({relativePath:o})=>{const{versionFolderPath:s}=K(o)||{},c=y.dirname(o);return s?[s,c]:c}));for(const o of n)r[Q(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function it(t){return m(t)&&Object.keys(t).length>0}function ft(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function ut(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const lt=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},zt=async t=>{if(t){if(Object.keys(t).length===0)return{};if(lt(t))return mt(t);await V.panicOnContentError(`You are using an incorrect format of ${J("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},mt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=S(n);r[o]=e.content[n]}e.content=r}return e};function Kt(t,e){const r=t.fsPath,n=t.slug,o=[],s=Z(e)&&(r||n)?et(e,[r,n].filter(X)):null;if(s){const a=e?.teamNamePatterns?.map(i=>i.replace("{teamPathSegment}",s.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...a)}const c=F(s?{content:{...tt(e),...e.content}}:e,t);return o.push(...pt(c)),ht(e,o)}function pt(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function ht(t,e){return e.map(n=>rt(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{j as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Gt as applyL10nToRbacConfig,Wt as canAccessAsset,Bt as canAccessFeature,d as canAccessResource,$t as canDownloadApiDefinition,ht as expandTeamsForRead,pt as extractTeamsFromScopeItems,M as filterDataByAccessDeep,vt as getAuthDetailsFromCookies,wt as getHigherRole,Kt as getRbacTeamsListForResource,F as getScopeItemsForResource,N as hasScopeAccess,lt as isRbacConfigValid,bt as isResourcePubliclyAccessible,mt as normalizeRbacConfig,zt as parseRbacConfig,Yt as parseTeamClaimToArray,Ht as resolveDirectoryHashes};
@@ -12,594 +12,5 @@ export declare function jsonValidatorMiddleware<T extends ZodSchema>(schema: T):
12
12
  out: {
13
13
  json: T extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").output<T> : T extends import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>> ? import("zod").infer<T> : never;
14
14
  };
15
- }, (Response & import("hono").TypedResponse<"Bad Request", 400, "text">) | (Response & import("hono").TypedResponse<{
16
- success: boolean;
17
- error: ({
18
- readonly path: (string | number | null)[];
19
- readonly message: string;
20
- readonly code: "custom";
21
- readonly params?: Record<string, any> | undefined;
22
- readonly input?: import("hono/utils/types").JSONValue | undefined;
23
- } | {
24
- readonly path: (string | number | null)[];
25
- readonly message: string;
26
- readonly code: "invalid_element";
27
- readonly origin: "map" | "set";
28
- readonly key: import("hono/utils/types").JSONValue;
29
- readonly issues: ({
30
- readonly path: (string | number | null)[];
31
- readonly message: string;
32
- readonly code: "custom";
33
- readonly params?: Record<string, any> | undefined;
34
- readonly input?: import("hono/utils/types").JSONValue | undefined;
35
- } | /*elided*/ any | {
36
- readonly path: (string | number | null)[];
37
- readonly message: string;
38
- readonly code: "invalid_key";
39
- readonly origin: "map" | "record";
40
- readonly issues: ({
41
- readonly path: (string | number | null)[];
42
- readonly message: string;
43
- readonly code: "custom";
44
- readonly params?: Record<string, any> | undefined;
45
- readonly input?: import("hono/utils/types").JSONValue | undefined;
46
- } | /*elided*/ any | /*elided*/ any | {
47
- readonly path: (string | number | null)[];
48
- readonly message: string;
49
- readonly code: "invalid_format";
50
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
51
- readonly pattern?: string;
52
- readonly input?: string;
53
- } | {
54
- readonly path: (string | number | null)[];
55
- readonly message: string;
56
- readonly code: "invalid_type";
57
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
58
- readonly input?: import("hono/utils/types").JSONValue | undefined;
59
- } | {
60
- readonly path: (string | number | null)[];
61
- readonly message: string;
62
- readonly code: "invalid_value";
63
- readonly values: (string | number | boolean | null)[];
64
- readonly input?: import("hono/utils/types").JSONValue | undefined;
65
- } | {
66
- readonly path: (string | number | null)[];
67
- readonly message: string;
68
- readonly code: "not_multiple_of";
69
- readonly divisor: number;
70
- readonly input?: number | undefined;
71
- } | {
72
- readonly path: (string | number | null)[];
73
- readonly message: string;
74
- readonly code: "too_big";
75
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
76
- readonly maximum: number;
77
- readonly inclusive?: boolean;
78
- readonly exact?: boolean;
79
- readonly input?: import("hono/utils/types").JSONValue | undefined;
80
- } | {
81
- readonly path: (string | number | null)[];
82
- readonly message: string;
83
- readonly code: "too_small";
84
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
85
- readonly minimum: number;
86
- readonly inclusive?: boolean;
87
- readonly exact?: boolean;
88
- readonly input?: import("hono/utils/types").JSONValue | undefined;
89
- } | {
90
- readonly path: (string | number | null)[];
91
- readonly message: string;
92
- readonly code: "unrecognized_keys";
93
- readonly keys: string[];
94
- readonly input?: {
95
- [x: string]: import("hono/utils/types").JSONValue;
96
- } | undefined;
97
- } | {
98
- readonly path: (string | number | null)[];
99
- readonly message: string;
100
- readonly code: "invalid_union";
101
- readonly errors: [];
102
- readonly input?: import("hono/utils/types").JSONValue | undefined;
103
- readonly discriminator?: string | undefined;
104
- readonly inclusive: false;
105
- readonly matches: number[];
106
- } | {
107
- readonly path: (string | number | null)[];
108
- readonly message: string;
109
- readonly code: "invalid_union";
110
- readonly errors: ({
111
- readonly path: (string | number | null)[];
112
- readonly message: string;
113
- readonly code: "custom";
114
- readonly params?: Record<string, any> | undefined;
115
- readonly input?: import("hono/utils/types").JSONValue | undefined;
116
- } | /*elided*/ any | /*elided*/ any | {
117
- readonly path: (string | number | null)[];
118
- readonly message: string;
119
- readonly code: "invalid_format";
120
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
121
- readonly pattern?: string;
122
- readonly input?: string;
123
- } | {
124
- readonly path: (string | number | null)[];
125
- readonly message: string;
126
- readonly code: "invalid_type";
127
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
128
- readonly input?: import("hono/utils/types").JSONValue | undefined;
129
- } | {
130
- readonly path: (string | number | null)[];
131
- readonly message: string;
132
- readonly code: "invalid_value";
133
- readonly values: (string | number | boolean | null)[];
134
- readonly input?: import("hono/utils/types").JSONValue | undefined;
135
- } | {
136
- readonly path: (string | number | null)[];
137
- readonly message: string;
138
- readonly code: "not_multiple_of";
139
- readonly divisor: number;
140
- readonly input?: number | undefined;
141
- } | {
142
- readonly path: (string | number | null)[];
143
- readonly message: string;
144
- readonly code: "too_big";
145
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
146
- readonly maximum: number;
147
- readonly inclusive?: boolean;
148
- readonly exact?: boolean;
149
- readonly input?: import("hono/utils/types").JSONValue | undefined;
150
- } | {
151
- readonly path: (string | number | null)[];
152
- readonly message: string;
153
- readonly code: "too_small";
154
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
155
- readonly minimum: number;
156
- readonly inclusive?: boolean;
157
- readonly exact?: boolean;
158
- readonly input?: import("hono/utils/types").JSONValue | undefined;
159
- } | {
160
- readonly path: (string | number | null)[];
161
- readonly message: string;
162
- readonly code: "unrecognized_keys";
163
- readonly keys: string[];
164
- readonly input?: {
165
- [x: string]: import("hono/utils/types").JSONValue;
166
- } | undefined;
167
- } | {
168
- readonly path: (string | number | null)[];
169
- readonly message: string;
170
- readonly code: "invalid_union";
171
- readonly errors: [];
172
- readonly input?: import("hono/utils/types").JSONValue | undefined;
173
- readonly discriminator?: string | undefined;
174
- readonly inclusive: false;
175
- readonly matches: number[];
176
- } | /*elided*/ any)[][];
177
- readonly input?: import("hono/utils/types").JSONValue | undefined;
178
- readonly discriminator?: string | undefined;
179
- readonly options?: (string | number | boolean | null)[] | undefined;
180
- readonly inclusive?: true;
181
- })[];
182
- readonly input?: import("hono/utils/types").JSONValue | undefined;
183
- } | {
184
- readonly path: (string | number | null)[];
185
- readonly message: string;
186
- readonly code: "invalid_format";
187
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
188
- readonly pattern?: string;
189
- readonly input?: string;
190
- } | {
191
- readonly path: (string | number | null)[];
192
- readonly message: string;
193
- readonly code: "invalid_type";
194
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
195
- readonly input?: import("hono/utils/types").JSONValue | undefined;
196
- } | {
197
- readonly path: (string | number | null)[];
198
- readonly message: string;
199
- readonly code: "invalid_value";
200
- readonly values: (string | number | boolean | null)[];
201
- readonly input?: import("hono/utils/types").JSONValue | undefined;
202
- } | {
203
- readonly path: (string | number | null)[];
204
- readonly message: string;
205
- readonly code: "not_multiple_of";
206
- readonly divisor: number;
207
- readonly input?: number | undefined;
208
- } | {
209
- readonly path: (string | number | null)[];
210
- readonly message: string;
211
- readonly code: "too_big";
212
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
213
- readonly maximum: number;
214
- readonly inclusive?: boolean;
215
- readonly exact?: boolean;
216
- readonly input?: import("hono/utils/types").JSONValue | undefined;
217
- } | {
218
- readonly path: (string | number | null)[];
219
- readonly message: string;
220
- readonly code: "too_small";
221
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
222
- readonly minimum: number;
223
- readonly inclusive?: boolean;
224
- readonly exact?: boolean;
225
- readonly input?: import("hono/utils/types").JSONValue | undefined;
226
- } | {
227
- readonly path: (string | number | null)[];
228
- readonly message: string;
229
- readonly code: "unrecognized_keys";
230
- readonly keys: string[];
231
- readonly input?: {
232
- [x: string]: import("hono/utils/types").JSONValue;
233
- } | undefined;
234
- } | {
235
- readonly path: (string | number | null)[];
236
- readonly message: string;
237
- readonly code: "invalid_union";
238
- readonly errors: [];
239
- readonly input?: import("hono/utils/types").JSONValue | undefined;
240
- readonly discriminator?: string | undefined;
241
- readonly inclusive: false;
242
- readonly matches: number[];
243
- } | {
244
- readonly path: (string | number | null)[];
245
- readonly message: string;
246
- readonly code: "invalid_union";
247
- readonly errors: ({
248
- readonly path: (string | number | null)[];
249
- readonly message: string;
250
- readonly code: "custom";
251
- readonly params?: Record<string, any> | undefined;
252
- readonly input?: import("hono/utils/types").JSONValue | undefined;
253
- } | any | any | {
254
- readonly path: (string | number | null)[];
255
- readonly message: string;
256
- readonly code: "invalid_format";
257
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
258
- readonly pattern?: string;
259
- readonly input?: string;
260
- } | {
261
- readonly path: (string | number | null)[];
262
- readonly message: string;
263
- readonly code: "invalid_type";
264
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
265
- readonly input?: import("hono/utils/types").JSONValue | undefined;
266
- } | {
267
- readonly path: (string | number | null)[];
268
- readonly message: string;
269
- readonly code: "invalid_value";
270
- readonly values: (string | number | boolean | null)[];
271
- readonly input?: import("hono/utils/types").JSONValue | undefined;
272
- } | {
273
- readonly path: (string | number | null)[];
274
- readonly message: string;
275
- readonly code: "not_multiple_of";
276
- readonly divisor: number;
277
- readonly input?: number | undefined;
278
- } | {
279
- readonly path: (string | number | null)[];
280
- readonly message: string;
281
- readonly code: "too_big";
282
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
283
- readonly maximum: number;
284
- readonly inclusive?: boolean;
285
- readonly exact?: boolean;
286
- readonly input?: import("hono/utils/types").JSONValue | undefined;
287
- } | {
288
- readonly path: (string | number | null)[];
289
- readonly message: string;
290
- readonly code: "too_small";
291
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
292
- readonly minimum: number;
293
- readonly inclusive?: boolean;
294
- readonly exact?: boolean;
295
- readonly input?: import("hono/utils/types").JSONValue | undefined;
296
- } | {
297
- readonly path: (string | number | null)[];
298
- readonly message: string;
299
- readonly code: "unrecognized_keys";
300
- readonly keys: string[];
301
- readonly input?: {
302
- [x: string]: import("hono/utils/types").JSONValue;
303
- } | undefined;
304
- } | {
305
- readonly path: (string | number | null)[];
306
- readonly message: string;
307
- readonly code: "invalid_union";
308
- readonly errors: [];
309
- readonly input?: import("hono/utils/types").JSONValue | undefined;
310
- readonly discriminator?: string | undefined;
311
- readonly inclusive: false;
312
- readonly matches: number[];
313
- } | any)[][];
314
- readonly input?: import("hono/utils/types").JSONValue | undefined;
315
- readonly discriminator?: string | undefined;
316
- readonly options?: (string | number | boolean | null)[] | undefined;
317
- readonly inclusive?: true;
318
- })[];
319
- readonly input?: import("hono/utils/types").JSONValue | undefined;
320
- } | {
321
- readonly path: (string | number | null)[];
322
- readonly message: string;
323
- readonly code: "invalid_key";
324
- readonly origin: "map" | "record";
325
- readonly issues: ({
326
- readonly path: (string | number | null)[];
327
- readonly message: string;
328
- readonly code: "custom";
329
- readonly params?: Record<string, any> | undefined;
330
- readonly input?: import("hono/utils/types").JSONValue | undefined;
331
- } | any | any | {
332
- readonly path: (string | number | null)[];
333
- readonly message: string;
334
- readonly code: "invalid_format";
335
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
336
- readonly pattern?: string;
337
- readonly input?: string;
338
- } | {
339
- readonly path: (string | number | null)[];
340
- readonly message: string;
341
- readonly code: "invalid_type";
342
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
343
- readonly input?: import("hono/utils/types").JSONValue | undefined;
344
- } | {
345
- readonly path: (string | number | null)[];
346
- readonly message: string;
347
- readonly code: "invalid_value";
348
- readonly values: (string | number | boolean | null)[];
349
- readonly input?: import("hono/utils/types").JSONValue | undefined;
350
- } | {
351
- readonly path: (string | number | null)[];
352
- readonly message: string;
353
- readonly code: "not_multiple_of";
354
- readonly divisor: number;
355
- readonly input?: number | undefined;
356
- } | {
357
- readonly path: (string | number | null)[];
358
- readonly message: string;
359
- readonly code: "too_big";
360
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
361
- readonly maximum: number;
362
- readonly inclusive?: boolean;
363
- readonly exact?: boolean;
364
- readonly input?: import("hono/utils/types").JSONValue | undefined;
365
- } | {
366
- readonly path: (string | number | null)[];
367
- readonly message: string;
368
- readonly code: "too_small";
369
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
370
- readonly minimum: number;
371
- readonly inclusive?: boolean;
372
- readonly exact?: boolean;
373
- readonly input?: import("hono/utils/types").JSONValue | undefined;
374
- } | {
375
- readonly path: (string | number | null)[];
376
- readonly message: string;
377
- readonly code: "unrecognized_keys";
378
- readonly keys: string[];
379
- readonly input?: {
380
- [x: string]: import("hono/utils/types").JSONValue;
381
- } | undefined;
382
- } | {
383
- readonly path: (string | number | null)[];
384
- readonly message: string;
385
- readonly code: "invalid_union";
386
- readonly errors: [];
387
- readonly input?: import("hono/utils/types").JSONValue | undefined;
388
- readonly discriminator?: string | undefined;
389
- readonly inclusive: false;
390
- readonly matches: number[];
391
- } | {
392
- readonly path: (string | number | null)[];
393
- readonly message: string;
394
- readonly code: "invalid_union";
395
- readonly errors: ({
396
- readonly path: (string | number | null)[];
397
- readonly message: string;
398
- readonly code: "custom";
399
- readonly params?: Record<string, any> | undefined;
400
- readonly input?: import("hono/utils/types").JSONValue | undefined;
401
- } | any | any | {
402
- readonly path: (string | number | null)[];
403
- readonly message: string;
404
- readonly code: "invalid_format";
405
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
406
- readonly pattern?: string;
407
- readonly input?: string;
408
- } | {
409
- readonly path: (string | number | null)[];
410
- readonly message: string;
411
- readonly code: "invalid_type";
412
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
413
- readonly input?: import("hono/utils/types").JSONValue | undefined;
414
- } | {
415
- readonly path: (string | number | null)[];
416
- readonly message: string;
417
- readonly code: "invalid_value";
418
- readonly values: (string | number | boolean | null)[];
419
- readonly input?: import("hono/utils/types").JSONValue | undefined;
420
- } | {
421
- readonly path: (string | number | null)[];
422
- readonly message: string;
423
- readonly code: "not_multiple_of";
424
- readonly divisor: number;
425
- readonly input?: number | undefined;
426
- } | {
427
- readonly path: (string | number | null)[];
428
- readonly message: string;
429
- readonly code: "too_big";
430
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
431
- readonly maximum: number;
432
- readonly inclusive?: boolean;
433
- readonly exact?: boolean;
434
- readonly input?: import("hono/utils/types").JSONValue | undefined;
435
- } | {
436
- readonly path: (string | number | null)[];
437
- readonly message: string;
438
- readonly code: "too_small";
439
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
440
- readonly minimum: number;
441
- readonly inclusive?: boolean;
442
- readonly exact?: boolean;
443
- readonly input?: import("hono/utils/types").JSONValue | undefined;
444
- } | {
445
- readonly path: (string | number | null)[];
446
- readonly message: string;
447
- readonly code: "unrecognized_keys";
448
- readonly keys: string[];
449
- readonly input?: {
450
- [x: string]: import("hono/utils/types").JSONValue;
451
- } | undefined;
452
- } | {
453
- readonly path: (string | number | null)[];
454
- readonly message: string;
455
- readonly code: "invalid_union";
456
- readonly errors: [];
457
- readonly input?: import("hono/utils/types").JSONValue | undefined;
458
- readonly discriminator?: string | undefined;
459
- readonly inclusive: false;
460
- readonly matches: number[];
461
- } | any)[][];
462
- readonly input?: import("hono/utils/types").JSONValue | undefined;
463
- readonly discriminator?: string | undefined;
464
- readonly options?: (string | number | boolean | null)[] | undefined;
465
- readonly inclusive?: true;
466
- })[];
467
- readonly input?: import("hono/utils/types").JSONValue | undefined;
468
- } | {
469
- readonly path: (string | number | null)[];
470
- readonly message: string;
471
- readonly code: "invalid_format";
472
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
473
- readonly pattern?: string;
474
- readonly input?: string;
475
- } | {
476
- readonly path: (string | number | null)[];
477
- readonly message: string;
478
- readonly code: "invalid_type";
479
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
480
- readonly input?: import("hono/utils/types").JSONValue | undefined;
481
- } | {
482
- readonly path: (string | number | null)[];
483
- readonly message: string;
484
- readonly code: "invalid_value";
485
- readonly values: (string | number | boolean | null)[];
486
- readonly input?: import("hono/utils/types").JSONValue | undefined;
487
- } | {
488
- readonly path: (string | number | null)[];
489
- readonly message: string;
490
- readonly code: "not_multiple_of";
491
- readonly divisor: number;
492
- readonly input?: number | undefined;
493
- } | {
494
- readonly path: (string | number | null)[];
495
- readonly message: string;
496
- readonly code: "too_big";
497
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
498
- readonly maximum: number;
499
- readonly inclusive?: boolean;
500
- readonly exact?: boolean;
501
- readonly input?: import("hono/utils/types").JSONValue | undefined;
502
- } | {
503
- readonly path: (string | number | null)[];
504
- readonly message: string;
505
- readonly code: "too_small";
506
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
507
- readonly minimum: number;
508
- readonly inclusive?: boolean;
509
- readonly exact?: boolean;
510
- readonly input?: import("hono/utils/types").JSONValue | undefined;
511
- } | {
512
- readonly path: (string | number | null)[];
513
- readonly message: string;
514
- readonly code: "unrecognized_keys";
515
- readonly keys: string[];
516
- readonly input?: {
517
- [x: string]: import("hono/utils/types").JSONValue;
518
- } | undefined;
519
- } | {
520
- readonly path: (string | number | null)[];
521
- readonly message: string;
522
- readonly code: "invalid_union";
523
- readonly errors: [];
524
- readonly input?: import("hono/utils/types").JSONValue | undefined;
525
- readonly discriminator?: string | undefined;
526
- readonly inclusive: false;
527
- readonly matches: number[];
528
- } | {
529
- readonly path: (string | number | null)[];
530
- readonly message: string;
531
- readonly code: "invalid_union";
532
- readonly errors: ({
533
- readonly path: (string | number | null)[];
534
- readonly message: string;
535
- readonly code: "custom";
536
- readonly params?: Record<string, any> | undefined;
537
- readonly input?: import("hono/utils/types").JSONValue | undefined;
538
- } | any | any | {
539
- readonly path: (string | number | null)[];
540
- readonly message: string;
541
- readonly code: "invalid_format";
542
- readonly format: import("zod/v4/core").$ZodStringFormats | (string & {});
543
- readonly pattern?: string;
544
- readonly input?: string;
545
- } | {
546
- readonly path: (string | number | null)[];
547
- readonly message: string;
548
- readonly code: "invalid_type";
549
- readonly expected: import("zod/v4/core").$ZodInvalidTypeExpected;
550
- readonly input?: import("hono/utils/types").JSONValue | undefined;
551
- } | {
552
- readonly path: (string | number | null)[];
553
- readonly message: string;
554
- readonly code: "invalid_value";
555
- readonly values: (string | number | boolean | null)[];
556
- readonly input?: import("hono/utils/types").JSONValue | undefined;
557
- } | {
558
- readonly path: (string | number | null)[];
559
- readonly message: string;
560
- readonly code: "not_multiple_of";
561
- readonly divisor: number;
562
- readonly input?: number | undefined;
563
- } | {
564
- readonly path: (string | number | null)[];
565
- readonly message: string;
566
- readonly code: "too_big";
567
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
568
- readonly maximum: number;
569
- readonly inclusive?: boolean;
570
- readonly exact?: boolean;
571
- readonly input?: import("hono/utils/types").JSONValue | undefined;
572
- } | {
573
- readonly path: (string | number | null)[];
574
- readonly message: string;
575
- readonly code: "too_small";
576
- readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
577
- readonly minimum: number;
578
- readonly inclusive?: boolean;
579
- readonly exact?: boolean;
580
- readonly input?: import("hono/utils/types").JSONValue | undefined;
581
- } | {
582
- readonly path: (string | number | null)[];
583
- readonly message: string;
584
- readonly code: "unrecognized_keys";
585
- readonly keys: string[];
586
- readonly input?: {
587
- [x: string]: import("hono/utils/types").JSONValue;
588
- } | undefined;
589
- } | {
590
- readonly path: (string | number | null)[];
591
- readonly message: string;
592
- readonly code: "invalid_union";
593
- readonly errors: [];
594
- readonly input?: import("hono/utils/types").JSONValue | undefined;
595
- readonly discriminator?: string | undefined;
596
- readonly inclusive: false;
597
- readonly matches: number[];
598
- } | any)[][];
599
- readonly input?: import("hono/utils/types").JSONValue | undefined;
600
- readonly discriminator?: string | undefined;
601
- readonly options?: (string | number | boolean | null)[] | undefined;
602
- readonly inclusive?: true;
603
- })[];
604
- }, 400, "json">)>;
15
+ }, Response>;
605
16
  //# sourceMappingURL=jsonValidatorMiddleware.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/redoc-reef",
3
- "version": "0.140.0-next.7",
3
+ "version": "0.140.0-next.8",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,14 +33,14 @@
33
33
  "@opentelemetry/sdk-trace-web": "2.8.0",
34
34
  "@opentelemetry/semantic-conventions": "1.40.0",
35
35
  "@redocly/ajv": "8.18.0",
36
- "@redocly/api-docs": "0.5.0-next.5",
37
- "@redocly/config": "0.69.0",
36
+ "@redocly/api-docs": "0.5.0-next.6",
37
+ "@redocly/config": "0.69.1",
38
38
  "@redocly/markdoc": "0.7.0-beta.2",
39
39
  "@redocly/openapi-core": "2.72.1",
40
40
  "@redocly/portal-legacy-ui": "0.19.0",
41
41
  "@redocly/portal-plugin-mock-server": "0.25.0-next.2",
42
42
  "@redocly/realm-asyncapi-sdk": "0.17.0",
43
- "@redocly/theme": "0.72.0-next.4",
43
+ "@redocly/theme": "0.72.0-next.5",
44
44
  "@shikijs/transformers": "3.21.0",
45
45
  "@tanstack/react-query": "5.62.3",
46
46
  "@tanstack/react-table": "8.21.3",