@redocly/reef 0.133.0-next.0 → 0.133.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/cli/develop.js +1 -1
  3. package/dist/constants/l10n/langs/ar.js +1 -1
  4. package/dist/constants/l10n/langs/de.js +1 -1
  5. package/dist/constants/l10n/langs/en.js +1 -1
  6. package/dist/constants/l10n/langs/es.js +1 -1
  7. package/dist/constants/l10n/langs/fr.js +1 -1
  8. package/dist/constants/l10n/langs/hi.js +1 -1
  9. package/dist/constants/l10n/langs/it.js +1 -1
  10. package/dist/constants/l10n/langs/ja.js +1 -1
  11. package/dist/constants/l10n/langs/ko.js +1 -1
  12. package/dist/constants/l10n/langs/pl.js +1 -1
  13. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  14. package/dist/constants/l10n/langs/pt.js +1 -1
  15. package/dist/constants/l10n/langs/ru.js +1 -1
  16. package/dist/constants/l10n/langs/uk.js +1 -1
  17. package/dist/constants/l10n/langs/zh.js +1 -1
  18. package/dist/server/api-routes/helpers/enhance-context.js +1 -1
  19. package/dist/server/esbuild/esbuild.js +3 -3
  20. package/dist/server/esbuild/generate.d.ts +3 -0
  21. package/dist/server/esbuild/generate.js +8 -8
  22. package/dist/server/esbuild/plugins/api-request-handlers-resolver.js +1 -1
  23. package/dist/server/plugins/api-functions/index.js +1 -1
  24. package/dist/server/plugins/dev-onboarding/api/adapters/apigee/adapter.js +3 -3
  25. package/dist/server/plugins/dev-onboarding/api/routes/index.js +1 -1
  26. package/dist/server/plugins/dev-onboarding/api/routes/meta.d.ts +4 -0
  27. package/dist/server/plugins/dev-onboarding/api/routes/meta.js +1 -0
  28. package/dist/server/plugins/dev-onboarding/api/types.d.ts +1 -0
  29. package/dist/server/plugins/dev-onboarding/template/App.js +5 -5
  30. package/dist/server/plugins/dev-onboarding/template/CreateAppDialog.js +3 -3
  31. package/dist/server/plugins/dev-onboarding/template/components/CallbackUrl.d.ts +5 -0
  32. package/dist/server/plugins/dev-onboarding/template/components/CallbackUrl.js +17 -0
  33. package/dist/server/plugins/dev-onboarding/template/components/DialogStyledComponents.d.ts +1 -0
  34. package/dist/server/plugins/dev-onboarding/template/components/DialogStyledComponents.js +6 -2
  35. package/dist/server/plugins/dev-onboarding/template/components/EditCallbackUrlDialog.d.ts +8 -0
  36. package/dist/server/plugins/dev-onboarding/template/components/EditCallbackUrlDialog.js +1 -0
  37. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  38. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +6 -1
  39. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
  40. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +4 -1
  41. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
  42. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +4 -1
  43. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
  44. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +4 -1
  45. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
  46. package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.d.ts +1 -1
  47. package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.js +1 -1
  48. package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +23 -5
  49. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +5 -1
  50. package/dist/server/plugins/mcp/docs-mcp/utils.d.ts +1 -1
  51. package/dist/server/plugins/mcp/docs-mcp/utils.js +1 -1
  52. package/dist/server/plugins/mcp/index.js +1 -1
  53. package/dist/server/plugins/openapi-docs/ast-utils.js +2 -2
  54. package/dist/server/store.d.ts +1 -0
  55. package/dist/server/store.js +1 -1
  56. package/dist/server/types/plugins/common.d.ts +1 -0
  57. package/package.json +15 -15
@@ -1,6 +1,9 @@
1
1
  import type { McpToolHandler } from '../../types.js';
2
2
  declare const _default: {
3
- 'get-endpoints': McpToolHandler;
3
+ 'get-endpoints': McpToolHandler<{
4
+ name: string;
5
+ version?: string;
6
+ }>;
4
7
  };
5
8
  export default _default;
6
9
  //# sourceMappingURL=get-endpoints.d.ts.map
