@redocly/reef 0.132.0-next.6 → 0.132.0-next.7
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 +20 -0
- package/dist/cli/telemetry/index.js +1 -1
- package/dist/client/App.js +1 -1
- package/dist/client/app/hooks/utils/match-banner-target.d.ts +23 -1
- package/dist/client/app/hooks/utils/match-banner-target.js +1 -1
- package/dist/client/mcp-tool-handlers-entry.d.ts +3 -0
- package/dist/client/mcp-tool-handlers-entry.js +1 -0
- package/dist/client/templates/asyncapi-docs/helpers.d.ts +1 -1
- package/dist/client/types/ai-search.d.ts +5 -3
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/markdoc/nodes/fence/index.js +1 -1
- package/dist/markdoc/nodes/index.d.ts +1 -1
- package/dist/markdoc/nodes/index.js +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/config/env-schema.d.ts +3 -3
- package/dist/server/config/env-schemas/api-urls.d.ts +3 -3
- package/dist/server/config/env-schemas/api-urls.js +1 -1
- package/dist/server/esbuild/esbuild.js +3 -3
- package/dist/server/esbuild/plugins/codegen/index.d.ts +1 -0
- package/dist/server/esbuild/plugins/codegen/index.js +7 -3
- package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.d.ts +7 -0
- package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.js +1 -0
- package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
- package/dist/server/plugins/default-theme/resolve-products-config.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/index.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-diagram-from-file.d.ts +4 -0
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-diagram-from-file.js +1 -0
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-native-md-link.js +1 -1
- package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +1 -1
- package/dist/server/plugins/markdown/markdoc/plugins/render-diagrams.d.ts +16 -0
- package/dist/server/plugins/markdown/markdoc/plugins/render-diagrams.js +1 -0
- package/dist/server/plugins/markdown/runtime-transform.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +7 -0
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.d.ts +4 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +10 -7
- package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +5 -10
- package/dist/server/plugins/mcp/docs-mcp/tools/search.js +3 -3
- package/dist/server/plugins/mcp/docs-mcp/tools/utils.d.ts +6 -3
- package/dist/server/plugins/mcp/docs-mcp/tools/utils.js +6 -6
- package/dist/server/plugins/mcp/docs-mcp/tools/whoami.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/whoami.js +1 -1
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
- package/dist/server/plugins/mcp/index.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.d.ts +13 -22
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/types.d.ts +24 -56
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +2 -2
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
- package/dist/server/store.d.ts +4 -1
- package/dist/server/store.js +1 -1
- package/dist/server/telemetry/index.js +1 -1
- package/dist/server/types/plugins/common.d.ts +10 -0
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/web-server/routes/otel/otel.js +1 -1
- package/dist/server/workers/types.d.ts +2 -2
- package/dist/server/workers/worker-pool.js +1 -1
- package/package.json +8 -8
- package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.d.ts +0 -4
- package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.js +0 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +0 -55
- package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +0 -1
- package/dist/server/plugins/mcp/handlers/mcp-request-handler.d.ts +0 -11
- package/dist/server/plugins/mcp/handlers/mcp-request-handler.js +0 -1
- package/dist/server/plugins/mcp/servers/base-server.d.ts +0 -17
- package/dist/server/plugins/mcp/servers/base-server.js +0 -1
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly requiredContext: readonly ContextKey[];
|
|
7
|
-
constructor();
|
|
8
|
-
protected executeAction(args: ToolArgsMap['get-security-schemes'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
|
|
9
|
-
}
|
|
1
|
+
import type { McpToolHandler } from '../../types.js';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
'get-security-schemes': McpToolHandler;
|
|
4
|
+
};
|
|
5
|
+
export default _default;
|
|
10
6
|
//# sourceMappingURL=get-security-schemes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
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};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { OpenAPIDefinition } from '@redocly/openapi-docs';
|
|
2
|
+
import type { McpToolContext } from '../../../types.js';
|
|
3
|
+
export declare function loadApiDescription(name: string, context: McpToolContext): Promise<OpenAPIDefinition>;
|
|
4
|
+
//# sourceMappingURL=load-api-description.d.ts.map
|
|
@@ -0,0 +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,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
declare const _default: {
|
|
2
|
+
whoami: import("../../types.js").McpToolHandler;
|
|
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;
|
|
9
|
+
};
|
|
10
|
+
export default _default;
|
|
8
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import o from"./list-apis.js";import r from"./get-endpoints.js";import t from"./get-endpoint-info.js";import i from"./get-security-schemes.js";import m from"./get-full-api-description.js";import p from"./search.js";import e from"./whoami.js";var d={...o,...r,...t,...i,...m,...p,...e};export{d as default};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly requiredContext: readonly ContextKey[];
|
|
7
|
-
constructor();
|
|
8
|
-
protected executeAction(args: ToolArgsMap['list-apis'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
|
|
9
|
-
}
|
|
1
|
+
import type { McpToolHandler } from '../../types.js';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
'list-apis': McpToolHandler;
|
|
4
|
+
};
|
|
5
|
+
export default _default;
|
|
10
6
|
//# sourceMappingURL=list-apis.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{filterApiDescriptionsByName as
|
|
1
|
+
import{filterApiDescriptionsByName as f}from"../utils.js";const x=async(a,l)=>{const{filter:i,page:n=1,limit:e=300}=a;let t=Object.values(l.apiDescriptionsMap);i&&(t=f(t,i));const s=(n-1)*e,o=s+e,r=Math.ceil(t.length/e),c=t.length;return t=t.slice(s,o),t.length===0?{content:[{type:"text",text:"No APIs available"}]}:{content:[{type:"text",text:JSON.stringify({items:t.map(({relativePath:g,...p})=>p),limit:e,total:c,page:n,totalPages:r})}]}};var m={"list-apis":x};export{m as default};
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly requiredContext: readonly ContextKey[];
|
|
7
|
-
constructor(products?: string[]);
|
|
8
|
-
register(options: DocsMcpToolRegistrationOptions): void;
|
|
9
|
-
protected executeAction(args: ToolArgsMap['search'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
|
|
10
|
-
}
|
|
1
|
+
import type { McpToolHandler } from '../../types.js';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
search: McpToolHandler;
|
|
4
|
+
};
|
|
5
|
+
export default _default;
|
|
11
6
|
//# sourceMappingURL=search.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{withPathPrefix as
|
|
1
|
+
import{withPathPrefix as l}from"@redocly/theme/core/utils";import{ServerRoutes as h}from"../../../../../constants/common.js";const d=async(c,t)=>{const{query:a,product:u}=c,p=JSON.stringify({query:a,product:u});let e=`${t.baseUrl}${l(h.SEMANTIC_SEARCH)}`;e.startsWith("http://")&&(e=e.replace(/^http:\/\//,"https://"));const o=t.user.idpAccessToken?`authorization=${String(t.user.idpAccessToken).replace(/^Bearer /,"")}`:"";try{const s=await fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...o?{Cookie:o}:{}},body:p});if(!s.ok)return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0};const r=await s.json();if(!r||r.length===0)return{content:[{type:"text",text:"No results found."}]};const i=r.map(n=>`### [${n.title}](${new URL(n.url,t.baseUrl).toString()})
|
|
2
2
|
|
|
3
|
-
${
|
|
3
|
+
${n.content}
|
|
4
4
|
`).join(`
|
|
5
5
|
|
|
6
|
-
`).trim();return{content:[{type:"text",text:
|
|
6
|
+
`).trim();return{content:[{type:"text",text:i.length?i:"No results found."}]}}catch{return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0}}};var m={search:d};export{m as default};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { OpenAPIDefinition, OpenAPIOperation } from '@redocly/openapi-docs';
|
|
2
2
|
import type { SearchItemData } from '@redocly/theme/core/types';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ApiFunctionsUser, RbacConfig } from '@redocly/config';
|
|
4
|
+
import type { McpEndpoint } from '../../types';
|
|
4
5
|
export declare function isMcpEndpoint(value: unknown): value is McpEndpoint;
|
|
5
6
|
type EndpointInfo = Pick<OpenAPIOperation, 'summary' | 'description' | 'security'> & {
|
|
6
7
|
method: string;
|
|
@@ -8,10 +9,12 @@ type EndpointInfo = Pick<OpenAPIOperation, 'summary' | 'description' | 'security
|
|
|
8
9
|
};
|
|
9
10
|
export declare function getEndpointsFromPaths(def: OpenAPIDefinition): EndpointInfo[];
|
|
10
11
|
export declare function processDocuments(documents: Record<string, SearchItemData[]>, outdir: string): string;
|
|
11
|
-
export declare function getApiDescriptionFromFs({ relativePath, outdir,
|
|
12
|
+
export declare function getApiDescriptionFromFs({ relativePath, outdir, user, rbac, requiresLogin, }: {
|
|
12
13
|
relativePath: string;
|
|
13
14
|
outdir: string;
|
|
14
|
-
|
|
15
|
+
user: ApiFunctionsUser;
|
|
16
|
+
rbac?: RbacConfig;
|
|
17
|
+
requiresLogin?: boolean;
|
|
15
18
|
}): Promise<OpenAPIDefinition | undefined>;
|
|
16
19
|
export {};
|
|
17
20
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import y from"node:fs";import
|
|
1
|
+
import y from"node:fs";import d from"node:path";import{existsSync as D}from"node:fs";import{readFile as j}from"node:fs/promises";import{replaceFileExtension as O}from"../../../../plugins/openapi-docs/store-definition-bundles";import{PUBLIC_API_DEFINITIONS_FOLDER as b}from"../../../../constants/common";import{filterDataByAccessDeep as g}from"../../../../utils/rbac";import{checkEndpointAndDeleteXMcp as A}from"../../utils/xmcp-utils.js";import{MAX_DOCUMENTS_PER_CATEGORY as F}from"../../constants.js";function N(e){return typeof e=="object"&&e!==null&&"responses"in e&&typeof e.responses=="object"}function T(e){const{paths:s={}}=e,o=[];for(const[c,i]of Object.entries(s)){const r=!A(i,"docs");for(const[p,t]of Object.entries(i))r||!A(t,"docs")||o.push({path:c,method:p.toUpperCase(),summary:t.summary,description:t.description,security:t.security})}return o}function R(e,s){return Object.entries(e).map(([c,i])=>{if(!i||i.length===0)return"";const r=i.slice(0,F).map(p=>{const{document:t,highlight:f}=p,h=f?.title||(Array.isArray(t.title)?t.title[0]:t.title);let a=`Document: ${t.title}`;a+=`### [${h}](${t.url})
|
|
2
2
|
|
|
3
|
-
`;let
|
|
3
|
+
`;let m;if(t.url)try{let n=t.url.startsWith("/")?t.url.slice(1):t.url;const l=n.indexOf("#");l!==-1&&(n=n.substring(0,l));const u=d.extname(n);u&&(n=n.slice(0,-u.length));let E=n+".md";const x=d.join(s,E);y.existsSync(x)&&(m=y.readFileSync(x,"utf8"))}catch{}return m||(m=f?.text||(Array.isArray(t.text)?t.text[0]:t.text)),a+=m,t.facets&&(a+=`
|
|
4
4
|
|
|
5
5
|
**Categories:**
|
|
6
|
-
`,Object.entries(t.facets).forEach(([n,l])=>{
|
|
7
|
-
`})),
|
|
6
|
+
`,Object.entries(t.facets).forEach(([n,l])=>{a+=`- ${n}: ${l}
|
|
7
|
+
`})),a});return`## ${c}
|
|
8
8
|
|
|
9
|
-
${
|
|
9
|
+
${r}`}).join(`
|
|
10
10
|
|
|
11
|
-
`).trim()}async function U({relativePath:e,outdir:
|
|
11
|
+
`).trim()}async function U({relativePath:e,outdir:s,user:o,rbac:c={},requiresLogin:i=!1}){const r=d.join(s||"",b,O(e,".json"));if(!D(r))return;const t=await j(r,"utf-8"),f=JSON.parse(t);return g(f,{isAuthenticated:o?.isAuthenticated,email:o?.email,teams:o?.teams},c,i)}export{U as getApiDescriptionFromFs,T as getEndpointsFromPaths,N as isMcpEndpoint,R as processDocuments};
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly requiredContext: readonly ContextKey[];
|
|
7
|
-
constructor();
|
|
8
|
-
protected executeAction(_args: ToolArgsMap['whoami'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
|
|
9
|
-
}
|
|
1
|
+
import type { McpToolHandler } from '../../types.js';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
whoami: McpToolHandler;
|
|
4
|
+
};
|
|
5
|
+
export default _default;
|
|
10
6
|
//# sourceMappingURL=whoami.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
const s=async(i,e)=>e.user?.isAuthenticated?{content:[{type:"text",text:JSON.stringify({email:e.user.email,name:e.user.claims?.name,subject:e.user.claims?.sub,clientId:e.user.claims?.client_id,scope:e.user.claims?.scope,issuedAt:e.user.claims?.iat?new Date(Number(e.user.claims.iat)*1e3).toISOString():void 0,expiresAt:e.user.claims?.exp?new Date(Number(e.user.claims.exp)*1e3).toISOString():void 0})}],isError:!1}:{content:[{type:"text",text:JSON.stringify({error:"Not authenticated",message:"No valid authentication token found. Please authenticate first."})}],isError:!0};var r={whoami:s};export{r as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{toFetchResponse as R,toReqRes as w}from"fetch-to-node";import{createDocsMcpServer as y}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as C}from"../utils.js";import{createMethodNotAllowedError as D,withErrorHandling as v}from"./errors.js";import{McpServerType as A}from"../constants.js";import{constructInvalidTokenResponse as S,constructUnauthorizedResponse as T,handleMcpAuth as U,shouldHandleMcpAuth as b}from"../auth/auth-handlers.js";const L=async(o,e,p)=>{const t=!!e?.config?.access?.requiresLogin,a=e?.config?.access?.rbac||{};if(b(t,a)){const{isAuthenticated:s,isTokenValid:i,currentUser:n}=await U(o,e);if(!s)return T(new URL(o.url).origin);if(!i)return S();n&&(e.user=n)}let r;const d=async()=>{r&&(await r.cleanup(),r=void 0)};return await v(async()=>{if(o.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need register it in your MCP Client (VS Code, Cursor, Claude Code, etc.) using that URL: ${o.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(o.method!=="POST")return D();const s=p,i=s?.props?.config?.apiDescriptionsMap||{},n=s?.props?.config?.mcpDocsServerName||"Docs MCP server",{config:{mcp:u={}}}=e,l=C(i,e.user,a,t),f=e.config.products?Object.values(e.config.products).map(M=>M?.name):[],m=u.docs?.name||n;r=await y({name:m,tools:s?.props?.tools||[],context:{...e,outdir:e.outdir||"",baseUrl:e.baseUrl||new URL(o.url).origin,apiDescriptionsMap:l,products:f}});const g=await o.json(),{req:h,res:c}=w(o);return await r.transport.handleRequest(h,c,g),R(c)},A.Docs,d)};var O=L;export{O as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withPathPrefix as d}from"@redocly/theme/core/utils";import{importApiRoutesHandler as f}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as h}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as D}from"../../../persistence/kv/services/kv-service.js";import{envConfig as
|
|
1
|
+
import{withPathPrefix as d}from"@redocly/theme/core/utils";import{importApiRoutesHandler as f}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as h}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as D}from"../../../persistence/kv/services/kv-service.js";import{envConfig as s}from"../../../config/env-config.js";async function v(i,a,e){const t=a.get("auth"),r=await e.resolveRouteStaticData(i)||{},o=d(i.slug),{requestHandlers:c}=await f(e.serverOutDir),p=c[i.requestHandlerId],u=(await p()).default,l=async()=>await D.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:s.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:s.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),m=h({honoCtx:a,ctx:{user:{teams:t.teams,email:t.claims.email,claims:t.claims,idpAccessToken:t.idpAccessToken,idpId:t.claims.idpId,isAuthenticated:t.isAuthenticated},config:e.config,outdir:e.outdir,baseUrl:new URL(a.req.url).origin},telemetry:A,getKv:l}),n=await u(a.req.raw,m,{...r,props:{...r.props,routeSlug:o,outdir:e.outdir}});return n instanceof Response?n:typeof n=="string"?new Response(n,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}export{v as handleMcpRequest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fileURLToPath as
|
|
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,24 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
});
|
|
12
|
-
protected registerTools(): void;
|
|
13
|
-
protected getServerType(): McpServerType;
|
|
14
|
-
}
|
|
15
|
-
export declare function createDocsMcpServer({ name, baseUrl, headers, apiDescriptionsMap, outdir, accessInfo, products, }: {
|
|
1
|
+
import { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
2
|
+
import { StreamableHTTPServerTransport } from '@redocly/mcp-typescript-sdk/server/streamableHttp.js';
|
|
3
|
+
import type { McpToolSchema } from '../../../types';
|
|
4
|
+
import type { McpToolContext } from '../types.js';
|
|
5
|
+
export type DocsMcpServerInstance = {
|
|
6
|
+
server: McpServer;
|
|
7
|
+
transport: StreamableHTTPServerTransport;
|
|
8
|
+
cleanup: () => Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
export declare function createDocsMcpServer({ name, tools, context, }: {
|
|
16
11
|
name: string;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
outdir: string;
|
|
21
|
-
accessInfo: AccessInfo;
|
|
22
|
-
products: string[];
|
|
23
|
-
}): Promise<import("../types.js").McpServerInstance>;
|
|
12
|
+
tools: McpToolSchema[];
|
|
13
|
+
context: McpToolContext;
|
|
14
|
+
}): Promise<DocsMcpServerInstance>;
|
|
24
15
|
//# sourceMappingURL=docs-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{McpServer as p}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as l}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{logger as m}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as f,MCP_TOOL_WORKER_KEY as d}from"../../../workers/mcp-tool-worker-pool.js";async function v({name:e,tools:a,context:n}){const o=new p({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}}}),s=new l({sessionIdGenerator:void 0});for(const r of a){const t=async(i,c)=>{m.info(`MCP tool called: ${r.name}`);const u={toolName:r.name,args:i,context:g(n),extra:I(c)};return await f.exec(d,[u],{timeout:6e4})};o.tool(r.name,r.description,r.schema,t)}return await o.connect(s),{server:o,transport:s,cleanup:async()=>{s.close()}}}function I(e){return{sessionId:e.sessionId,authInfo:e.authInfo,requestId:e.requestId,requestInfo:e.requestInfo,_meta:e._meta}}function g(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,products:e.products}}export{v as createDocsMcpServer};
|
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import type { OpenAPIPath } from '@redocly/openapi-docs/src/types';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
2
|
+
import type { ApiFunctionsContext, ApiFunctionsContextMethods, PageStaticData } from '@redocly/config';
|
|
3
|
+
import type { CallToolResult, RequestId, RequestInfo, RequestMeta } from '@redocly/mcp-typescript-sdk/types.js';
|
|
4
|
+
import type { AuthInfo } from '@redocly/mcp-typescript-sdk/server/types.js';
|
|
5
5
|
import type { OpenAPIServer } from '@redocly/openapi-docs/lib/types/open-api.js';
|
|
6
6
|
import type { McpErrorCodes, McpServerType } from './constants';
|
|
7
|
-
import type {
|
|
7
|
+
import type { McpToolSchema } from '../../types';
|
|
8
8
|
type ObjectValues<T> = T[keyof T];
|
|
9
9
|
export type McpServerType = ObjectValues<typeof McpServerType>;
|
|
10
10
|
export type McpErrorCodeTypes = ObjectValues<typeof McpErrorCodes>;
|
|
11
|
-
export type AccessInfo = {
|
|
12
|
-
isAuthenticated: boolean;
|
|
13
|
-
email?: string;
|
|
14
|
-
teams?: string[];
|
|
15
|
-
rbac: RbacConfig;
|
|
16
|
-
requiresLogin: boolean;
|
|
17
|
-
};
|
|
18
11
|
export type ApiDescriptionInfo = {
|
|
19
12
|
name: string;
|
|
20
13
|
relativePath: string;
|
|
@@ -29,6 +22,8 @@ export type McpDocsStaticDataPropsConfig = {
|
|
|
29
22
|
export type McpDocsStaticData = PageStaticData & {
|
|
30
23
|
props: {
|
|
31
24
|
config: McpDocsStaticDataPropsConfig;
|
|
25
|
+
serverOutDir?: string;
|
|
26
|
+
tools?: McpToolSchema[];
|
|
32
27
|
};
|
|
33
28
|
};
|
|
34
29
|
export type McpPath = {
|
|
@@ -43,11 +38,6 @@ export type McpEndpoint = {
|
|
|
43
38
|
'x-mcp'?: XMcpConfig;
|
|
44
39
|
[key: string]: any;
|
|
45
40
|
};
|
|
46
|
-
export type McpServerInstance = {
|
|
47
|
-
readonly server: McpServer;
|
|
48
|
-
readonly transport: StreamableHTTPServerTransport;
|
|
49
|
-
cleanup(): Promise<void>;
|
|
50
|
-
};
|
|
51
41
|
export type McpPluginConfig = {
|
|
52
42
|
readonly hide: boolean;
|
|
53
43
|
readonly docs: {
|
|
@@ -71,51 +61,29 @@ export type McpUserInfo = {
|
|
|
71
61
|
exp?: number;
|
|
72
62
|
[key: string]: any;
|
|
73
63
|
};
|
|
74
|
-
export type ToolArgsMap = {
|
|
75
|
-
'list-apis': {
|
|
76
|
-
filter?: string;
|
|
77
|
-
page?: number;
|
|
78
|
-
limit?: number;
|
|
79
|
-
};
|
|
80
|
-
'get-endpoints': {
|
|
81
|
-
name: string;
|
|
82
|
-
};
|
|
83
|
-
'get-endpoint-info': {
|
|
84
|
-
name: string;
|
|
85
|
-
path: string;
|
|
86
|
-
method: string;
|
|
87
|
-
};
|
|
88
|
-
'get-security-schemes': {
|
|
89
|
-
name: string;
|
|
90
|
-
};
|
|
91
|
-
'get-full-api-description': {
|
|
92
|
-
name: string;
|
|
93
|
-
};
|
|
94
|
-
search: {
|
|
95
|
-
query: string;
|
|
96
|
-
product?: string;
|
|
97
|
-
};
|
|
98
|
-
whoami: Record<string, never>;
|
|
99
|
-
};
|
|
100
|
-
export type McpToolWorkerParams = {
|
|
101
|
-
[K in keyof ToolArgsMap]: {
|
|
102
|
-
toolName: K;
|
|
103
|
-
args: ToolArgsMap[K];
|
|
104
|
-
context: {
|
|
105
|
-
apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
|
|
106
|
-
outdir?: string;
|
|
107
|
-
accessInfo?: AccessInfo;
|
|
108
|
-
baseUrl?: string;
|
|
109
|
-
headers?: Record<string, string | string[] | undefined>;
|
|
110
|
-
products?: string[];
|
|
111
|
-
};
|
|
112
|
-
};
|
|
113
|
-
}[keyof ToolArgsMap];
|
|
114
64
|
export type SemanticSearchResult = {
|
|
115
65
|
title: string;
|
|
116
66
|
url: string;
|
|
117
67
|
content: string;
|
|
118
68
|
};
|
|
119
69
|
export type McpToolWorkerResponse = CallToolResult;
|
|
70
|
+
export type McpToolExtra = {
|
|
71
|
+
sessionId?: string;
|
|
72
|
+
authInfo?: AuthInfo;
|
|
73
|
+
requestId: RequestId;
|
|
74
|
+
requestInfo?: RequestInfo;
|
|
75
|
+
_meta?: RequestMeta;
|
|
76
|
+
};
|
|
77
|
+
export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | keyof ApiFunctionsContextMethods> & {
|
|
78
|
+
apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
|
|
79
|
+
products?: string[];
|
|
80
|
+
};
|
|
81
|
+
export type McpToolHandler<TArgs extends Record<string, unknown> = Record<string, unknown>> = (args: TArgs, context: McpToolContext, extra: McpToolExtra) => Promise<McpToolWorkerResponse>;
|
|
82
|
+
export type McpToolExecutionParams = {
|
|
83
|
+
toolName: string;
|
|
84
|
+
args: Record<string, unknown>;
|
|
85
|
+
context: McpToolContext;
|
|
86
|
+
extra: McpToolExtra;
|
|
87
|
+
};
|
|
120
88
|
export {};
|
|
121
89
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function executeMcpTool(params:
|
|
1
|
+
import type { McpToolExecutionParams, McpToolWorkerResponse } from '../types.js';
|
|
2
|
+
export declare function executeMcpTool(params: McpToolExecutionParams): Promise<McpToolWorkerResponse>;
|
|
3
3
|
//# sourceMappingURL=execute-mcp-tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{telemetry as s}from"../../../telemetry/index.js";import{mcpToolHandlers as p}from"../../../../client/mcp-tool-handlers-entry.js";async function w(o){s.initialize();const{toolName:e,args:c,context:a,extra:l}=o;try{const r=p[e];if(!r)throw new Error(`Unknown MCP tool: ${e}`);const{default:i}=await r(),n=i[e];if(!n)throw new Error(`MCP tool module does not export a handler for "${e}". Expected \`export default { '${e}': handler }\`.`);const t=await n(c,a,l);if(!f(t))throw new Error(`MCP tool "${e}" returned an invalid result.`);return t.isError?s.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:e,message:`${t.content.map(({text:d})=>d).join(" ")}`,stack:""}]):s.sendMcpToolCalledMessage([{object:"mcp_server",server_type:"docs",tool:e}]),t}catch(r){throw s.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:e,message:r instanceof Error?r.message:String(r),stack:r instanceof Error&&r.stack||""}]),r}}function f(o){return!o||typeof o!="object"?!1:Array.isArray(o.content)}export{w as executeMcpTool};
|
package/dist/server/store.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Node } from '@markdoc/markdoc';
|
|
2
2
|
import type { JSX } from 'react';
|
|
3
3
|
import type { CommonError, GlobalData } from '../types/index.js';
|
|
4
|
-
import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts, WildcardRedirectsTree, RedirectOptions } from './types';
|
|
4
|
+
import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts, WildcardRedirectsTree, RedirectOptions, McpToolRegistration, McpToolSchema } from './types';
|
|
5
5
|
import type { RedoclyConfig, RedirectConfig, CompilationError, PageStaticData } from '@redocly/config';
|
|
6
6
|
import type { SearchFacet } from '@redocly/theme/core/types';
|
|
7
7
|
import type { BundledDefinition as OpenApiBundledDefinition } from './plugins/openapi-docs/load-definition.js';
|
|
@@ -55,6 +55,7 @@ export declare class Store {
|
|
|
55
55
|
templates: Map<string, string>;
|
|
56
56
|
browserPlugins: Set<string>;
|
|
57
57
|
apiRoutesRequestHandlers: Map<string, string>;
|
|
58
|
+
mcpToolHandlers: Map<string, McpToolRegistration>;
|
|
58
59
|
serverPropsGetters: Map<string, string>;
|
|
59
60
|
pagePropsGetters: Map<string, string>;
|
|
60
61
|
listeners: Map<string, Set<(...args: any[]) => void>>;
|
|
@@ -149,6 +150,8 @@ export declare class Store {
|
|
|
149
150
|
addRoute: (route: PageRouteInit) => void;
|
|
150
151
|
addRouteSharedDataToAllLocales: (slug: string, dataKey: string, dataId: string) => void;
|
|
151
152
|
addApiRoute: (route: ApiRoute) => void;
|
|
153
|
+
addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
|
|
154
|
+
getMcpTools: () => McpToolRegistration[];
|
|
152
155
|
addMiddleware: (middleware: MiddlewareDetails) => void;
|
|
153
156
|
getRouteByFsPath: (relativePath: string) => PageRouteDetails | undefined;
|
|
154
157
|
getRouteBySlug: (slug: string, opts?: {
|
package/dist/server/store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import A from"@markdoc/markdoc";import{getPathnameForLocale as C}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as p}from"../constants/common.js";import{DEFAULT_TITLE as O}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as T}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as S}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 y}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as g}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{writeEnvVariable as _}from"./utils/envs/write-env-variable.js";import{envConfig 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"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ot="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;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}=S(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(y(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),g.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}),g.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,s,e)=>{const a=[p,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=C(t,p,r.code,a);this.addRouteSharedData(o,s,e)}};addApiRoute=t=>{this.apiRoutes.push(t),g.verbose("Created API route %s",t.slug)};addMiddleware=t=>{this.middleware.push(t),g.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)};slugHasRouteOrRedirect=t=>{if(this.routesBySlug.has(t))return!0;const s=this.getRedirect(t);if(!s)return!1;if(!y(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=p)=>{const s=Array.from(this.routesBySlug.values()),e=t.toLowerCase();return s.filter(a=>t===p?!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:u})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[t.slug]},resource:u})},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(f=>o.add(f));const u=this.sharedDataDeps.get(c);u&&u.forEach(f=>this.addRouteSharedData(t.slug,f,f))}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:O,...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]=G.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&&_("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}=S(t,a);if(o||!T(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,Ot 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 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{writeEnvVariable as _}from"./utils/envs/write-env-variable.js";import{envConfig 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"],Tt="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)};slugHasRouteOrRedirect=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]=G.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&&_("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,Tt as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AsyncApiRealmAPI as o}from"@redocly/realm-asyncapi-sdk";import{envConfig as e}from"../config/env-config.js";import{PACKAGE_NAME as t}from"../../config/product-gates.js";import{OTEL_TRACES_DEV_URL as i,TELEMETRY_ENABLED as s}from"../constants/common.js";class l extends o.Telemetry{constructor(){super(),this.updateCloudEventData(()=>({organizationId:e.ORGANIZATION_ID||"",organizationSlug:e.ORGANIZATION_SLUG||"",projectId:e.PROJECT_ID||"",projectSlug:"",origin:"realmApi",actor:{id:"Anonymous",object:"user",uri:""},source:"server"}))}initialize(r=!1){this.init({otel:{serviceName:"realm-server",serviceVersion:`${t}@${e.REDOCLY_PORTAL_VERSION||""}`,collectorTraceUrl:r?i:e.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",isProd:e.isProductionEnv,version:"1.0",tracerName:"server-telemetry",delayMillis:100},disabled:r?e.TELEMETRY_DEV_DEBUG!=="true":!s})}}const A=new l;export{A as telemetry};
|
|
1
|
+
import{AsyncApiRealmAPI as o}from"@redocly/realm-asyncapi-sdk";import{envConfig as e}from"../config/env-config.js";import{PACKAGE_NAME as t}from"../../config/product-gates.js";import{OTEL_TRACES_DEV_URL as i,TELEMETRY_ENABLED as s}from"../constants/common.js";class l extends o.Telemetry{constructor(){super(),this.updateCloudEventData(()=>({organizationId:e.ORGANIZATION_ID||"",organizationSlug:e.ORGANIZATION_SLUG||"",projectId:e.PROJECT_ID||"",projectSlug:e.PROJECT_SLUG||"",origin:"realmApi",actor:{id:"Anonymous",object:"user",uri:""},source:"server",env:e.redoclyEnv}))}initialize(r=!1){this.init({otel:{serviceName:"realm-server",serviceVersion:`${t}@${e.REDOCLY_PORTAL_VERSION||""}`,collectorTraceUrl:r?i:e.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",isProd:e.isProductionEnv,version:"1.0",tracerName:"server-telemetry",delayMillis:100},disabled:r?e.TELEMETRY_DEV_DEBUG!=="true":!s})}}const A=new l;export{A as telemetry};
|
|
@@ -115,6 +115,14 @@ export type ApiRoute = RouteDetails & {
|
|
|
115
115
|
httpMethod: ApiRouteMethod;
|
|
116
116
|
requestHandlerId: string;
|
|
117
117
|
};
|
|
118
|
+
export type McpToolSchema = {
|
|
119
|
+
name: string;
|
|
120
|
+
description: string;
|
|
121
|
+
schema: Record<string, unknown>;
|
|
122
|
+
};
|
|
123
|
+
export type McpToolRegistration = McpToolSchema & {
|
|
124
|
+
importPath: string;
|
|
125
|
+
};
|
|
118
126
|
export type MiddlewareDetails = {
|
|
119
127
|
id: string;
|
|
120
128
|
importPath: string;
|
|
@@ -144,6 +152,8 @@ export type ProcessContentActions = {
|
|
|
144
152
|
getSearchFacets: () => Map<string, SearchFacet>;
|
|
145
153
|
addRoute: (route: PageRouteInit) => void;
|
|
146
154
|
addApiRoute: (route: ApiRoute) => void;
|
|
155
|
+
addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
|
|
156
|
+
getMcpTools: () => McpToolRegistration[];
|
|
147
157
|
createRequestHandler: (id: string, importPath: string) => void;
|
|
148
158
|
addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
|
|
149
159
|
createTemplate: (id: string, importPath: string) => string;
|