@@ -1 +1 @@
1
- import{loadApiDescription as s}from"./helpers/load-api-description.js";import{getEndpointsFromPaths as p}from"./utils.js";const c=async(n,r)=>{const{name:o}=n;let t;try{t=await s(o,r)}catch(i){return{content:[{type:"text",text:i.message}],isError:!0}}const e=p(t);return e.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",servers:t.servers||[],endpoints:e},null,2)}]}};var f={"get-endpoints":c};export{f as default};
1
+ import{loadApiDescription as p}from"./helpers/load-api-description.js";import{getEndpointsFromPaths as c}from"./utils.js";const a=async(n,r)=>{const{name:o,version:i}=n;let t;try{t=await p(o,r,i)}catch(s){return{content:[{type:"text",text:s.message}],isError:!0}}const e=c(t);return e.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",servers:t.servers||[],endpoints:e},null,2)}]}};var l={"get-endpoints":a};export{l as default};
@@ -1,6 +1,9 @@
1
1
  import type { McpToolHandler } from '../../types.js';
2
2
  declare const _default: {
3
- 'get-full-api-description': McpToolHandler;
3
+ 'get-full-api-description': McpToolHandler<{
4
+ name: string;
5
+ version?: string;
6
+ }>;
4
7
  };
5
8
  export default _default;
6
9
  //# sourceMappingURL=get-full-api-description.d.ts.map
@@ -1 +1 @@
1
- import{loadApiDescription as o}from"./helpers/load-api-description.js";const s=async(e,i)=>{const{name:n}=e;let t;try{t=await o(n,i)}catch(r){return{content:[{type:"text",text:r.message}],isError:!0}}return{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",definition:t},null,2)}]}};var c={"get-full-api-description":s};export{c as default};
1
+ import{loadApiDescription as s}from"./helpers/load-api-description.js";const p=async(e,i)=>{const{name:n,version:r}=e;let t;try{t=await s(n,i,r)}catch(o){return{content:[{type:"text",text:o.message}],isError:!0}}return{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",definition:t},null,2)}]}};var a={"get-full-api-description":p};export{a as default};
@@ -1,6 +1,9 @@
1
1
  import type { McpToolHandler } from '../../types.js';
2
2
  declare const _default: {
3
- 'get-security-schemes': McpToolHandler;
3
+ 'get-security-schemes': McpToolHandler<{
4
+ name: string;
5
+ version?: string;
6
+ }>;
4
7
  };
5
8
  export default _default;
6
9
  //# sourceMappingURL=get-security-schemes.d.ts.map
@@ -1 +1 @@
1
- import{loadApiDescription as n}from"./helpers/load-api-description.js";const c=async(t,r)=>{const{name:s}=t;let e;try{e=await n(s,r)}catch(i){return{content:[{type:"text",text:i.message}],isError:!0}}return{content:[{type:"text",text:JSON.stringify({name:e.info?.title,version:e.info?.version,securitySchemes:e.components?.securitySchemes||[],security:e.security||[]},null,2)}]}};var u={"get-security-schemes":c};export{u as default};
1
+ import{loadApiDescription as c}from"./helpers/load-api-description.js";const o=async(t,r)=>{const{name:s,version:i}=t;let e;try{e=await c(s,r,i)}catch(n){return{content:[{type:"text",text:n.message}],isError:!0}}return{content:[{type:"text",text:JSON.stringify({name:e.info?.title,version:e.info?.version,securitySchemes:e.components?.securitySchemes||[],security:e.security||[]},null,2)}]}};var y={"get-security-schemes":o};export{y as default};
@@ -1,4 +1,4 @@
1
1
  import type { OpenAPIDefinition } from '@redocly/openapi-docs';
2
2
  import type { McpToolContext } from '../../../types.js';
3
- export declare function loadApiDescription(name: string, context: McpToolContext): Promise<OpenAPIDefinition>;
3
+ export declare function loadApiDescription(name: string, context: McpToolContext, version?: string): Promise<OpenAPIDefinition>;
4
4
  //# sourceMappingURL=load-api-description.d.ts.map
@@ -1 +1 @@
1
- import{findApiDescriptionByName as c}from"../../utils.js";import{getApiDescriptionFromFs as t}from"../utils.js";async function f(r,i){const o=c(i.apiDescriptionsMap,r);if(!o)throw new Error(`No API found matching "${r}".`);const n=!!i?.config?.access?.requiresLogin,e=i?.config?.access?.rbac||{},s=await t({relativePath:o.relativePath||"",outdir:i.outdir||"",user:i.user,rbac:e,requiresLogin:n});if(!s)throw new Error(`No API found matching "${r}".`);return s}export{f as loadApiDescription};
1
+ import{findApiDescriptionByNameAndVersion as t}from"../../utils.js";import{getApiDescriptionFromFs as a}from"../utils.js";async function u(r,i,s){const o=t(i.apiDescriptionsMap,r,s);if(!o)throw new Error(`No API found matching "${r}".`);const e=!!i?.config?.access?.requiresLogin,c=i?.config?.access?.rbac||{},n=await a({relativePath:o.relativePath||"",outdir:i.outdir||"",user:i.user,rbac:c,requiresLogin:e});if(!n)throw new Error(`No API found matching "${r}".`);return n}export{u as loadApiDescription};
@@ -1,11 +1,29 @@
1
1
  declare const _default: {
2
2
  whoami: import("../../types.js").McpToolHandler;
3
3
  search: import("../../types.js").McpToolHandler;
4
- 'get-full-api-description': import("../../types.js").McpToolHandler;
5
- 'get-security-schemes': import("../../types.js").McpToolHandler;
6
- 'get-endpoint-info': import("../../types.js").McpToolHandler;
7
- 'get-endpoints': import("../../types.js").McpToolHandler;
8
- 'list-apis': import("../../types.js").McpToolHandler;
4
+ 'get-full-api-description': import("../../types.js").McpToolHandler<{
5
+ name: string;
6
+ version?: string;
7
+ }>;
8
+ 'get-security-schemes': import("../../types.js").McpToolHandler<{
9
+ name: string;
10
+ version?: string;
11
+ }>;
12
+ 'get-endpoint-info': import("../../types.js").McpToolHandler<{
13
+ name: string;
14
+ path: string;
15
+ method: string;
16
+ version?: string;
17
+ }>;
18
+ 'get-endpoints': import("../../types.js").McpToolHandler<{
19
+ name: string;
20
+ version?: string;
21
+ }>;
22
+ 'list-apis': import("../../types.js").McpToolHandler<{
23
+ filter?: string;
24
+ page?: number;
25
+ limit?: number;
26
+ }>;
9
27
  };
10
28
  export default _default;
11
29
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,10 @@
1
1
  import type { McpToolHandler } from '../../types.js';
2
2
  declare const _default: {
3
- 'list-apis': McpToolHandler;
3
+ 'list-apis': McpToolHandler<{
4
+ filter?: string;
5
+ page?: number;
6
+ limit?: number;
7
+ }>;
4
8
  };
5
9
  export default _default;
6
10
  //# sourceMappingURL=list-apis.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import type { OpenAPISchema, OpenAPIParameter, OpenAPIResponse, OpenAPIRequestBody, Referenced, OpenAPIDefinition } from '@redocly/openapi-docs/lib/types/open-api.js';
2
2
  import type { ApiDescriptionInfo } from '../types.js';
3
- export declare function findApiDescriptionByName(apiDescriptionsMap: Record<string, ApiDescriptionInfo>, name: string): ApiDescriptionInfo | undefined;
3
+ export declare function findApiDescriptionByNameAndVersion(apiDescriptionsMap: Record<string, ApiDescriptionInfo>, name: string, version?: string): ApiDescriptionInfo | undefined;
4
4
  export declare function filterApiDescriptionsByName(apiDescriptionsMap: ApiDescriptionInfo[], filter: string): ApiDescriptionInfo[];
5
5
  export declare function resolveRef<T>(ref: string, def?: OpenAPIDefinition): T | undefined;
6
6
  type ResolveSchemaRefsParams = {
@@ -1 +1 @@
1
- function a(e,o){if(o)return e[o.toLowerCase()]}function v(e,o){return Object.values(e).filter(({name:n})=>n.toLowerCase().includes(o.toLowerCase()))}function d(e,o){if(!o||!e?.startsWith("#/"))return;const n=e.slice(2).split("/");let t=o;for(const s of n)if(typeof t=="object"&&t!==null&&s in t)t=t[s];else return;return t}function l({schema:e,definition:o,visitedRefs:n=new Set,maxDepth:t=50,currentDepth:s=0}){if(!e)return;if(s>=t)return{type:"object",description:`Maximum resolution depth exceeded (${t})`};if("$ref"in e&&e.$ref){if(n.has(e.$ref))return{type:"object",description:`Circular reference detected: ${e.$ref}`,"x-circular-ref":e.$ref};const f=new Set(n);f.add(e.$ref);const u=d(e.$ref,o);return u?l({schema:u,definition:o,visitedRefs:f,maxDepth:t,currentDepth:s+1}):{type:"object",description:`Could not resolve reference: ${e.$ref}`,"x-unresolved-ref":e.$ref}}const r={...e};if(r.properties){const f={};for(const[u,i]of Object.entries(r.properties)){const p=l({schema:i,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:s+1});f[u]=p||i}r.properties=f}if(r.items&&typeof r.items=="object")if(Array.isArray(r.items))r.items=r.items.map(f=>l({schema:f,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:s+1})||f);else{const f=l({schema:r.items,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:s+1});f&&(r.items=f)}return["allOf","anyOf","oneOf"].forEach(f=>{const u=r[f];Array.isArray(u)&&(r[f]=u.reduce((i,p)=>{const m=l({schema:p,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:s+1});return m&&i.push(m),i},[]))}),r}function h({pathParams:e,opParams:o,definition:n}){return[...e,...o].reduce((t,s)=>{if(!s)return t;if("$ref"in s&&s.$ref){const r=d(s.$ref,n);return r&&t.push({...r,schema:"schema"in r&&r.schema?l({schema:r.schema,definition:n}):void 0}),t}return t.push({...s,schema:"schema"in s&&s.schema?l({schema:s.schema,definition:n}):void 0}),t},[])}function $(e,o){const n={...e};if(e.example!==void 0&&(n.example=e.example),!e.examples)return n;const t={};for(const[s,r]of Object.entries(e.examples))if("$ref"in r){const c=d(r.$ref,o);c&&(t[s]=c)}else t[s]=r;return n.examples=t,n}function x(e,o){if(!e)return;const n="$ref"in e&&e.$ref?d(e.$ref,o):e;if(!n)return;const t={...n};if("content"in n&&n.content){const s={};for(const[r,c]of Object.entries(n.content))s[r]={...$(c,o),schema:c.schema?l({schema:c.schema,definition:o}):void 0};t.content=s}return t}function w(e,o){return Object.entries(e).reduce((n,[t,s])=>{const r="$ref"in s&&s.$ref?d(s.$ref,o):s;if(!r)return n;const c={...r};if("content"in r&&r.content){const f={};for(const[u,i]of Object.entries(r.content))f[u]={...$(i,o),schema:i.schema?l({schema:i.schema,definition:o}):void 0};c.content=f}return n[t]=c,n},{})}export{v as filterApiDescriptionsByName,a as findApiDescriptionByName,h as resolveParameters,d as resolveRef,x as resolveRequestBody,w as resolveResponses,l as resolveSchemaRefs};
1
+ function $(e,o,s){if(!o)return;const n=o.toLowerCase();if(s)return e[`${n}@${s}`];const t=Object.values(e).filter(({name:r})=>r.toLowerCase()===n);if(t.length){if(t.length>1){const r=t.map(({version:c})=>c||"(no version)").join(", ");throw new Error(`Multiple versions of "${o}" found: ${r}. Specify a version to disambiguate.`)}return t[0]}}function v(e,o){return Object.values(e).filter(({name:s})=>s.toLowerCase().includes(o.toLowerCase()))}function d(e,o){if(!o||!e?.startsWith("#/"))return;const s=e.slice(2).split("/");let n=o;for(const t of s)if(typeof n=="object"&&n!==null&&t in n)n=n[t];else return;return n}function l({schema:e,definition:o,visitedRefs:s=new Set,maxDepth:n=50,currentDepth:t=0}){if(!e)return;if(t>=n)return{type:"object",description:`Maximum resolution depth exceeded (${n})`};if("$ref"in e&&e.$ref){if(s.has(e.$ref))return{type:"object",description:`Circular reference detected: ${e.$ref}`,"x-circular-ref":e.$ref};const f=new Set(s);f.add(e.$ref);const u=d(e.$ref,o);return u?l({schema:u,definition:o,visitedRefs:f,maxDepth:n,currentDepth:t+1}):{type:"object",description:`Could not resolve reference: ${e.$ref}`,"x-unresolved-ref":e.$ref}}const r={...e};if(r.properties){const f={};for(const[u,i]of Object.entries(r.properties)){const p=l({schema:i,definition:o,visitedRefs:new Set(s),maxDepth:n,currentDepth:t+1});f[u]=p||i}r.properties=f}if(r.items&&typeof r.items=="object")if(Array.isArray(r.items))r.items=r.items.map(f=>l({schema:f,definition:o,visitedRefs:new Set(s),maxDepth:n,currentDepth:t+1})||f);else{const f=l({schema:r.items,definition:o,visitedRefs:new Set(s),maxDepth:n,currentDepth:t+1});f&&(r.items=f)}return["allOf","anyOf","oneOf"].forEach(f=>{const u=r[f];Array.isArray(u)&&(r[f]=u.reduce((i,p)=>{const m=l({schema:p,definition:o,visitedRefs:new Set(s),maxDepth:n,currentDepth:t+1});return m&&i.push(m),i},[]))}),r}function h({pathParams:e,opParams:o,definition:s}){return[...e,...o].reduce((n,t)=>{if(!t)return n;if("$ref"in t&&t.$ref){const r=d(t.$ref,s);return r&&n.push({...r,schema:"schema"in r&&r.schema?l({schema:r.schema,definition:s}):void 0}),n}return n.push({...t,schema:"schema"in t&&t.schema?l({schema:t.schema,definition:s}):void 0}),n},[])}function a(e,o){const s={...e};if(e.example!==void 0&&(s.example=e.example),!e.examples)return s;const n={};for(const[t,r]of Object.entries(e.examples))if("$ref"in r){const c=d(r.$ref,o);c&&(n[t]=c)}else n[t]=r;return s.examples=n,s}function w(e,o){if(!e)return;const s="$ref"in e&&e.$ref?d(e.$ref,o):e;if(!s)return;const n={...s};if("content"in s&&s.content){const t={};for(const[r,c]of Object.entries(s.content))t[r]={...a(c,o),schema:c.schema?l({schema:c.schema,definition:o}):void 0};n.content=t}return n}function x(e,o){return Object.entries(e).reduce((s,[n,t])=>{const r="$ref"in t&&t.$ref?d(t.$ref,o):t;if(!r)return s;const c={...r};if("content"in r&&r.content){const f={};for(const[u,i]of Object.entries(r.content))f[u]={...a(i,o),schema:i.schema?l({schema:i.schema,definition:o}):void 0};c.content=f}return s[n]=c,s},{})}export{v as filterApiDescriptionsByName,$ as findApiDescriptionByNameAndVersion,h as resolveParameters,d as resolveRef,w as resolveRequestBody,x as resolveResponses,l as resolveSchemaRefs};
@@ -1 +1 @@
1
- import{fileURLToPath as M}from"node:url";import{dirname as P,join as p}from"node:path";import{logger as d}from"../../tools/notifiers/logger.js";import{reporter as y}from"../../tools/notifiers/reporter.js";import{isDefined as S}from"../../../utils/guards/is-defined.js";import{filterIgnoredApiDescriptions as b,getCleanedUpApiDescriptions as R,isMcpInRedirects as w}from"./utils.js";import{getDefaultToolSchemas as O}from"./docs-mcp/tool-schemas.js";import{telemetryTraceStep as A}from"../../../cli/telemetry/helpers/trace-step.js";const f="mcp-docs-server-handler",m=P(M(import.meta.url));async function T(){let i=!1;return{id:"mcp",async processContent(r,o){i||await A("build.plugin.mcp",async c=>{const t=await r.loadOpenApiDefinitions(o),n=await o.getConfig(),{mcp:s,redirects:l}=n;if(c?.setAttribute("config",JSON.stringify(s||{})),!(s?.hide||s?.docs?.hide)&&(w(l)&&await y.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),!s?.docs?.hide)){d.info("Configuring MCP servers...");const u=p(m,"./handlers/docs-mcp-handler.js"),g=R(b(t,s?.docs?.ignore||[])),a=new Map;for(const e of g)a.set(e.definition.info?.title?.toLowerCase()||"",{name:e.definition.info?.title||"",description:e.definition.info?.description||"",version:e.definition.info?.version||"",servers:e.definition.servers||[],relativePath:e.relativePath});const D=Object.values(n.products||{}).map(e=>e?.name).filter(S),h=!!n?.access?.requiresLogin,v=n?.access?.rbac||{},C=O({products:D,requiresLogin:h,rbac:v});r.addMcpTools(p(m,"./docs-mcp/tools/index.js"),C),await j({actions:r,handlerPath:u,apiDescriptionsMap:Object.fromEntries(a),mcpConfig:s}),i=!0}})},async afterRoutesCreated(r,o){const c=await o.getConfig(),{mcp:t}=c;r.setGlobalData({mcpData:{docs:{enabled:!t?.hide&&!t?.docs?.hide,name:t?.docs?.name}}})}}}var U=T;async function j({actions:i,handlerPath:r,apiDescriptionsMap:o,mcpConfig:c}){i.createRequestHandler(f,r),i.addApiRoute({slug:"/mcp",requestHandlerId:f,httpMethod:"all",getStaticData:async()=>({props:{config:{apiDescriptionsMap:o,mcpDocsServerName:c?.docs?.name||"Docs MCP Server"},serverOutDir:i.serverOutDir,tools:i.getMcpTools().map(({importPath:t,...n})=>n)}})}),d.info("Registered Docs MCP Server endpoint at /mcp")}export{f as MCP_DOCS_SERVER_HANDLER_ID,U as default,T as mcpServerPlugin};
1
+ import{fileURLToPath as y}from"node:url";import{dirname as S,join as m}from"node:path";import{logger as f}from"../../tools/notifiers/logger.js";import{reporter as b}from"../../tools/notifiers/reporter.js";import{isDefined as R}from"../../../utils/guards/is-defined.js";import{filterIgnoredApiDescriptions as w,getCleanedUpApiDescriptions as O,isMcpInRedirects as A}from"./utils.js";import{getDefaultToolSchemas as T}from"./docs-mcp/tool-schemas.js";import{telemetryTraceStep as j}from"../../../cli/telemetry/helpers/trace-step.js";const l="mcp-docs-server-handler",u=S(y(import.meta.url));async function E(){let e=!1;return{id:"mcp",async processContent(r,o){e||await j("build.plugin.mcp",async c=>{const t=await r.loadOpenApiDefinitions(o),n=await o.getConfig(),{mcp:s,redirects:g}=n;if(c?.setAttribute("config",JSON.stringify(s||{})),!(s?.hide||s?.docs?.hide)&&(A(g)&&await b.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),!s?.docs?.hide)){f.info("Configuring MCP servers...");const D=m(u,"./handlers/docs-mcp-handler.js"),h=O(w(t,s?.docs?.ignore||[])),a=new Map;for(const i of h){const p=i.definition.info?.title||"",d=i.definition.info?.version||"";a.set(`${p.toLowerCase()}@${d}`,{name:p,description:i.definition.info?.description||"",version:d,servers:i.definition.servers||[],relativePath:i.relativePath})}const v=Object.values(n.products||{}).map(i=>i?.name).filter(R),C=!!n?.access?.requiresLogin,M=n?.access?.rbac||{},P=T({products:v,requiresLogin:C,rbac:M});r.addMcpTools(m(u,"./docs-mcp/tools/index.js"),P),await L({actions:r,handlerPath:D,apiDescriptionsMap:Object.fromEntries(a),mcpConfig:s}),e=!0}})},async afterRoutesCreated(r,o){const c=await o.getConfig(),{mcp:t}=c;r.setGlobalData({mcpData:{docs:{enabled:!t?.hide&&!t?.docs?.hide,name:t?.docs?.name}}})}}}var B=E;async function L({actions:e,handlerPath:r,apiDescriptionsMap:o,mcpConfig:c}){e.createRequestHandler(l,r),e.addApiRoute({slug:"/mcp",requestHandlerId:l,httpMethod:"all",getStaticData:async()=>({props:{config:{apiDescriptionsMap:o,mcpDocsServerName:c?.docs?.name||"Docs MCP Server"},serverOutDir:e.serverOutDir,tools:e.getMcpTools().map(({importPath:t,...n})=>n)}})}),f.info("Registered Docs MCP Server endpoint at /mcp")}export{l as MCP_DOCS_SERVER_HANDLER_ID,B as default,E as mcpServerPlugin};
@@ -1,2 +1,2 @@
1
- import{getAstNodeByPointer as x,getLineColLocation as P}from"@redocly/openapi-core";import*as c from"yaml-ast-parser";import{combineUrls as A}from"@redocly/theme/core/utils";const K=(e,n,t,o)=>{const r=[];return e.forEach(s=>{const i=L(s,n,t);i.length===0&&r.push(o),r.push(...i)}),Array.from(new Set(r)).map(s=>A(o,s))},L=(e,n,t)=>{const o=E(e,n,3),r=f(o,n,s=>{const i=s.split("/");return i[1]==="paths"?i.slice(0,4).join("/"):null});return v(r,t)},k=(e,n)=>{const t=e.split("/"),o=t.length;for(let r=1;r<o;r++){const s=t.join("/"),i=[...n.matchAll(new RegExp(`[^a-zA-Z0-9]${s}[^a-zA-Z0-9]`,"g"))].filter(u=>u.index!==void 0).map(u=>u.index);if(i.length>0)return{pointer:s,indexes:i};t.pop()}return null},f=(e,n,t,o=new Set,r=[])=>{const s=[],i=n.getAst(c.safeLoad),u=t(e);if(u){s.push({pointer:u,trace:[e,...r]});const a=x(i,u,!1),l=u.split("/");a&&a.parent&&a.parent.key.value==="parameters"&&l[1]==="paths"&&m(a.parent.parent).forEach(d=>{if(d.key.value!=="parameters"){const y=`${l.slice(0,3).join("/")}/${d.key.value}`;s.push(...f(y,n,t,o,r))}})}r=[e,...r];const p=k(e,n.body);return p&&!o.has(p.pointer)&&(o.add(p.pointer),p.indexes.forEach(a=>{const l=g(a,n);s.push(...f(l,n,t,o,r))})),s},v=(e,n)=>e.map(t=>n[t.pointer]).filter(t=>typeof t<"u"),B=(e,n)=>{const t=n.body.split(`
2
- `);let o=0;for(let s=0;s<e-1;s++)t[s][0]==="\r"&&o++,o+=t[s].length+1;let r=0;for(;t[e-1][r]===" "||t[e-1][r]===" "||t[e-1][r]==="-";)o++,r++;return o},E=(e,n,t)=>{const o=B(e,n);return g(o,n,t)},g=(e,n,t)=>{const o=n.getAst(c.safeLoad),{nodePath:r}=h(o,e,t??0);return"#/"+r.join("/")},h=(e,n,t,o=[])=>{if(t&&o.length===t)return{node:e,nodePath:o};const r=m(e),s=r.findIndex(i=>{if(i.startPosition<=n&&i.endPosition>=n)return!0});if(s!==-1){const i=r[s],u=N(o,e,i,s);return h(i,n,t,u)}return{node:e,nodePath:o}};function m(e){switch(e?.kind){case c.Kind.MAPPING:return[e.key,e.value];case c.Kind.MAP:return e.mappings;case c.Kind.SEQ:return e?.items;default:return[]}}function N(e,n,t,o){return n?.kind===c.Kind.SEQ?[...e,o]:t?.kind===c.Kind.MAPPING&&t?.key?.value&&typeof t.key.value=="string"?[...e,t.key.value.replace(/\//g,"~1")]:e}function R(e,n){const t=P({pointer:e,source:n}),o={lineNumber:t.start.line,column:t.start.col},r=t.end?{lineNumber:t.end.line,column:t.end.col}:void 0;return{start:o,end:r}}export{h as getAstNodeByStartPosition,m as getChildNodes,E as getPointerByLine,g as getPointerByStartPosition,R as getPointerPosition,f as getPointerUsed,L as getRoutesByLine,K as getRoutesByLines,v as getRoutesWhereUsed,B as getStartPositionByLine};
1
+ import{getAstNodeByPointer as x,getLineColLocation as P}from"@redocly/openapi-core";import*as a from"yaml-ast-parser";import{combineUrls as A}from"@redocly/theme/core/utils";const I=(e,n,t,o)=>{const r=[];return e.forEach(s=>{const i=L(s,n,t);i.length===0&&r.push(""),r.push(...i)}),Array.from(new Set(r)).map(s=>A(o,s))},L=(e,n,t)=>{const o=S(e,n,3),r=f(o,n,s=>{const i=s.split("/");return i[1]==="paths"?i.slice(0,4).join("/"):null});return v(r,t)},k=(e,n)=>{const t=e.split("/"),o=t.length;for(let r=1;r<o;r++){const s=t.join("/"),i=[...n.matchAll(new RegExp(`[^a-zA-Z0-9]${s}[^a-zA-Z0-9]`,"g"))].filter(u=>u.index!==void 0).map(u=>u.index);if(i.length>0)return{pointer:s,indexes:i};t.pop()}return null},f=(e,n,t,o=new Set,r=[])=>{const s=[],i=n.getAst(a.safeLoad),u=t(e);if(u){s.push({pointer:u,trace:[e,...r]});const c=x(i,u,!1),l=u.split("/");c&&c.parent&&c.parent.key.value==="parameters"&&l[1]==="paths"&&m(c.parent.parent).forEach(d=>{if(d.key.value!=="parameters"){const y=`${l.slice(0,3).join("/")}/${d.key.value}`;s.push(...f(y,n,t,o,r))}})}r=[e,...r];const p=k(e,n.body);return p&&!o.has(p.pointer)&&(o.add(p.pointer),p.indexes.forEach(c=>{const l=g(c,n);s.push(...f(l,n,t,o,r))})),s},v=(e,n)=>e.map(t=>n[t.pointer]).filter(t=>typeof t<"u"),B=(e,n)=>{const t=n.body.split(`
2
+ `);let o=0;for(let s=0;s<e-1;s++)t[s][0]==="\r"&&o++,o+=t[s].length+1;let r=0;for(;t[e-1][r]===" "||t[e-1][r]===" "||t[e-1][r]==="-";)o++,r++;return o},S=(e,n,t)=>{const o=B(e,n);return g(o,n,t)},g=(e,n,t)=>{const o=n.getAst(a.safeLoad),{nodePath:r}=h(o,e,t??0);return"#/"+r.join("/")},h=(e,n,t,o=[])=>{if(t&&o.length===t)return{node:e,nodePath:o};const r=m(e),s=r.findIndex(i=>{if(i.startPosition<=n&&i.endPosition>=n)return!0});if(s!==-1){const i=r[s],u=E(o,e,i,s);return h(i,n,t,u)}return{node:e,nodePath:o}};function m(e){switch(e?.kind){case a.Kind.MAPPING:return[e.key,e.value];case a.Kind.MAP:return e.mappings;case a.Kind.SEQ:return e?.items;default:return[]}}function E(e,n,t,o){return n?.kind===a.Kind.SEQ?[...e,o]:t?.kind===a.Kind.MAPPING&&t?.key?.value&&typeof t.key.value=="string"?[...e,t.key.value.replace(/\//g,"~1")]:e}function K(e,n){const t=P({pointer:e,source:n}),o={lineNumber:t.start.line,column:t.start.col},r=t.end?{lineNumber:t.end.line,column:t.end.col}:void 0;return{start:o,end:r}}export{h as getAstNodeByStartPosition,m as getChildNodes,S as getPointerByLine,g as getPointerByStartPosition,K as getPointerPosition,f as getPointerUsed,L as getRoutesByLine,I as getRoutesByLines,v as getRoutesWhereUsed,B as getStartPositionByLine};
@@ -168,6 +168,7 @@ export declare class Store {
168
168
  createTemplate: (id: string, importPath: string) => string;
169
169
  addBrowserPlugin: (importPath: string) => void;
170
170
  createRequestHandler: (id: string, importPath: string) => string;
171
+ clearRequestHandlersByPrefix: (prefix: string) => void;
171
172
  registerServerPropsGetter: (id: string, importPath: string) => string;
172
173
  registerPagePropsGetter: (id: string, importPath: string) => void;
173
174
  writeRouteStaticData(route: RouteDetails, context: LifecycleContext): Promise<void>;
@@ -1 +1 @@
1
- import A from"@markdoc/markdoc";import{getPathnameForLocale as C}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as V}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as H}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as R}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as U}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as q}from"./utils/redirects/find-redirect.js";import{followRedirectChain as x}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ct="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#e=new Map;constructor({outdir:t,contentDir:s,serverMode:e=!1,serverOutDir:a}){this.#r=s,this.outdir=t,this.serverMode=e,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(t,s){const e=this.listeners.get(t);e?e.add(s):this.listeners.set(t,new Set([s]))}queueEvent=(t,s,...e)=>{this.#e.set(t+String(s),[t,s,...e])};runListeners=(t,s,...e)=>{for(const a of this.listeners.get(t)||new Set)s?a(s,...e):a(...e)};startPluginsRun(){this.clear(),this.#o=new Promise(t=>{this.#i=t})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const t of this.#e.values())this.runListeners(...t);this.#e.clear()}startEsbuildRun(){this.#n=new Promise(t=>{this.#c=t})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const t=R.instance(),s=await H(this.serverOutDir),e=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?t.canAccessFeature(D[a]):!0));this.#s={...s,tags:e}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=t=>{const s=this.globalData,e={...this.globalData,...t};this.globalData=e,JSON.stringify(e)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,e)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:t,context:s,deps:e,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(t,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of e?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of e?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of e?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of e?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(e?.routeSlugs&&r.partials?.length)for(const i of e.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(t){return(await t.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(t){return(await t.cache.load(".","asyncapi-docs")).data}setSearchEngine(t){this.searchEngine=t}setSearchFacets=t=>{this.searchFacets=t};setGlobalConfig=t=>{const s=Object.keys(t);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(t,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:e,unsetEnvVars:a,replacedValues:r}=J(t);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,e)};getConfig=()=>this.config;getGlobalConfig=t=>this.config[t];getSearchFacets=()=>this.searchFacets;addRedirect=(t,s,e={})=>{if(!R.instance().canAccessFeature("redirects")&&t!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(t).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=e,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=t=>{const s=h(t).toLowerCase(),e=q(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!e)return null;if(S(e.to)){const a=h(e.to).toLowerCase();if(!a.endsWith("*")&&x(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:e.to,type:e.type}};createSharedData=async(t,s,e)=>{if(e&&this.#t[t]===e)return t;const a=JSON.stringify(s),r=e??k(a);return this.#t[t]===r||(this.#t[t]=r,await B(t,a,this.outdir),this.queueEvent("shared-data-updated",t)),t};addRouteSharedData=(t,s,e)=>{const a=L(t),r=this.routesSharedData.get(a)||{};r[s]=e,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${t}, ${s}, ${e}`)};getRouteSharedDataByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=t=>{const s=this.getGlobalConfig(m)||{},e=this.routesPartials.get(t);if(!e||e.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(e),o=Array.from(e);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=t=>{const e={...U(t.fsPath,this.config.metadataGlobs),...t.metadata||{}};this.newRoutes.push({...t,metadata:e}),u.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,s,e)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=C(t,g,r.code,a);this.addRouteSharedData(o,s,e)}};addApiRoute=t=>{this.apiRoutes.push(t),u.verbose("Created API route %s",t.slug)};addMcpTools=(t,s)=>{for(const e of s)this.mcpToolHandlers.set(e.name,{...e,importPath:t}),u.verbose("Created MCP tool %s",e.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=t=>{this.middleware.push(t),u.verbose("Created middleware %s",t.id)};getRouteByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(t,s={})=>{const{followRedirect:e=!0}=s,a=this.getRedirect(t);return e&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(t)};hasRouteOrRedirectBySlug=t=>{if(this.routesBySlug.has(t))return!0;const s=this.getRedirect(t);if(!s)return!1;if(!S(s.to))return!0;const e=h(s.to);return this.routesBySlug.has(e)};getRoutesByTemplateId=t=>this.newRoutes.filter(s=>s.templateId===t);getAllRoutesForLocale=(t=g)=>{const s=Array.from(this.routesBySlug.values()),e=t.toLowerCase();return s.filter(a=>t===g?!K(a.fsPath):a.slug.startsWith(`/${e}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=t=>this.templates.get(t);getRequestHandler=t=>this.apiRoutesRequestHandlers.get(t);createTemplate=(t,s)=>(this.templates.set(t,s),t);addBrowserPlugin=t=>{this.browserPlugins.add(t)};createRequestHandler=(t,s)=>(this.apiRoutesRequestHandlers.set(t,s),t);registerServerPropsGetter=(t,s)=>(this.serverPropsGetters.set(t,s),t);registerPagePropsGetter=(t,s)=>{this.pagePropsGetters.set(t,s)};async writeRouteStaticData(t,s){const e=await this.resolveRouteStaticData(t,s,!1);e&&V(t.slug,e,this.outdir)}async resolveRouteStaticData(t,s,e){if(this.serverMode)return N(t.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[t.slug]},resource:f})},r=await t.getStaticData?.(t,a)||{},o=new Set(this.routesDynamicComponents.get(t.slug)),l=this.routesSharedData.get(t.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(t.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await t.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...t.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:e||!t.fsPath?null:await this.lifecycleContext?.fs.getLastModified(t.fsPath)}}addSsrComponents(t,s){if(!t?.length)return;const e=typeof t[0]=="string"?t.join(""):I(t);e&&(s==="head"?this.ssr.headTags.push(e):s==="preBody"?this.ssr.preBodyTags.push(e):this.ssr.postBodyTags.push(e))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const t=[];for(const[e,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[e].entries());t.push([e,r]);break;case"object":e==="config"&&t.push([e,await this.getConfigWithEnvPlaceholders()]),t.push([e,this[e]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(t);return s[E]=_.PLAN_GATES,s}static fromJson(t,s){const e=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":e[r]=new Map(t[r]);break;case"object":if(r==="config"){e.setGlobalConfig(t[r]);break}e[r]=t[r];break;default:throw new Error("Invalid format")}e.config[m]=Z(e.config[m]||{});const a=t[E];return a&&G("PLAN_GATES",a),e}async getConfigWithEnvPlaceholders(){const t=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:e}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=y(t,a);if(o||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=e}return t}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const t=Array.from(this.unsetEnvVars).filter(e=>!Y.includes(e));if(t.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${t.join(", ")}`;await w.panicOnBuildContentError(s)}}function Z(b){return M(b,t=>A.Ast.fromJSON(JSON.stringify(t)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Ct as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
1
+ import A from"@markdoc/markdoc";import{getPathnameForLocale as C}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as k}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as R}from"../utils/path/is-local-link.js";import{reporter as S}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as L}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as H}from"./utils/static-data.js";import{parseAndResolveMarkdoc as V}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as w}from"./entitlements/entitlements-provider.js";import{isL10nPath as q}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as K}from"./utils/globs.js";import{replaceEnvVariablesDeep as U}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as x}from"./utils/redirects/find-redirect.js";import{followRedirectChain as J}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ct="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#e=new Map;constructor({outdir:t,contentDir:s,serverMode:e=!1,serverOutDir:a}){this.#r=s,this.outdir=t,this.serverMode=e,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(t,s){const e=this.listeners.get(t);e?e.add(s):this.listeners.set(t,new Set([s]))}queueEvent=(t,s,...e)=>{this.#e.set(t+String(s),[t,s,...e])};runListeners=(t,s,...e)=>{for(const a of this.listeners.get(t)||new Set)s?a(s,...e):a(...e)};startPluginsRun(){this.clear(),this.#o=new Promise(t=>{this.#i=t})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const t of this.#e.values())this.runListeners(...t);this.#e.clear()}startEsbuildRun(){this.#n=new Promise(t=>{this.#c=t})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const t=w.instance(),s=await j(this.serverOutDir),e=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?t.canAccessFeature(D[a]):!0));this.#s={...s,tags:e}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=t=>{const s=this.globalData,e={...this.globalData,...t};this.globalData=e,JSON.stringify(e)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,e)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:t,context:s,deps:e,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await V(t,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of e?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of e?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of e?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of e?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(e?.routeSlugs&&r.partials?.length)for(const i of e.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(t){return(await t.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(t){return(await t.cache.load(".","asyncapi-docs")).data}setSearchEngine(t){this.searchEngine=t}setSearchFacets=t=>{this.searchFacets=t};setGlobalConfig=t=>{const s=Object.keys(t);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(t,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:e,unsetEnvVars:a,replacedValues:r}=U(t);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,e)};getConfig=()=>this.config;getGlobalConfig=t=>this.config[t];getSearchFacets=()=>this.searchFacets;addRedirect=(t,s,e={})=>{if(!w.instance().canAccessFeature("redirects")&&t!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(t).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=e,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=t=>{const s=h(t).toLowerCase(),e=x(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!e)return null;if(R(e.to)){const a=h(e.to).toLowerCase();if(!a.endsWith("*")&&J(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:e.to,type:e.type}};createSharedData=async(t,s,e)=>{if(e&&this.#t[t]===e)return t;const a=JSON.stringify(s),r=e??L(a);return this.#t[t]===r||(this.#t[t]=r,await B(t,a,this.outdir),this.queueEvent("shared-data-updated",t)),t};addRouteSharedData=(t,s,e)=>{const a=k(t),r=this.routesSharedData.get(a)||{};r[s]=e,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${t}, ${s}, ${e}`)};getRouteSharedDataByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=t=>{const s=this.getGlobalConfig(m)||{},e=this.routesPartials.get(t);if(!e||e.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(e),o=Array.from(e);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=t=>{const e={...K(t.fsPath,this.config.metadataGlobs),...t.metadata||{}};this.newRoutes.push({...t,metadata:e}),u.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,s,e)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=C(t,g,r.code,a);this.addRouteSharedData(o,s,e)}};addApiRoute=t=>{this.apiRoutes.push(t),u.verbose("Created API route %s",t.slug)};addMcpTools=(t,s)=>{for(const e of s)this.mcpToolHandlers.set(e.name,{...e,importPath:t}),u.verbose("Created MCP tool %s",e.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=t=>{this.middleware.push(t),u.verbose("Created middleware %s",t.id)};getRouteByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(t,s={})=>{const{followRedirect:e=!0}=s,a=this.getRedirect(t);return e&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(t)};hasRouteOrRedirectBySlug=t=>{if(this.routesBySlug.has(t))return!0;const s=this.getRedirect(t);if(!s)return!1;if(!R(s.to))return!0;const e=h(s.to);return this.routesBySlug.has(e)};getRoutesByTemplateId=t=>this.newRoutes.filter(s=>s.templateId===t);getAllRoutesForLocale=(t=g)=>{const s=Array.from(this.routesBySlug.values()),e=t.toLowerCase();return s.filter(a=>t===g?!q(a.fsPath):a.slug.startsWith(`/${e}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=t=>this.templates.get(t);getRequestHandler=t=>this.apiRoutesRequestHandlers.get(t);createTemplate=(t,s)=>(this.templates.set(t,s),t);addBrowserPlugin=t=>{this.browserPlugins.add(t)};createRequestHandler=(t,s)=>(this.apiRoutesRequestHandlers.set(t,s),t);clearRequestHandlersByPrefix=t=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(t)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(t,s)=>(this.serverPropsGetters.set(t,s),t);registerPagePropsGetter=(t,s)=>{this.pagePropsGetters.set(t,s)};async writeRouteStaticData(t,s){const e=await this.resolveRouteStaticData(t,s,!1);e&&H(t.slug,e,this.outdir)}async resolveRouteStaticData(t,s,e){if(this.serverMode)return N(t.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[t.slug]},resource:f})},r=await t.getStaticData?.(t,a)||{},o=new Set(this.routesDynamicComponents.get(t.slug)),l=this.routesSharedData.get(t.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(t.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await t.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...t.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:e||!t.fsPath?null:await this.lifecycleContext?.fs.getLastModified(t.fsPath)}}addSsrComponents(t,s){if(!t?.length)return;const e=typeof t[0]=="string"?t.join(""):I(t);e&&(s==="head"?this.ssr.headTags.push(e):s==="preBody"?this.ssr.preBodyTags.push(e):this.ssr.postBodyTags.push(e))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const t=[];for(const[e,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[e].entries());t.push([e,r]);break;case"object":e==="config"&&t.push([e,await this.getConfigWithEnvPlaceholders()]),t.push([e,this[e]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(t);return s[E]=_.PLAN_GATES,s}static fromJson(t,s){const e=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":e[r]=new Map(t[r]);break;case"object":if(r==="config"){e.setGlobalConfig(t[r]);break}e[r]=t[r];break;default:throw new Error("Invalid format")}e.config[m]=Z(e.config[m]||{});const a=t[E];return a&&G("PLAN_GATES",a),e}async getConfigWithEnvPlaceholders(){const t=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:e}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=y(t,a);if(o||!O(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=e}return t}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const t=Array.from(this.unsetEnvVars).filter(e=>!Y.includes(e));if(t.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${t.join(", ")}`;await S.panicOnBuildContentError(s)}}function Z(b){return M(b,t=>A.Ast.fromJSON(JSON.stringify(t)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Ct as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
@@ -155,6 +155,7 @@ export type ProcessContentActions = {
155
155
  addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
156
156
  getMcpTools: () => McpToolRegistration[];
157
157
  createRequestHandler: (id: string, importPath: string) => void;
158
+ clearRequestHandlersByPrefix: (prefix: string) => void;
158
159
  addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
159
160
  createTemplate: (id: string, importPath: string) => string;
160
161
  addBrowserPlugin: (importPath: string) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/reef",
3
- "version": "0.133.0-next.0",
3
+ "version": "0.133.0-next.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,22 +21,22 @@
21
21
  "@opentelemetry/api": "1.9.0",
22
22
  "@opentelemetry/context-zone": "2.0.1",
23
23
  "@opentelemetry/core": "2.0.1",
24
- "@opentelemetry/exporter-trace-otlp-http": "0.202.0",
24
+ "@opentelemetry/exporter-trace-otlp-http": "0.214.0",
25
25
  "@opentelemetry/instrumentation": "0.202.0",
26
26
  "@opentelemetry/instrumentation-http": "0.202.0",
27
- "@opentelemetry/resources": "2.0.1",
28
- "@opentelemetry/sdk-trace-node": "2.0.1",
29
- "@opentelemetry/sdk-trace-web": "2.0.1",
30
- "@opentelemetry/semantic-conventions": "1.34.0",
27
+ "@opentelemetry/resources": "2.6.1",
28
+ "@opentelemetry/sdk-trace-node": "2.6.1",
29
+ "@opentelemetry/sdk-trace-web": "2.6.1",
30
+ "@opentelemetry/semantic-conventions": "1.40.0",
31
31
  "@redocly/ajv": "8.18.0",
32
- "@redocly/openapi-core": "2.29.0",
32
+ "@redocly/openapi-core": "2.29.1",
33
33
  "@shikijs/transformers": "3.21.0",
34
34
  "@tanstack/react-query": "5.62.3",
35
35
  "@tanstack/react-table": "8.21.3",
36
36
  "@tanstack/react-virtual": "3.13.0",
37
37
  "@redocly/mcp-typescript-sdk": "1.18.1",
38
38
  "@wojtekmaj/react-datetimerange-picker": "6.0.0",
39
- "@xmldom/xmldom": "0.9.9",
39
+ "@xmldom/xmldom": "0.9.10",
40
40
  "ajv-formats": "^3.0.1",
41
41
  "anser": "^2.3.2",
42
42
  "babel-plugin-styled-components": "2.1.4",
@@ -90,14 +90,14 @@
90
90
  "xpath": "0.0.34",
91
91
  "yaml-ast-parser": "0.0.43",
92
92
  "zod": "^3.25.76",
93
- "@redocly/asyncapi-docs": "1.10.0-next.0",
94
- "@redocly/config": "0.48.0",
95
- "@redocly/graphql-docs": "1.10.0-next.0",
96
- "@redocly/openapi-docs": "3.21.0-next.0",
93
+ "@redocly/asyncapi-docs": "1.10.0-next.1",
94
+ "@redocly/config": "0.48.1",
95
+ "@redocly/graphql-docs": "1.10.0-next.1",
96
+ "@redocly/openapi-docs": "3.21.0-next.1",
97
97
  "@redocly/portal-legacy-ui": "0.16.0-next.0",
98
- "@redocly/portal-plugin-mock-server": "0.18.0-next.0",
99
- "@redocly/realm-asyncapi-sdk": "0.11.0-next.0",
100
- "@redocly/theme": "0.65.0-next.0"
98
+ "@redocly/portal-plugin-mock-server": "0.18.0-next.1",
99
+ "@redocly/realm-asyncapi-sdk": "0.11.0-next.1",
100
+ "@redocly/theme": "0.65.0-next.1"
101
101
  },
102
102
  "peerDependencies": {
103
103
  "react": "^19.2.4",