@redocly/redoc-reef 0.135.0-next.6 → 0.135.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 +28 -0
- package/dist/cli/develop.js +1 -1
- package/dist/client/templates/openapi-docs/helpers.js +1 -1
- 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/server/api-routes/execute-api-route.js +1 -1
- package/dist/server/api-routes/import-api-routes-handlers.js +1 -1
- package/dist/server/constants/common.d.ts +0 -2
- package/dist/server/constants/common.js +1 -1
- package/dist/server/constants/plugins/openapi-docs.d.ts +0 -1
- package/dist/server/constants/plugins/openapi-docs.js +1 -1
- package/dist/server/esbuild/plugins/api-request-handlers-resolver.js +1 -1
- package/dist/server/esbuild/plugins/on-rebuild.d.ts +4 -4
- package/dist/server/plugins/api-functions/index.js +1 -1
- package/dist/server/plugins/catalog-classic/index.d.ts +0 -1
- package/dist/server/plugins/catalog-classic/index.js +1 -1
- package/dist/server/plugins/config-parser/loaders/redocly-config-loader.js +1 -1
- package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
- package/dist/server/plugins/lifecycle.js +2 -2
- package/dist/server/plugins/markdown/search/walk-sections.js +3 -1
- package/dist/server/plugins/mcp/constants.d.ts +1 -0
- package/dist/server/plugins/mcp/constants.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/codemode/build-tool-type-declarations.d.ts +4 -0
- package/dist/server/plugins/mcp/docs-mcp/codemode/build-tool-type-declarations.js +8 -0
- package/dist/server/plugins/mcp/docs-mcp/codemode/prompts.d.ts +5 -0
- package/dist/server/plugins/mcp/docs-mcp/codemode/prompts.js +4 -0
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +3 -0
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +2 -2
- package/dist/server/plugins/mcp/docs-mcp/tools/core/types.d.ts +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/execute.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/graphql/list-graphql-apis.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.js +3 -1
- package/dist/server/plugins/openapi-docs/index.js +1 -1
- package/dist/server/plugins/scorecard-classic/get-scorecard-config.d.ts +5 -0
- package/dist/server/plugins/scorecard-classic/index.js +1 -1
- package/dist/server/plugins/search/index.js +1 -1
- package/dist/server/plugins/sso/index.js +1 -1
- package/dist/server/store.d.ts +5 -1
- package/dist/server/store.js +1 -1
- package/dist/server/utils/ai-agent-detection.d.ts +6 -0
- package/dist/server/utils/ai-agent-detection.js +1 -1
- package/dist/server/web-server/routes/otel/otel.js +1 -1
- package/dist/server/web-server/routes/page-data.js +1 -1
- package/dist/server/web-server/utils.js +1 -1
- package/package.json +8 -8
- package/dist/server/plugins/catalog-classic/get-server-props.d.ts +0 -4
- package/dist/server/plugins/catalog-classic/get-server-props.js +0 -1
- package/dist/server/plugins/catalog-classic/get-template-path.d.ts +0 -2
- package/dist/server/plugins/catalog-classic/get-template-path.js +0 -1
- package/dist/server/plugins/mcp/docs-mcp/codemode/build-execute-tool-description.d.ts +0 -4
- package/dist/server/plugins/mcp/docs-mcp/codemode/build-execute-tool-description.js +0 -4
- package/dist/server/plugins/openapi-docs/get-server-props-custom-fields.d.ts +0 -11
- package/dist/server/plugins/openapi-docs/get-server-props-custom-fields.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{redocConfigSchema as m,rootRedoclyConfigSchema as t}from"@redocly/config";import p from"is-glob";import{I18N_DIR_NAME as d,L10N_DIR_NAME as u}from"../../../constants/common.js";import{CONFIG_FILE_NAME as f}from"../../../../constants/common.js";import{DEFAULT_SEARCH_ENGINE as A}from"../../../constants/plugins/search.js";import{deepMerge as F}from"../../../../utils/object/deep-merge.js";import{logger as b}from"../../../tools/notifiers/logger.js";import{EntitlementsProvider as C}from"../../../entitlements/entitlements-provider.js";import{readAndValidateConfig as h}from"./utils/read-and-validate-config.js";import{resolveExternalPlugins as v}from"../../../external-plugins/resolve-external-plugins.js";import{getPathForAllLocales as l}from"../../../fs/utils/get-path-for-all-locales.js";import{parseRbacConfig as y}from"../../../utils/rbac.js";import{RbacConfigLocation as E,validateRbacConfig as S}from"../../validate-rbac-config.js";const z=async(e,{fs:r},
|
|
1
|
+
import{redocConfigSchema as m,rootRedoclyConfigSchema as t}from"@redocly/config";import p from"is-glob";import{I18N_DIR_NAME as d,L10N_DIR_NAME as u}from"../../../constants/common.js";import{CONFIG_FILE_NAME as f}from"../../../../constants/common.js";import{DEFAULT_SEARCH_ENGINE as A}from"../../../constants/plugins/search.js";import{deepMerge as F}from"../../../../utils/object/deep-merge.js";import{logger as b}from"../../../tools/notifiers/logger.js";import{EntitlementsProvider as C}from"../../../entitlements/entitlements-provider.js";import{readAndValidateConfig as h}from"./utils/read-and-validate-config.js";import{resolveExternalPlugins as v}from"../../../external-plugins/resolve-external-plugins.js";import{getPathForAllLocales as l}from"../../../fs/utils/get-path-for-all-locales.js";import{parseRbacConfig as y}from"../../../utils/rbac.js";import{RbacConfigLocation as E,validateRbacConfig as S}from"../../validate-rbac-config.js";const z=async(e,{fs:r},s)=>{const a=await h(e,r,s,async c=>e===f?g(r.cwd,c?.plugins||[]):void 0);if(a?.access?.rbac){const c=await y(a.access.rbac);a.access.rbac=c,S(c,e===f?E.RootRedoclyYaml:void 0)}(a?.l10n||a?.i18n)&&(a.l10n=L(a),a.i18n=void 0);const i=F(a||{},{markdown:{partialsFolders:(a?.markdown?.partialsFolders||[]).flatMap(c=>l(c,r))}});return R({...i,configPath:e,ignore:I(a?.ignore,r)})};async function g(e,r){const s=await v(e,r),a=s.map(n=>n.config.schema?n.lifecyclePlugin.id:""),i={};for(const n of s){const o=n.lifecyclePlugin?.id;n.config.schema&&o&&t.properties&&(i[o]=n.config.schema)}return{...t,properties:{...i,...t.properties,openapi:m},$id:t.$id+a.join("")}}function R(e){const r=C.instance();return r.canAccessFeature("apiFunctions")||(e.apiFunctions=void 0),r.canAccessFeature("products")||(e.products=void 0),r.canAccessFeature("breadcrumbs")||(e.breadcrumbs={hide:!0}),r.canAccessFeature("seo")||(e.seo={llmstxt:{hide:!0}}),r.canAccessFeature("redirects")||(e.redirects={}),r.canAccessFeature("l10n")||(e.l10n=void 0),r.canAccessFeature("rbac")||e.access&&(e.access.rbac=void 0),r.canAccessFeature("sso")||e.access&&(e.access.sso=void 0),r.canAccessFeature("ssoDirect")||(e.ssoDirect=void 0),r.canAccessFeature("catalogClassic")||(e.catalog=void 0,e.catalogClassic=void 0),r.canAccessFeature("scorecard")||(e.scorecard=void 0,e.scorecardClassic=void 0),r.canAccessFeature("scorecards")||(e.scorecards=void 0),r.canAccessFeature("devOnboarding")||(e.developerOnboarding=void 0),r.canAccessFeature("analytics")||(e.analytics=void 0),r.canAccessFeature("removeAttribution")||(e.removeAttribution=void 0),r.canAccessFeature("mockServer")||(e.mockServer={off:!0}),r.canAccessFeature("advancedSearch")||e.search&&(e.search.engine=A),r.canAccessFeature("banner")||(e.banner=void 0),e}function I(e=[],r){return["static",...e].flatMap(s=>p(s)&&(s.startsWith("*")||s.startsWith(u)||s.startsWith("/"+u)||s.startsWith(d)||s.startsWith("/"+d))?s:l(s,r))}function L(e){return e.i18n&&b.warn("The `i18n` configuration is deprecated. Please use `l10n` instead."),e.l10n||e.i18n||{}}export{z as redoclyConfigLoader};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import w from"path";import{lintConfig as A,loadConfig as T,createConfigTypes as U}from"@redocly/openapi-core";import{deepMerge as $}from"../../../../../utils/object/deep-merge.js";import{logger as d}from"../../../../tools/notifiers/logger.js";import{BRANCH_ENV_PREFIX as L}from"../../../../../constants/common.js";import{sanitizeBranchName as x}from"../../../../utils/envs/sanitize-branch-name.js";import{envConfig as C}from"../../../../config/env-config.js";import{safeParsePartial as E}from"../../safe-parse.js";import{formatConfigProblem as B}from"../../format-error.js";import{ExternalResolver as j}from"../../../../fs/utils/external-ref-resolver.js";import{resolveMutuallyExclusiveProps as q}from"../../resolve-mutual-exclusion.js";function g(e,t,s,
|
|
1
|
+
import w from"path";import{lintConfig as A,loadConfig as T,createConfigTypes as U}from"@redocly/openapi-core";import{deepMerge as $}from"../../../../../utils/object/deep-merge.js";import{logger as d}from"../../../../tools/notifiers/logger.js";import{BRANCH_ENV_PREFIX as L}from"../../../../../constants/common.js";import{sanitizeBranchName as x}from"../../../../utils/envs/sanitize-branch-name.js";import{envConfig as C}from"../../../../config/env-config.js";import{safeParsePartial as E}from"../../safe-parse.js";import{formatConfigProblem as B}from"../../format-error.js";import{ExternalResolver as j}from"../../../../fs/utils/external-ref-resolver.js";import{resolveMutuallyExclusiveProps as q}from"../../resolve-mutual-exclusion.js";function g(e,t,s,o){t in e&&e[t]&&typeof e[t]=="string"&&(/^https?:\/\/.*/.test(e[t])||o(new Error(`Invalid ${s} URL: "${e[t]}". ${s} must start with "http://" or "https://".`)))}function N(e,t){if("access"in e&&e.access&&typeof e.access=="object"){const s=e.access;g(s,"logoutReturnUrl","access.logoutReturnUrl",t),g(s,"residency","access.residency",t);const o=["requiresLogin","logoutReturnUrl","residency","sso","rbac"];for(const a of o)a in s&&s[a]!==void 0&&a in e&&e[a]!==void 0&&t(new Error(`Property '${a}' is defined both at root level and in 'access' object. Please use 'access.${a}' to define this configuration.`))}}async function G(e,t,s,o){const u=t.getFileInfo(e)?.realRelativePath||e;async function c(){const l=new j(t),p=w.join(t.cwd,u),i=await T({configPath:p,externalRefResolver:l}),f=await o(i.resolvedConfig);if(f===void 0)return i.resolvedConfig;const P=[...i.document?.source?await A({config:i,externalConfigTypes:U(f,i)}):[],...i.document?.source?q(i.resolvedConfig,i.document?.source):[]];if(P.length>0)for(const b of P)s(new Error(B(b,t.cwd)));return i.resolvedConfig}const r=await t.exists(e)?await c():{},R=k(r),y=await o(r);g(r,"residency","Residency",s),g(r,"logoutReturnUrl","Logout return URL",s),N(r,s);let m=y?E(y,r):r;const{env:h}=m;if(h){const l=C.REDOCLY_ENV,p=h[l]||{},i=C.PUBLIC_REDOCLY_BRANCH_NAME||"",f=i?x(i):"",v=f&&h[`${L}${f}`]||{};m=$(m,v,p)}const n=I(m,R);if(n.imports&&n.imports.length>0){d.warn("The 'imports' property is deprecated. Please use 'plugins' property instead.");const l=new Set([...n.plugins||[],...n.imports.map(p=>w.posix.join(p,"plugin.js"))]);n.plugins=Array.from(l),delete n.imports}if(n.catalog&&(d.warn("The 'catalog' property is deprecated. Please use 'catalogClassic' property instead."),n.catalogClassic={...n.catalog},delete n.catalog),n.scorecard&&(d.warn("The 'scorecard' property is deprecated. Please use 'scorecardClassic' property instead."),n.scorecardClassic=n.scorecard,delete n.scorecard),n.search?.ai){d.warn("The 'search.ai' property is deprecated. Please use 'aiAssistant' property instead.");const l={...n.search?.ai,...n.aiAssistant,suggestions:n.aiAssistant?.suggestions?.length?n.aiAssistant.suggestions:n.search?.ai.suggestions||[]};n.aiAssistant=l,delete n.search.ai}return _(n)}function _(e){const t={...e},o={..."access"in e&&e.access&&typeof e.access=="object"?e.access:{}},a=["requiresLogin","logoutReturnUrl","residency","sso","idps","rbac"],u=[];for(const c of a){const r=t[c];r!==void 0&&(u.push(c),c==="requiresLogin"&&o.requiresLogin===void 0&&(o.requiresLogin=r),c==="logoutReturnUrl"&&o.logoutReturnUrl===void 0&&(o.logoutReturnUrl=r),c==="residency"&&o.residency===void 0&&(o.residency=r),c==="sso"&&o.sso===void 0&&(o.sso=r),c==="idps"&&o.idps===void 0&&(o.idps=r),c==="rbac"&&o.rbac===void 0&&(o.rbac=r),delete t[c])}return u.length>0&&d.warn(`The following properties at root level are deprecated: ${u.join(", ")}. Please move them to the 'access' object.`),Object.keys(o).length>0&&(t.access=o),t}function k(e){if(!e.theme)return[];d.warn("The 'theme' property in redocly.yaml is deprecated. Please move all of the properties from 'theme' to the root of the config.");const t=[];for(const s of Object.keys(e.theme))e[s]==null?t.push(s):d.warn(`Detected both '${s}' and 'theme.${s}' properties in redocly.yaml. The 'theme.${s}' property will be ignored and needs to be removed or merged into the '${s}'.`);return t}function I(e,t){if(!e.theme||t.length===0)return e;const s={...e};for(const o of t)s[o]=e.theme[o];return delete s.theme,s}export{_ as ensureAccessBackwardsCompatibility,G as readAndValidateConfig};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
`+
|
|
1
|
+
import B from"@redocly/portal-plugin-mock-server";import _ from"path";import{REDOCLY_ROUTE_RBAC as x}from"@redocly/config";import{combineUrls as v,withPathPrefix as N}from"@redocly/theme/core/utils";import{VERSION_SEPARATOR as L}from"../constants/common.js";import{removeTrailingSlash as T}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as k}from"../../utils/url/remove-leading-slash.js";import{isTruthy as j}from"../../utils/guards/is-truthy.js";import{normalizeRouteSlug as F}from"../../utils/path/normalize-route-slug.js";import{slash as q}from"../../utils/path/slash.js";import{parsePathVersions as V}from"../../utils/path/parse-path-versions.js";import{reporter as b}from"../tools/notifiers/reporter.js";import{logger as h}from"../tools/notifiers/logger.js";import{envConfig as S}from"../config/env-config.js";import{shaDirPathShort as $}from"../utils/crypto/sha-dir-path-short.js";import{writeServerRebuildTrigger as M}from"../esbuild/generate.js";import{customPagesPlugin as z}from"../../server/plugins/pages/index.js";import{openAPIDocsPlugin as H}from"../../server/plugins/openapi-docs/index.js";import{asyncAPIDocsPlugin as I}from"../../server/plugins/asyncapi-docs/index.js";import{configParserPlugin as U}from"./config-parser/index.js";import{markdownPlugin as G}from"./markdown/index.js";import{generateBrowserPluginsModule as W,generateClientRoutes as K,generateTemplatesModule as Y}from"../esbuild/generate.js";import{graphqlDocsPlugin as J}from"./graphql-docs/index.js";import{searchPlugin as Q}from"./search/index.js";import{defaultThemePlugin as X}from"./default-theme/index.js";import{apiKeyMgmtPlugin as Z}from"./dev-onboarding/index.js";import{apiFunctionsPlugin as ee}from"./api-functions/index.js";import{scorecardClassicPlugin as te}from"./scorecard-classic/index.js";import{lintPlugin as oe}from"./lint/index.js";import{resolveExternalPlugins as ie}from"../external-plugins/resolve-external-plugins.js";import{sidebarsPlugin as re}from"./sidebars/index.js";import{l10nPlugin as ne}from"./l10n/index.js";import{validateRedirects as se}from"../utils/redirects/validate-redirects.js";import{analyticsPlugins as ae}from"./analytics/index.js";import{sitemapPlugin as le}from"./sitemap/index.js";import{entitlementsPlugin as ue}from"./entitlements/index.js";import{getBilledPagesCount as ce,slug as fe}from"../utils/index.js";import{telemetry as me}from"../../cli/telemetry/index.js";import{telemetryTraceStep as E}from"../../cli/telemetry/helpers/trace-step.js";import{EntitlementsProvider as D}from"../entitlements/entitlements-provider.js";import{enforceLoginPlugin as de}from"./enforce-login/index.js";import{ssoPlugin as pe}from"./sso/index.js";import{Cache as ge}from"../fs/cache.js";import{ContentFs as Pe}from"../fs/content-fs.js";import{findProductBySlug as he}from"../utils/product.js";import{parseBaseName as ye}from"./utils.js";import{isRouteReserved as Re}from"./get-reserved-routes.js";import{catalogClassicPlugin as we}from"./catalog-classic/index.js";import{arazzoDocsPlugin as Ce}from"./arazzo-docs/index.js";const ve=[U,de,pe,X,ne,G,H,I,Ce,te,oe,ee,z,J,Z,we,{importPath:"./catalog-entities/plugin.js",loadCondition:()=>S.NEW_CATALOG_ENABLED??!1},{importPath:"./scorecards/plugin.js",loadCondition:()=>S.NEW_SCORECARDS_ENABLED??!1},{importPath:"./mcp/index.js",loadCondition:()=>D.instance().canAccessFeature("mcp")},re,le,ue,Q,B,...ae];async function Ct(t,e=ve){return await E("build.plugins_init",async()=>{const r=[],w=D.instance(),y={};for(const s of e){let d;if("loadCondition"in s){if(!s.loadCondition())continue;const o=await import(s.importPath);if(!o.default||typeof o.default!="function"){await b.panicOnBuild(`Dynamic plugin ${s.importPath} does not export a default export or it is not a function`);continue}d=o.default}else d=s;const R=await d(t);for(const[o,l]of Object.entries(R.loaders||{}))y[o]&&await b.panicOnBuild(`Duplicate loader with name ${o}`),y[o]=l;(!R.requiredEntitlements||R.requiredEntitlements?.every(o=>w.canAccessFeature(o)))&&r.push(R)}const u=new Pe(t.contentDir);await u.ready;const m=new ge(u);return m.setLoaders(y),h.verbose("All plugins instantiated"),{pluginInstances:r,lifecycleContext:Se(u,m)}})}function O(t){h.verbose("Generating templates"),E("build.write_client_entries",()=>{Y(t),W(t),K(t)})}async function be(t){const e=t.getAllRoutes();ce(e)||await b.panicOnBuild("No routes created by plugins. Please check your project configuration.")}async function vt(t,e,r,w={}){const y=D.instance();try{await E("build.plugins_run",async()=>{e.startPluginsRun();const u=S.isDevelopMode&&e.buildRevision>0,m=u?Array.from(e.apiRoutesRequestHandlers.keys()).sort().join(","):"";let s=[];await E("build.plugins_process_content",async o=>{for(const i of t){const a=h.startTiming();await i.processContent?.(e,r),h.verboseTime(a,`processContent for ${i.id}`)}s=(await ie(e.contentDir,e.config.plugins)).map(i=>i.lifecyclePlugin).filter(i=>j(i)&&(!i.requiredEntitlements||i.requiredEntitlements?.every(a=>y.canAccessFeature(a)))),r.cache.setLoaders(Object.fromEntries(s.flatMap(i=>Object.entries(i.loaders||{}))));for(const i of s){const a=h.startTiming();await i.processContent?.(e,r),h.verboseTime(a,`processContent for ${i.id}`)}o?.setAttribute("externalPluginsProcessed",s.length.toString())});const d=await Ee(e,r),R=[...t,...s];if(O(e),S.isDevelopMode?await e.userCodeReady:e.buildRevision++,await E("build.plugins_after_routes_created",async()=>{for(const o of R){const l=h.startTiming();await o.afterRoutesCreated?.(e,d),h.verboseTime(l,`afterRoutesCreated for ${o.id}`)}}),se(e),await e.reportUnsetEnvVars(),await be(e),O(e),u){const o=Array.from(e.apiRoutesRequestHandlers.keys()).sort().join(",");m!==o&&(e.markRequestHandlersEntryOutdated(),M(e.serverOutDir))}})}catch(u){const m="Unhandled error in plugin. "+u.message+`
|
|
2
|
+
`+u.stack;me.sendCliErrorCaughtMessage({message:m}),w.failFast?await b.panic(m):await b.panicOnBuild(m)}finally{e.finishPluginsRun()}}async function Ee(t,e){const{cache:r,fs:w}=e,y=await e.getConfig(),u=Object.values(y.products||{}),m=(await r.load("versions-config","versions-config")).data,s=(await r.load("content-slugs","content-slugs")).data;for(const{duplicateInAllLocales:o,slugSuffix:l,sharedData:i=[],redirectFrom:a=[],...c}of t.newRoutes){const f=F(c.slug?c.slug:d(c.fsPath)),g=T(l?v(f,l):f),n={...c,[x]:{slug:g,fsPath:c.fsPath},slug:g,baseSlug:f,versions:R(c.fsPath,l),product:he(u,g,d)};Re(g,y)&&await b.panicOnBuildContentError(`Route "${g}" is reserved and cannot be used. Please choose a different slug for "${c.fsPath}".`),t.routesByFsPath.set(n.fsPath,n.slug),t.routesBySlug.set(n.slug,n);for(const{key:P,id:p}of i)t.addRouteSharedData(n.slug,P,p);for(const P of a)t.addRedirect(P.from,{type:P.type,to:n.slug});if(o)for(const P of w.localeFolders){const p={...n,slug:"/"+P.toLowerCase()+n.slug};t.routesByFsPath.set(p.fsPath,p.slug),t.routesBySlug.set(p.slug,p);for(const{key:C,id:A}of i)t.addRouteSharedData(p.slug,C,A);for(const C of a){const A=v(w.localizationFolder,P,C.from);t.addRedirect(A,{type:C.type,to:p.slug},{trackOriginalSource:!1})}}}return t.newRoutes=[],{...e,slugify:d};function d(o){const l=q(o).replace(new RegExp("^(@i18n|@l10n)\\/"),""),i=s.fileSlugs.get(l)||s.dirSlugs.get(T(l));if(i)return i;const{baseName:a,isIndexFile:c}=ye(o);let f=_.dirname(o.replace(new RegExp("^(@i18n|@l10n)\\/"),""));return f=f==="."?"/":f,v("/",fe(c?f:v(f,a)),"/")}function R(o,l=""){const i=V(o);if(!i?.versionName)return;const{versionFolderPath:a,filePathInVersion:c,versionName:f}=i,g=m.get(a);if(g)return g.versions.map(n=>{const P=g.defaultVersion===n.version,p=k(v(a,L+n.version,c)),C=d(p);return{version:n.version,label:n.name||n.version,link:F(v(C,l)),default:P,active:f===n.version,folderId:$(`${a}`)}})}}function Se(t,e){return{fs:t,cache:e,getConfig:async(r=".")=>(await e.load(r,"nearest-redocly-config",t.localeFolders)).data,isPathIgnored:async r=>(await e.load(r,"is-ignored")).data,withPathPrefix:N,logger:h}}export{ve as INTERNAL_PLUGINS,Se as createLifecycleContext,Ct as initPlugins,vt as runPlugins,O as writeClientEntries};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{logger as N}from"../../../tools/notifiers/logger.js";import{isNode as f}from"../../../../markdoc/helpers/guards/is-node.js";import{isConditionalNode as T}from"../../../../markdoc/helpers/guards/is-conditional-node.js";import{isContentNode as m}from"../../../../markdoc/helpers/guards/is-content-node.js";import{getNodeAttribute as u}from"../../../../markdoc/helpers/get-node-attribute.js";import{extractRbacFromCondition as w}from"../../../../markdoc/helpers/extract-rbac-from-condition-node.js";import{TextNode as
|
|
1
|
+
import{logger as N}from"../../../tools/notifiers/logger.js";import{isNode as f}from"../../../../markdoc/helpers/guards/is-node.js";import{isConditionalNode as T}from"../../../../markdoc/helpers/guards/is-conditional-node.js";import{isContentNode as m}from"../../../../markdoc/helpers/guards/is-content-node.js";import{getNodeAttribute as u}from"../../../../markdoc/helpers/get-node-attribute.js";import{extractRbacFromCondition as w}from"../../../../markdoc/helpers/extract-rbac-from-condition-node.js";import{TextNode as n}from"./nodes/text-node.js";import{TAG_TITLE_ATTRIBUTES as b,TagNode as p}from"./nodes/tag-node.js";import{HeadingNode as y}from"./nodes/heading-node.js";import{joinSectionContent as d}from"./join-section-content.js";class B{#s;#o;#e;#r;#c;constructor({ast:i,partials:t,skipConditionals:r=!1,getInnerContent:s,renderTag:o}){if(this.#s=i,this.#o=t,this.#e=r,this.#r=s,this.#c=o,!this.#s||!f(this.#s))throw new Error("ast is not a valid Markdoc Node.")}#i(){return{skipConditionals:this.#e,renderTag:this.#c}}*transform(){yield*this.#n(this.#s,{parentNode:null})}*#n(i,t,r=this.#r){if(!(!i||!f(i))){if(T(i)){if(this.#e)return;const s=w(i);s&&s.length>0&&(yield*this.#t(i,{...t,rbacTeams:s},r));return}if(m(i)){yield new n({node:i,content:r([i],this.#i()),...t});return}if(i.type==="heading"){yield new y({node:i,content:r([i],this.#i()),rbacTeams:t?.rbacTeams});return}if(i.type==="tag"){yield*this.#l(i,t,r);return}yield*this.#t(i,t,r)}}*#l(i,t,r=this.#r){switch(i.tag){case"partial":{const s=i.attributes.file,o=i.attributes.variables??{};if(s&&this.#o[s]){yield*this.#n(this.#o[s],t,(e,l)=>r(e,{...l,variables:o}));return}N.warn(`Could not create search indexes for partial \u201C${s}\u201D: file not found`);return}case"cards":case"tabs":case"code-walkthrough":{yield*this.#t(i,t,r);return}case"markdoc-example":{const s=r([i],this.#i());yield new n({node:i,content:s,...t});return}case"code-snippet":{const s=u(i,"title"),o=r([i],this.#i());if(s){const e=new p({node:i,content:s,...t});t={...t,parentNode:e},yield e}o&&(yield new n({node:i,content:o,...t}));return}default:{const s=this.#h(i,t,r);if(s){yield*s;return}const o=b.find(c=>c in i.attributes),e=(o&&u(i,o))??"",l=typeof e=="string"?e:r([e]);if(l){const c=new p({node:i,content:l,...t});t={...t,parentNode:c},yield c}if(a(i))yield*this.#t(i,t,r);else{const c=r([i],this.#i());c&&(yield new n({node:i,content:c,...t}))}return}}}#h(i,t,r){const s=()=>a(i)?d([...this.#t(i,t,r)]):"",o=this.#c?.(i,{getBody:s});return o===void 0?void 0:[new n({node:i,content:o.endsWith(`
|
|
2
|
+
`)?o:`${o}
|
|
3
|
+
`,...t})]}*#t(i,t,r=this.#r){for(const s of[...Object.values(i.slots),...i.children])for(const o of this.#n(s,t,r))o instanceof y&&(t={...t,parentNode:o}),yield o}}function a(h){return h.children.length>0||Object.keys(h.slots).length>0}export{B as AstToSearchNodeTransformer};
|
|
@@ -11,4 +11,5 @@ export declare const McpErrorCodes: {
|
|
|
11
11
|
export declare const DEFAULT_CONNECTION_TIMEOUT_MS = 30000;
|
|
12
12
|
export declare const SSE_KEEPALIVE_INTERVAL_MS = 15000;
|
|
13
13
|
export declare const MAX_DOCUMENTS_PER_CATEGORY = 3;
|
|
14
|
+
export declare const MCP_NOT_ALLOWED_TEMPLATE_ID = "mcp-not-allowed";
|
|
14
15
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const o={Docs:"docs"},r={InternalError:-32603,ServerError:-32e3,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602},e=3e4,t=15e3,E=3,_="mcp-not-allowed";export{e as DEFAULT_CONNECTION_TIMEOUT_MS,E as MAX_DOCUMENTS_PER_CATEGORY,_ as MCP_NOT_ALLOWED_TEMPLATE_ID,r as McpErrorCodes,o as McpServerType,t as SSE_KEEPALIVE_INTERVAL_MS};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const f=/^[A-Za-z_$][\w$]*$/;function y(n){const e=n.split(/[^A-Za-z0-9]+/).filter(Boolean).map((o,i)=>i===0?o:o[0].toUpperCase()+o.slice(1)).join("");return f.test(e)?e:`_${e}`}function T(n){return["```ts","declare const tools: {",n.map(e=>{const o=e.schema,i=e.outputSchema?u(e.outputSchema):"unknown",s=o.required?.length?"input":"input?";return` /** ${l(e.description)} */
|
|
2
|
+
${y(e.name)}(${s}: ${u(o," ")}): Promise<${i}>;`}).join(`
|
|
3
|
+
`),"};","```"].join(`
|
|
4
|
+
`)}function l(n){return(n??"").replace(/\*\//g,"*\\/")}function u(n,r=""){if(!n||typeof n!="object")return"unknown";const e=n.nullable?" | null":"";if(typeof n.codemodeType=="string")return n.codemodeType+e;if(Array.isArray(n.enum))return n.enum.map(m).join(" | ")+e;switch(n.type){case"string":return"string"+e;case"number":case"integer":return"number"+e;case"boolean":return"boolean"+e;case"array":return`Array<${u(n.items,r)}>`+e;case"object":return b(n,r)+e;default:return"unknown"}}function m(n){return typeof n=="string"?`'${n.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`:String(n)}function b(n,r){const e=n.properties??{},o=Object.keys(e),i=n.additionalProperties,s=i?i===!0?"unknown":u(i,r):void 0;if(o.length===0)return i===!1?"{}":`Record<string, ${s??"unknown"}>`;const $=new Set(n.required??[]),c=o.map(t=>{const p=e[t],d=$.has(t)?"":"?",g=f.test(t)?t:JSON.stringify(t);return{doc:p.description,field:`${g}${d}: ${u(p,r+" ")}`}});if(s&&c.push({field:`[key: string]: ${s}`}),!c.some(({doc:t})=>t))return`{ ${c.map(({field:t})=>t).join("; ")} }`;const a=r+" ";return`{
|
|
5
|
+
${c.map(({doc:t,field:p})=>`${t?`${a}/** ${l(t)} */
|
|
6
|
+
`:""}${a}${p};`).join(`
|
|
7
|
+
`)}
|
|
8
|
+
${r}}`}export{T as buildToolTypeDeclarations,y as sanitizeToolName};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const EXECUTE_DESCRIPTION: string;
|
|
2
|
+
export declare const DESCRIBE_TOOLS_DESCRIPTION: string;
|
|
3
|
+
export declare const CODE_MODE_INSTRUCTIONS: string;
|
|
4
|
+
export declare const USAGE_NOTES = "Types named `OpenApi\u2026` are the standard OpenAPI Specification objects.";
|
|
5
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const e=["Run JavaScript in a sandbox against the documentation tools on the global `tools` object.","The only extra global is `tools` - there is no `fetch`, `console`, `setTimeout`, `require`, or Node.js API; all I/O goes through `tools`.","","Workflow - minimize round-trips; one `describe-tools` call plus one `execute` call covers most requests:","1. Analyze the user request and decide which sandbox tools it needs (every tool name is listed in the `describe-tools` input schema).","2. Call `describe-tools` with those names to get their exact TypeScript signatures. NEVER call `execute` with guessed method names, parameter names, or enum values.","3. Batch everything the request needs into a SINGLE script: chain tool calls, pass one call's output into the next, process results in plain JavaScript (filter, map, aggregate), and `return` only what the request needs.","","Example - list the write endpoints of an API:","","```ts","const { items } = await tools.listApis({ filter: 'billing' });","const { endpoints } = await tools.getEndpoints({ name: items[0].name });","const writes = endpoints.filter((e) => e.method !== 'GET');","return { api: items[0].name, writes: writes.map((e) => `${e.method} ${e.path}`) };","```"].join(`
|
|
2
|
+
`),t=["Get the exact TypeScript signatures of the sandbox tools available to `execute`.","Analyze the user request first, then pass `tools` with only the tool names the request needs (every name is listed in this input schema); omit `tools` only when you cannot tell which tools apply.","Always call this before your first `execute` and never guess signatures. Request every tool the task may need in ONE call instead of calling this repeatedly."].join(`
|
|
3
|
+
`),s=["This server exposes documentation tools (API discovery, endpoint details, security schemes, full-text search) through two tools:","- `describe-tools` returns the exact TypeScript signatures of the sandbox tools.","- `execute` runs JavaScript that calls those tools on the global `tools` object.","Workflow: analyze the request, call `describe-tools` once with only the tool names it needs, then batch everything into a single `execute` script. Minimize round-trips and never guess tool signatures."].join(`
|
|
4
|
+
`),o="Types named `OpenApi\u2026` are the standard OpenAPI Specification objects.";export{s as CODE_MODE_INSTRUCTIONS,t as DESCRIBE_TOOLS_DESCRIPTION,e as EXECUTE_DESCRIPTION,o as USAGE_NOTES};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { McpToolSchema } from '../../../types';
|
|
2
2
|
export declare const EXECUTE_TOOL_NAME = "execute";
|
|
3
3
|
export declare const EXECUTE_TOOL_SCHEMA: McpToolSchema;
|
|
4
|
+
export declare const DESCRIBE_TOOLS_TOOL_NAME = "describe-tools";
|
|
5
|
+
export declare const CODE_MODE_TOOL_NAMES: ReadonlySet<string>;
|
|
4
6
|
export declare function getDefaultToolSchemas(config: {
|
|
5
7
|
products?: string[];
|
|
8
|
+
locales?: string[];
|
|
6
9
|
requiresLogin: boolean;
|
|
7
10
|
rbac?: Record<string, unknown>;
|
|
8
11
|
hasGraphqlApis?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{shouldHandleMcpAuth as p}from"../auth/auth-handlers.js";import{GRAPHQL_TYPE_KINDS as l}from"./tools/graphql/types.js";const s=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","TRACE"],t={type:"string",nullable:!0},n={codemodeType:"OpenApiServer[]"},r={codemodeType:"OpenApiSecurityRequirement[]"},o={codemodeType:"Record<string, OpenApiSecurityScheme>"},c={codemodeType:"OpenApiDocument"},u={codemodeType:"OpenApiOperation & { path: string; method: string }"},m="execute",P={name:m,description:"Run JavaScript in a sandbox to orchestrate multiple documentation tools in one call.",schema:{type:"object",required:["code","description"],additionalProperties:!1,properties:{code:{type:"string",description:"JavaScript to run in the sandbox. Return a value to receive it as the result.",minLength:1},description:{type:"string",description:"A short, human-readable summary of what this code does (shown to users in place of the raw call).",minLength:1}}}},d={type:"object",additionalProperties:!1,required:[],properties:{filter:{type:"string",description:"API name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of APIs per page. Default is 300",minimum:1,default:300,nullable:!0}}},a={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1},version:{type:"string",description:"API version (required when multiple APIs share the same name but differ by version)",nullable:!0}}},h={type:"object",required:["name","path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...s,...s.map(e=>e.toLowerCase())],minLength:1},version:{type:"string",description:"API version (required when multiple APIs share the same name but differ by version)",nullable:!0}}},y={type:"object",required:[],additionalProperties:!1,properties:{}};function q(e){const i=[{name:"list-apis",description:"Lists available APIs with their context and purpose",schema:d,annotations:{title:"List APIs",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:t,version:t,servers:n}}},limit:{type:"number"},total:{type:"number"},page:{type:"number"},totalPages:{type:"number"}}}},{name:"get-endpoints",description:"Get all endpoints for a specific API",schema:a,annotations:{title:"Get Endpoints",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{api:{type:"string"},version:{type:"string"},servers:n,endpoints:{type:"array",items:{type:"object",properties:{path:{type:"string"},method:{type:"string"},summary:t,description:t,security:r}}}}}},{name:"get-endpoint-info",description:"Get comprehensive information about specific endpoint including parameters, security, and examples",schema:h,annotations:{title:"Get Endpoint Info",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{api:{type:"string"},version:{type:"string"},servers:n,endpoint:u,globalSecurity:r,securitySchemes:o}}},{name:"get-security-schemes",description:"Get the security schemes for a specific API",schema:a,annotations:{title:"Get Security Schemes",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{name:t,version:t,securitySchemes:o,security:r}}},{name:"get-full-api-description",description:"Get the complete OpenAPI description",schema:a,annotations:{title:"Get Full API Description",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{api:{type:"string"},version:{type:"string"},definition:c}}},v(e.products)];return p(e.requiresLogin,e.rbac)&&i.push({name:"whoami",description:"Get information about the currently authenticated user",schema:y,annotations:{title:"Who Am I",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{email:{type:"string"},name:{type:"string"},subject:{type:"string"},clientId:{type:"string"},scope:{type:"string"},issuedAt:{type:"string"},expiresAt:{type:"string"}}}}),e.hasGraphqlApis&&i.push(...H()),i}const g={type:"object",required:[],additionalProperties:!1,properties:{filter:{type:"string",description:"GraphQL schema name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},f={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},kind:{type:"string",description:"Optional: return only a single category of schema members",enum:[...l],nullable:!0},filter:{type:"string",description:'Optional: only members whose name contains this substring (e.g. "book")',minLength:1,nullable:!0},referencesType:{type:"string",description:'Optional: only members that reference this type directly or transitively (via return, field, argument, union-member or input-field types). Finds cross-cutting members that never name it \u2014 e.g. referencesType "Book" surfaces a search query returning a union that includes Book.',minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},b={type:"object",required:["name","type"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},type:{type:"string",description:"Name of the type, operation, or directive",minLength:1},includeReferencedTypes:{type:"boolean",description:"Also include the SDL of every type referenced transitively. Gives the whole subgraph at once, but can be large for highly-connected types.",default:!1,nullable:!0}}},S={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1}}};function H(){return[{name:"list-graphql-apis",description:"Lists available GraphQL schemas with their context and purpose",schema:g,annotations:{title:"List GraphQL APIs",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},{name:"get-graphql-type-list",description:'List all operations and types in a GraphQL schema as a flat, paginated list. Each item is tagged with its kind (query, object, enum, \u2026) and carries a one-line description; operations also include their return type and argument signature \u2014 use it to decide which members to fetch in detail. Narrow the result with `kind` (one category) and/or `filter` (member-name substring, e.g. "book") to explore a domain cheaply instead of pulling the full schema.',schema:f,annotations:{title:"Get GraphQL Type List",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},{name:"get-graphql-type",description:"Get the SDL for a single GraphQL type, operation (query/mutation/subscription field), or directive. Set includeReferencedTypes to also pull in every type it references transitively \u2014 the full structural subgraph in one call, ideal for complete exploration of an entity (e.g. Book and all the types it touches).",schema:b,annotations:{title:"Get GraphQL Type",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},{name:"get-graphql-schema",description:"Get the complete GraphQL schema as SDL \u2014 the whole type graph in one call. Returns everything, so it can be very large and token-expensive for big schemas; prefer get-graphql-type-list (filter/paginate) plus targeted get-graphql-type calls, and reach for this only for small schemas or when you truly need the full SDL.",schema:S,annotations:{title:"Get GraphQL Schema",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}}]}function v(e){return{name:"search",description:"Search across the documentation to fetch relevant content for a given query",schema:e&&e.length>0?{type:"object",required:["query"],additionalProperties:!1,properties:{query:{type:"string",description:"Search query. Should be a single word or that phrase that is presented in a documentation.",minLength:1},product:{type:"string",description:"Optional product name to filter search results by specific product.",enum:e,nullable:!0}}}:{type:"object",required:["query"],additionalProperties:!1,properties:{query:{type:"string",description:"Search query. Should be a single word or that phrase that is presented in a documentation.",minLength:1}}},annotations:{title:"Search Documentation",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"string"}}}export{m as EXECUTE_TOOL_NAME,P as EXECUTE_TOOL_SCHEMA,q as getDefaultToolSchemas};
|
|
1
|
+
import{shouldHandleMcpAuth as d}from"../auth/auth-handlers.js";import{EXECUTE_DESCRIPTION as h}from"./codemode/prompts.js";import{GRAPHQL_TYPE_KINDS as o}from"./tools/graphql/types.js";const p=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","TRACE"],t={type:"string",nullable:!0},n={limit:{type:"number"},total:{type:"number"},page:{type:"number"},totalPages:{type:"number"}},r={codemodeType:"OpenApiServer[]"},s={codemodeType:"OpenApiSecurityRequirement[]"},l={codemodeType:"Record<string, OpenApiSecurityScheme>"},y={codemodeType:"OpenApiDocument"},g={codemodeType:"OpenApiOperation & { path: string; method: string }"},c="execute",j={name:c,description:h,schema:{type:"object",required:["code","description"],additionalProperties:!1,properties:{code:{type:"string",description:"JavaScript to run in the sandbox. Return a value to receive it as the result.",minLength:1},description:{type:"string",description:"A short, human-readable summary of what this code does (shown to users in place of the raw call).",minLength:1}}}},f="describe-tools",I=new Set([c,f]),b={type:"object",additionalProperties:!1,required:[],properties:{filter:{type:"string",description:"API name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of APIs per page. Default is 300",minimum:1,default:300,nullable:!0}}},a={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1},version:{type:"string",description:"API version (required when multiple APIs share the same name but differ by version)",nullable:!0}}},S={type:"object",required:["name","path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...p,...p.map(e=>e.toLowerCase())],minLength:1},version:{type:"string",description:"API version (required when multiple APIs share the same name but differ by version)",nullable:!0}}},v={type:"object",required:[],additionalProperties:!1,properties:{}};function w(e){const i=[{name:"list-apis",description:"Lists available APIs with their context and purpose",schema:b,annotations:{title:"List APIs",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:t,version:t,servers:r}}},...n}}},{name:"get-endpoints",description:"Get all endpoints for a specific API",schema:a,annotations:{title:"Get Endpoints",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{api:{type:"string"},version:{type:"string"},servers:r,endpoints:{type:"array",items:{type:"object",properties:{path:{type:"string"},method:{type:"string"},summary:t,description:t,security:s}}}}}},{name:"get-endpoint-info",description:"Get comprehensive information about specific endpoint including parameters, security, and examples",schema:S,annotations:{title:"Get Endpoint Info",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{api:{type:"string"},version:{type:"string"},servers:r,endpoint:g,globalSecurity:s,securitySchemes:l}}},{name:"get-security-schemes",description:"Get the security schemes for a specific API",schema:a,annotations:{title:"Get Security Schemes",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{name:t,version:t,securitySchemes:l,security:s}}},{name:"get-full-api-description",description:"Get the complete OpenAPI description",schema:a,annotations:{title:"Get Full API Description",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{api:{type:"string"},version:{type:"string"},definition:y}}},P(e.products,e.locales)];return d(e.requiresLogin,e.rbac)&&i.push({name:"whoami",description:"Get information about the currently authenticated user",schema:v,annotations:{title:"Who Am I",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{email:{type:"string"},name:{type:"string"},subject:{type:"string"},clientId:{type:"string"},scope:{type:"string"},issuedAt:{type:"string"},expiresAt:{type:"string"}}}}),e.hasGraphqlApis&&i.push(...O()),i}const H={type:"object",required:[],additionalProperties:!1,properties:{filter:{type:"string",description:"GraphQL schema name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},L={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},kind:{type:"string",description:"Optional: return only a single category of schema members",enum:[...o],nullable:!0},filter:{type:"string",description:'Optional: only members whose name contains this substring (e.g. "book")',minLength:1,nullable:!0},referencesType:{type:"string",description:'Optional: only members that reference this type directly or transitively (via return, field, argument, union-member or input-field types). Finds cross-cutting members that never name it \u2014 e.g. referencesType "Book" surfaces a search query returning a union that includes Book.',minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},T={type:"object",required:["name","type"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},type:{type:"string",description:"Name of the type, operation, or directive",minLength:1},includeReferencedTypes:{type:"boolean",description:"Also include the SDL of every type referenced transitively. Gives the whole subgraph at once, but can be large for highly-connected types.",default:!1,nullable:!0}}},A={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1}}};function O(){return[{name:"list-graphql-apis",description:"Lists available GraphQL schemas with their context and purpose",schema:H,annotations:{title:"List GraphQL APIs",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:t}}},...n}}},{name:"get-graphql-type-list",description:'List all operations and types in a GraphQL schema as a flat, paginated list. Each item is tagged with its kind (query, object, enum, \u2026) and carries a one-line description; operations also include their return type and argument signature \u2014 use it to decide which members to fetch in detail. Narrow the result with `kind` (one category), `filter` (member-name substring, e.g. "book"), or `referencesType` (only members that use a given type, directly or transitively) to explore a domain cheaply instead of pulling the full schema.',schema:L,annotations:{title:"Get GraphQL Type List",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{name:{type:"string"},items:{type:"array",items:{type:"object",properties:{kind:{type:"string",enum:o},name:{type:"string"},description:t,type:{type:"string"},args:{type:"string"}}}},...n}}},{name:"get-graphql-type",description:"Get the SDL for a single GraphQL type, operation (query/mutation/subscription field), or directive. Set includeReferencedTypes to also pull in every type it references transitively \u2014 the full structural subgraph in one call, ideal for complete exploration of an entity (e.g. Book and all the types it touches). That traversal only follows what the target depends on; to go the other direction and find the members that use a type, call get-graphql-type-list with `referencesType`.",schema:T,annotations:{title:"Get GraphQL Type",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"string"}},{name:"get-graphql-schema",description:"Get the complete GraphQL schema as SDL \u2014 the whole type graph in one call. Returns everything, so it can be very large and token-expensive for big schemas; prefer get-graphql-type-list (filter/paginate) plus targeted get-graphql-type calls, and reach for this only for small schemas or when you truly need the full SDL.",schema:A,annotations:{title:"Get GraphQL Schema",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"string"}}]}function P(e,i){const u=e&&e.length>0,m=i&&i.length>0;return{name:"search",description:"Search across the documentation to fetch relevant content for a given query",schema:{type:"object",required:["query"],additionalProperties:!1,properties:{query:{type:"string",description:"Search query. Should be a single word or that phrase that is presented in a documentation.",minLength:1},...u?{product:{type:"string",description:"Optional product name to filter search results by specific product.",enum:e,nullable:!0}}:{},...m?{locale:{type:"string",description:"Optional locale code to filter search results by documentation language (e.g. 'en', 'ja'). Use the locale matching the language of the user's request. Defaults to the project's default locale.",enum:i,nullable:!0}}:{}}},annotations:{title:"Search Documentation",readOnlyHint:!0,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"string"}}}export{I as CODE_MODE_TOOL_NAMES,f as DESCRIBE_TOOLS_TOOL_NAME,c as EXECUTE_TOOL_NAME,j as EXECUTE_TOOL_SCHEMA,w as getDefaultToolSchemas};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{withPathPrefix as
|
|
1
|
+
import{withPathPrefix as f}from"@redocly/theme/core/utils";import{ServerRoutes as d}from"../../../../../../constants/api.js";import{DEFAULT_LOCALE_PLACEHOLDER as m}from"../../../../../../constants/common.js";const y=async(i,t)=>{const{query:c,product:l,locale:u}=i,p=t.config.l10n?.defaultLocale||m,h=JSON.stringify({query:c,product:l,locale:u||p});let e=`${t.baseUrl}${f(d.SEMANTIC_SEARCH)}`;e.startsWith("http://")&&(e=e.replace(/^http:\/\//,"https://"));const o=t.accessToken?`authorization=${String(t.accessToken).replace(/^Bearer /,"")}`:"";try{const s=await fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...o?{Cookie:o}:{}},body:h});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 a=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:a.length?a:"No results found."}]}}catch{return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0}}};var C={search:y};export{C as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mcpToolHandlers as s}from"../../../../../client/mcp-tool-handlers-entry.js";import{EXECUTE_TOOL_NAME as c}from"../tool-schemas.js";import{sanitizeToolName as
|
|
1
|
+
import{mcpToolHandlers as s}from"../../../../../client/mcp-tool-handlers-entry.js";import{EXECUTE_TOOL_NAME as c,CODE_MODE_TOOL_NAMES as u}from"../tool-schemas.js";import{sanitizeToolName as f}from"../codemode/build-tool-type-declarations.js";import{runInSandbox as l}from"../codemode/sandbox.js";import{executeMcpTool as m,isMcpToolAvailable as p}from"../../workers/execute-mcp-tool.js";const y=async(t,r,n)=>{const o=await E(r,n),{result:i,error:e}=await l(t.code,o);return{content:[{type:"text",text:JSON.stringify({result:i,error:e})}],isError:e!==void 0}};async function E(t,r){const n={};for(const o of Object.keys(s))u.has(o)||await d(o,t)&&(n[f(o)]=async i=>{const e=await m({toolName:o,args:i,context:t,extra:r}),a=O(e);if(e.isError)throw new Error(a);return T(a)});return n}async function d(t,r){try{return await p({toolName:t,context:r})}catch{return!1}}function O(t){return t.content.filter(r=>r.type==="text").map(r=>r.text).join("")}function T(t){try{return JSON.parse(t)}catch{return t}}var _={[c]:y};export{_ as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{paginate as p,textResult as
|
|
1
|
+
import{paginate as p,textResult as m}from"./tool-helpers.js";const c=async(r,l)=>{const{filter:i,page:o=1,limit:n=300}=r;let t=l.graphqlDescriptions;if(i){const e=i.toLowerCase();t=t.filter(s=>s.name.toLowerCase().includes(e))}const a=p(t,o,n);return m(JSON.stringify({...a,items:a.items.map(({name:e,description:s})=>({name:e,description:s}))}))};var g={"list-graphql-apis":c};export{g as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withPathPrefix as
|
|
1
|
+
import{withPathPrefix as h}from"@redocly/theme/core/utils";import{importApiRoutesHandler as g}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as A}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as T}from"../../../telemetry/index.js";import{KvService as D}from"../../../persistence/kv/services/kv-service.js";import{envConfig as o}from"../../../config/env-config.js";import{acceptsHtml as R}from"../../../utils/ai-agent-detection.js";import{handleErrorPageRender as E}from"../../../web-server/utils.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as c}from"../constants.js";async function b(n,t,e){const i=t.req.raw;if(i.method==="GET"&&R(i.headers.get("accept"))&&e.templates.has(c))return E(t,e,{slug:n.slug},405,c);const r=t.get("auth"),s=await e.resolveRouteStaticData(n)||{},m=h(n.slug),{requestHandlers:p}=await g(e.serverOutDir),l=p[n.requestHandlerId],u=(await l()).default,d=async()=>await D.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:o.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:o.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),f=A({honoCtx:t,ctx:{user:{teams:r.teams,email:r.claims.email,claims:r.claims,idpAccessToken:r.idpAccessToken,idpId:r.claims.idpId,isAuthenticated:r.isAuthenticated},config:e.config,outdir:e.outdir,baseUrl:new URL(t.req.url).origin},telemetry:T,getKv:d}),a=await u(t.req.raw,f,{...s,props:{...s.props,routeSlug:m,outdir:e.outdir}});return a instanceof Response?a:typeof a=="string"?new Response(a,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(a),{headers:{"Content-Type":"application/json"}})}export{b as handleMcpRequest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fileURLToPath as
|
|
1
|
+
import{fileURLToPath as b}from"node:url";import{dirname as A,join as a}from"node:path";import{logger as g}from"../../tools/notifiers/logger.js";import{reporter as O}from"../../tools/notifiers/reporter.js";import{isDefined as _}from"../../../utils/guards/is-defined.js";import{buildGraphqlDescriptions as w,filterIgnoredApiDescriptions as h,getCleanedUpApiDescriptions as R,isMcpInRedirects as q}from"./utils.js";import{isMcpCodeModeEnabled as L}from"./mode.js";import{getDefaultToolSchemas as j,EXECUTE_TOOL_SCHEMA as N}from"./docs-mcp/tool-schemas.js";import{telemetryTraceStep as G}from"../../../cli/telemetry/helpers/trace-step.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as H}from"./constants.js";const D="mcp-docs-server-handler",p=A(b(import.meta.url));async function I(){let i=!1;return{id:"mcp",async processContent(e,r){i||await G("build.plugin.mcp",async c=>{const t=await e.loadOpenApiDefinitions(r),d=await e.loadGraphqlDefinitions(r),s=await r.getConfig(),{mcp:n,redirects:v}=s;if(c?.setAttribute("config",JSON.stringify(n||{})),!(n?.hide||n?.docs?.hide)&&(q(v)&&await O.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),e.createTemplate(H,"@redocly/theme/layouts/McpNotAllowed"),!n?.docs?.hide)){g.info("Configuring MCP servers...");const M=a(p,"./handlers/docs-mcp-handler.js"),C=R(h(t,n?.docs?.ignore||[])),l=new Map;for(const o of C){const f=o.definition.info?.title||"",u=o.definition.info?.version||"";l.set(`${f.toLowerCase()}@${u}`,{name:f,description:o.definition.info?.description||"",version:u,servers:o.definition.servers||[],relativePath:o.relativePath})}const m=w(h(d,n?.docs?.ignore||[])),P=Object.values(s.products||{}).map(o=>o?.name).filter(_),y=s.l10n?.locales?.map(o=>o.code)??r.fs.localeFolders,E=!!s?.access?.requiresLogin,S=s?.access?.rbac||{},T=j({products:P,locales:y,requiresLogin:E,rbac:S,hasGraphqlApis:m.length>0});e.addMcpTools(a(p,"./docs-mcp/tools/index.js"),T),L()&&e.addMcpTools(a(p,"./docs-mcp/tools/execute.js"),[N]),await U({actions:e,handlerPath:M,apiDescriptionsMap:Object.fromEntries(l),graphqlDescriptions:m,mcpConfig:n}),i=!0}})},async afterRoutesCreated(e,r){const c=await r.getConfig(),{mcp:t}=c;e.setGlobalData({mcpData:{docs:{enabled:!t?.hide&&!t?.docs?.hide,name:t?.docs?.name}}})}}}var K=I;async function U({actions:i,handlerPath:e,apiDescriptionsMap:r,graphqlDescriptions:c,mcpConfig:t}){i.createRequestHandler(D,e),i.addApiRoute({slug:"/mcp",requestHandlerId:D,httpMethod:"all",getStaticData:async()=>({props:{config:{apiDescriptionsMap:r,graphqlDescriptions:c,mcpDocsServerName:t?.docs?.name||"Docs MCP Server"},serverOutDir:i.serverOutDir,tools:i.getMcpTools().map(({importPath:d,...s})=>s)}})}),g.info("Registered Docs MCP Server endpoint at /mcp")}export{D as MCP_DOCS_SERVER_HANDLER_ID,K as default,I as mcpServerPlugin};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{McpServer as _}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as S}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{logger as p}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as u,MCP_TOOL_WORKER_KEY as b,MCP_TOOL_IS_AVAILABLE_KEY as y}from"../../../workers/mcp-tool-worker-pool.js";import{EXECUTE_TOOL_NAME as d,EXECUTE_TOOL_SCHEMA as f,DESCRIBE_TOOLS_TOOL_NAME as I,CODE_MODE_TOOL_NAMES as C}from"../docs-mcp/tool-schemas.js";import{buildToolTypeDeclarations as M,sanitizeToolName as E}from"../docs-mcp/codemode/build-tool-type-declarations.js";import{CODE_MODE_INSTRUCTIONS as D,DESCRIBE_TOOLS_DESCRIPTION as g,USAGE_NOTES as h}from"../docs-mcp/codemode/prompts.js";import{isMcpCodeModeEnabled as T}from"../mode.js";async function B({name:e,tools:o,context:n}){const a=new _({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},instructions:T()?D:void 0}),s=new S({sessionIdGenerator:void 0}),c=L(n),l=r=>async(t,m)=>{p.info(`MCP tool called: ${r}`);const O={toolName:r,args:t,context:c,extra:w(m)};return await u.exec(b,[O],{timeout:6e4})},i=async r=>{try{return await u.exec(y,[{toolName:r,context:c}],{timeout:1e4})}catch(t){return p.error(`Failed to check MCP tool availability for "${r}": ${t instanceof Error?t.message:String(t)}`),!1}};if(T()){const r=o.filter(t=>!C.has(t.name));a.tool(d,f.description,f.schema,l(d)),a.tool(I,g,q(r),v(r,i))}else await Promise.all(o.map(async r=>{const t=r.annotations||{title:r.name},m=a.tool(r.name,r.description,r.schema,t,l(r.name));await i(r.name)||m.disable()}));return await a.connect(s),{server:a,transport:s,cleanup:async()=>{s.close()}}}function q(e){const o=[...new Set(e.map(n=>E(n.name)))];return{type:"object",required:[],additionalProperties:!1,properties:{tools:{type:"array",description:"Tool names to describe. Omit to describe every tool.",items:{type:"string",enum:o},nullable:!0}}}}function v(e,o){return async n=>{const a=n.tools,s=a?.length?e.filter(i=>a.includes(E(i.name))):e,c=await Promise.all(s.map(i=>o(i.name))),l=s.filter((i,r)=>c[r]);return{content:[{type:"text",text:`${M(l)}
|
|
2
|
+
|
|
3
|
+
${h}`}]}}}function w(e){return{sessionId:e.sessionId,authInfo:e.authInfo,requestId:e.requestId,requestInfo:e.requestInfo,_meta:e._meta}}function L(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata}}export{B as createDocsMcpServer};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{simplifyAstStructure as
|
|
1
|
+
import{simplifyAstStructure as Z}from"@redocly/openapi-docs";import{REDOCLY_ROUTE_RBAC as A,REDOCLY_TEAMS_RBAC as S}from"@redocly/config";import{OPENAPI_DOCS_TEMPLATE_ID as H,PUBLIC_RBAC_SCOPE_ITEM as $}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as ee,PUBLIC_API_DEFINITIONS_FOLDER as te}from"../../constants/common.js";import{OPENAPI_SHARED_DATA_PREFIX as j}from"../../constants/plugins/openapi-docs.js";import{envConfig as G}from"../../config/env-config.js";import{isRbacScopeItems as oe}from"../../utils/rbac/is-rbac-scope-items.js";import{getRouteSlugsForPath as ae}from"../utils.js";import{searchResolver as re}from"./search/search-resolver.js";import{convertOpenAPIDocs2Sidebar as se,shouldAddRoute as ne}from"./utils.js";import{getTemplatePath as U}from"./get-template-path.js";import{storeDefinitionBundles as ie}from"./store-definition-bundles.js";import{definitionLoader as pe,definitionsLoader as ce}from"./load-definition.js";import{getAiDocumentsStore as de}from"./search/get-ai-search-documents.js";import{fromCurrentDir as le}from"../../utils/paths.js";import{telemetryTraceStep as fe}from"../../../cli/telemetry/helpers/trace-step.js";import{getApiConfigByPath as ue}from"../get-api-config.js";const B="openapi-spec-download";async function Te(){let L=[],E={},M=new Set,f={};return{id:"openapi",requiredEntitlements:["openapi"],loaders:{"load-oas-docs":ce,"load-oas":pe},processContent:async(e,c)=>{await fe("build.plugin.openapi_docs",async u=>{e.createRequestHandler(B,le(import.meta.url,"./spec-download.api.js")),e.addApiRoute({slug:te+"/*",requestHandlerId:B,httpMethod:"all",[S]:$,getStaticData:async()=>({props:{}})}),e.addApiRoute({slug:ee+"/*",requestHandlerId:B,httpMethod:"all",[S]:$,getStaticData:async()=>({props:{}})});const _=e.createTemplate(H,U("../../../client/templates/openapi-docs/template.js")),a=e.registerServerPropsGetter(H,U("./get-server-props.js")),o=await c.getConfig();u?.setAttribute("config",JSON.stringify(o.openapi||{})),E={},f={};const p=await e.loadOpenApiDefinitions(c);L=p.map(({markdocChunks:r,relativePath:m,customOutputRelativeFile:i,isVirtual:n,realRelativePath:g})=>({chunks:r,relativePath:m,realRelativePath:g,isVirtual:i!=null||n})),ie(p,e.outdir);for(const r of p||[]){const{definition:m,config:i,relativePath:n,customOutputRelativeFile:g,contentItems:C,flatItems:D,parser:d,options:I,rawOptions:V,hash:q}=r,b=g||n,s=[],k={},{definition:Y}=d||{},{info:l}=Y||{},y=l?.["x-metadata"],v=!!i.openapi?.excludeFromSearch||!!i.theme?.openapi?.excludeFromSearch||!!o.openapi?.excludeFromSearch||!!o.theme?.openapi?.excludeFromSearch,x={title:l?.title,description:l?.description,summary:l?.summary,...i.metadata,...y},h={untagged:[],tagged:new Map};for(const t of D){const{id:O,href:P,operationDefinition:F}=t;if(F){const{tags:R}=F;if(R)for(const w of R)h.tagged.has(w)||h.tagged.set(w,[]),h.tagged.get(w)?.push(t);else h.untagged.push(t);G.isDevelopMode&&(k[`#${F.pointer}`]=t.href)}if(!ne({item:t}))continue;const T=t,W=T.type==="section"&&!!T.infoDefinition,X=P.split("#")[0]+"/",z=t?.operationDefinition?.[S],K=oe(i.access?.rbac)?i.access.rbac:void 0;s.push({excludeFromSearch:v,slugSuffix:X,fsPath:b,metadata:{subType:"openapi-operation"},httpVerb:t?.httpVerb||"",path:n,templateId:_,[S]:z||K,getAiDocumentsStore:de({parser:d,options:I,info:l,tagOperations:h,openapiContentItem:T,metadata:x,relativePath:n,getSearchFacets:e.getSearchFacets,includeInLLMsTxt:W,excludeFromSearch:v}),getStaticData:async R=>({props:{dynamicMarkdocComponents:["openapi"],baseSlug:R.baseSlug,seo:t["x-metadata"]?.seo||{title:t.name,description:t.description},itemId:O,disableAutoScroll:!0}})})}if(s[0]={...s[0],metadata:{type:"openapi",...x},hasClientRoutes:!0,getSidebar:(t,O)=>{const P=[];return se({contentItems:C,sidebarItems:P,routeSlug:t.slug,navItem:O}),P},getNavText:()=>l?.title,getSearchDocuments:re(d,I,D,e.getSearchFacets,e.setSearchFacets,v)},y?.apiId&&!r.isVirtual){const t=ue(r.config.apis,r.realRelativePath);f[y.apiId]={[S]:t.rbac,[A]:{fsPath:b}}}const J=s[0];s[0]=s[s.length-1],s[s.length-1]=J;for(const t of s)e.addRoute({...t,serverPropsGetterIds:[a]});const Q=G.isDevelopMode?n:void 0,N=`${j}${n}`;E[N]={fsPath:b,definition:m,options:V,sourcePath:Q,routesMapping:k,hash:q};for(const t of s)e.addRoute({...t,sharedData:[{id:N,key:"openAPIDocsStore"}],serverPropsGetterIds:[a]})}})},afterRoutesCreated:async(e,c)=>{const u=new Set;for(const{chunks:a,relativePath:o,isVirtual:p,realRelativePath:r}of L){const m=ae(e.getAllRoutes(),o),i=(await c.cache.load(r,"load-oas")).compoundHash;await c.cache.load(o,{loader:async function(){for(const{node:g,markdown:C,key:D,relativePath:d}of a){const{ast:I}=await e.parseMarkdoc({input:{content:C,relativePath:d,isVirtual:p},context:c,deps:{sharedDataIds:[`${j}${d}`],routeSlugs:m}});g[`x-parsed-md-${D}`]={result:Z(I)}}},name:"openapi-markdoc-inline-parser"},[i]);for(const{pointer:n}of a)u.add(n)}const _=M.difference(u);for(const a of _)c.cache.delete(a);M=u;for(const[a,o]of Object.entries(E))await e.createSharedData(a,{...o,baseSlug:e.getRouteByFsPath(o.fsPath)?.baseSlug},o.hash);Object.entries(f).forEach(([a,o])=>{const p=o[A]?.fsPath;if(!p)return;const r=e.getRouteByFsPath(p)?.baseSlug;f[a]={...o,[A]:{...o[A],slug:r},slug:r}}),e.setGlobalData({apiProducts:f})}}}export{Te as openAPIDocsPlugin};
|
|
@@ -51,6 +51,11 @@ export declare const getScorecardConfig: (config: Partial<RedoclyConfig>) => {
|
|
|
51
51
|
[x: string]: unknown;
|
|
52
52
|
} | undefined;
|
|
53
53
|
extends?: string[] | undefined;
|
|
54
|
+
graphqlRules?: {
|
|
55
|
+
[x: string]: string | {
|
|
56
|
+
[x: string]: unknown;
|
|
57
|
+
};
|
|
58
|
+
} | undefined;
|
|
54
59
|
name: string;
|
|
55
60
|
oas2Decorators?: {
|
|
56
61
|
[x: string]: unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{writeFileSync as
|
|
1
|
+
import{writeFileSync as D}from"node:fs";import L from"path";import{SCORECARD_OUTPUT_FILE_NAME as w}from"../../constants/common.js";import{mapObject as E}from"../../../utils/object/map-object.js";import{envConfig as A}from"../../config/env-config.js";import{removeLeadingSlash as j}from"../../../utils/url/remove-leading-slash.js";import{combineUrls as O}from"@redocly/theme/core/utils";import{logger as _}from"../../tools/notifiers/logger.js";import{getRouteSlugToCatalogSlugMap as F}from"../../utils/catalog-classic/get-route-slug-to-catalog-slug-map.js";import{deepEqual as I}from"../../../utils/object/deep-equal.js";import{ensureDir as N}from"../../utils/index.js";import{getTemplatePath as q}from"./get-template-path.js";import{getAllRuleNames as U}from"./lint.js";import{getScorecardConfig as T}from"./get-scorecard-config.js";import{getScorecardSlug as k}from"./shared-utils.js";import{scorecardConfigLoader as M}from"./loaders/scorecard-config.js";import{scorecardLoader as W}from"./loaders/scorecard.js";import{computeScorecard as B}from"./compute-scorecard.js";import{telemetryTraceStep as J}from"../../../cli/telemetry/helpers/trace-step.js";const $="scorecardClassic";let u={},R={};async function ne({id:b,requiredEntitlements:P,loadersPrefix:v=""}){let p=null,y=null,h=!1;return{id:b??"scorecardClassic",requiredEntitlements:P??["scorecard"],loaders:{[`${v}scorecard-config`]:M,[`${v}scorecard`]:W},async processContent(r,l){await J("build.plugin.scorecard_classic",async S=>{const a=r.createTemplate($,q("./template/index.js")),g=await l.getConfig(),m=T(g),f=g?.reunite??{},i=[()=>p===null,()=>!I(u,m),()=>!I(R,f)].some(e=>e());u=m,S?.setAttribute("config",JSON.stringify(u||{})),R=f;const n=g.catalogClassic??{},c=u.levels||[];if(c.length<1)throw Error("Invalid configuration of levels config");i&&(p=await B({actions:r,context:l,scorecardConfig:u,reuniteConfig:R}));const{data:{configs:t}}=await l.cache.load("",`${v}scorecard-config`),{perLevel:d,all:s}=U(t);y={levelNames:c.map(e=>e.name),rules:s,rulesPerLevel:d};for(const[e,o]of Object.entries(n)){const C=O(o.slug,"scorecard/");r.addRoute({duplicateInAllLocales:!0,slug:C,fsPath:O(o.slug,"scorecard/"),templateId:a,hasClientRoutes:!0,excludeFromSidebar:!0,serverPropsGetterIds:[],sharedData:[{id:"scorecard",key:"scorecard"},{key:"catalog",id:"catalog-"+e}],getNavText:()=>Promise.resolve(o.title||"API design scorecard"),getStaticData:async()=>({props:{catalogId:e,catalogConfig:{...o,items:void 0},scorecardConfig:u,scorecardInfo:y}})})}})},afterRoutesCreated:async(r,l)=>{const S=await l.getConfig(),a=S.catalogClassic??{},g=T(S);if(Object.keys(a).length){const i=Object.keys(a).length>1?await F(r,l,a):null,n={};for(const[c,t]of Object.entries(p||{})){const d=r.getRouteByFsPath(c),s=d?.slug;if(s){if(d&&!g.ignoreMetadata){const e=i?i.get(s)??Object.values(a)[0].slug:Object.values(a)[0].slug,o=O(e,"scorecard/");d.metadata={...d.metadata,scorecardStatus:t.status,scorecardLevel:t.scorecardLevel,scorecardLevelIdx:t.scorecardLevelIdx,scorecardLevels:E(t.levels,C=>({uniqueErrors:C.uniqueErrors,uniqueWarnings:C.uniqueWarnings})),scoreCardSlug:o+"apis/"+encodeURIComponent(j(s))}}if(n[s]={...t,levels:E(t.levels,e=>({...e,problems:e.problems.map(o=>({ruleId:o.ruleId,severity:o.severity}))}))},!h){const e=L.resolve(r.outdir,"_scorecard",k(s));D(N(e),JSON.stringify(t))}}}await r.createSharedData("scorecard",n)}const m={};for(const[i,n]of Object.entries(p||{})){const c=r.getRouteByFsPath(i)?.slug;c&&(m[c]=n)}const f=A.REDOCLY_METADATA_OUTPUT_FOLDER;!h&&f&&(_.info("Writing scorecard data..."),D(L.join(f,w),JSON.stringify({scorecardData:m,...y}))),h=!0}}}export{ne as scorecardClassicPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{REDOCLY_TEAMS_RBAC as
|
|
1
|
+
import{REDOCLY_TEAMS_RBAC as p}from"@redocly/config";import{DEFAULT_SEARCH_ENGINE as s}from"../../constants/plugins/search.js";import{envConfig as c}from"../../config/env-config.js";import{logger as E}from"../../tools/notifiers/logger.js";import{reporter as u}from"../../tools/notifiers/reporter.js";import{prepareSearchDocuments as S}from"./documents/search-documents.js";import{SearchEngine as b}from"./engines/search-engine.js";import{prepareSemanticDocuments as D}from"./ai-indexer/prepare-semantic-documents.js";import{isAiSearchEnabled as y,shouldGenerateEmbeddings as A}from"./utils.js";import{telemetryTraceStep as C}from"../../../cli/telemetry/helpers/trace-step.js";import{EntitlementsProvider as R}from"../../entitlements/entitlements-provider.js";async function B(){let e=!0;return{async afterRoutesCreated(t,i){(c.SEARCH_DEV_REINIT||e)&&await _(t,i),e=!1},id:"search"}}async function _(e,t){await C("build.plugin.search",async i=>{const r=e.getConfig();if(i?.setAttribute("config",JSON.stringify(r.search||{})),r.search?.hide){E.info("Search is disabled in the config, skipping");return}const o=r.search?.engine||s,m=c.isDevelopMode?c.SEARCH_DEV_DEBUG?o:s:o,{l10n:l}=e.getGlobalData(),d=y(r),n=r.access?.rbac?.features?.aiSearch,f=A(r);let a;try{a=new b(m,l)}catch(g){await u.panic(g);return}await a.initIndexSchema(e.getSearchFacets()),e.setSearchEngine(a),e.setGlobalData({searchFeatures:{advanced:{enabled:m!==s&&!r.search?.filters?.hide},ai:{enabled:d,[p]:n&&Object.keys(n).length?n:void 0}}}),await S(t.fs,e,a);const h=R.instance().canAccessFeature("seo")===!0&&r.seo?.llmstxt?.hide!==!0;await D(e,t,{embeddingsEnabled:f,llmstxtEnabled:h})})}export{B as searchPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_SSO_IDP_TITLE as
|
|
1
|
+
import{DEFAULT_SSO_IDP_TITLE as A}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as I}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as C}from"../../tools/notifiers/logger.js";const O="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function S(T){return{id:"sso",async processContent(i){await I("build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&C.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=O,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n,prompt:"login"};t&&(p.login_idps=t);const m={oidc:{title:A,type:"OIDC",configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid"],authorizationRequestCustomParams:p,audience:"{{ process.env.ORGANIZATION_ID }}",introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{S as ssoPlugin};
|
package/dist/server/store.d.ts
CHANGED
|
@@ -78,10 +78,14 @@ export declare class Store {
|
|
|
78
78
|
queueEvent: <T extends Array<unknown>>(type: LifecycleEventType, id?: string, ...args: T) => void;
|
|
79
79
|
runListeners: <T extends Array<unknown>>(type: LifecycleEventType, id?: string, ...args: T) => void;
|
|
80
80
|
startPluginsRun(): void;
|
|
81
|
-
waitForPluginsLifecycle(): Promise<[void, void]>;
|
|
81
|
+
waitForPluginsLifecycle(): Promise<[void, void, void]>;
|
|
82
|
+
waitForPluginsRun(): Promise<void>;
|
|
82
83
|
finishPluginsRun(): void;
|
|
83
84
|
startEsbuildRun(): void;
|
|
84
85
|
finishEsbuildRun(): void;
|
|
86
|
+
markRequestHandlersEntryOutdated(): void;
|
|
87
|
+
noteRequestHandlersEntryBuildStart(): void;
|
|
88
|
+
markRequestHandlersEntryUpdated(): void;
|
|
85
89
|
get contentDir(): string;
|
|
86
90
|
markUserCodeReady(): void;
|
|
87
91
|
reloadMarkdocOptions(): Promise<void>;
|
package/dist/server/store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import b from"@markdoc/markdoc";import{getPathnameForLocale as A}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{MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as O}from"./constants/common.js";import{isObject as M}from"../utils/guards/is-object.js";import{mapObject as L}from"../utils/object/map-object.js";import{getValueDeep as R}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 y}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 _}from"./utils/crypto/sha1.js";import{envConfig as G,setEnv as F}from"./config/env-config.js";import{KvService as B}from"./persistence/kv/services/kv-service.js";import{writeSharedData as I}from"./utils/index.js";import{renderComponents as H}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 q}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as w}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as U}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as x}from"./utils/redirects/find-redirect.js";import{followRedirectChain as W}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as $}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as z}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"},E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Te="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#e={};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;#t=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:a}){this.#r=s,this.outdir=e,this.serverMode=t,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(e,s){const t=this.listeners.get(e);t?t.add(s):this.listeners.set(e,new Set([s]))}queueEvent=(e,s,...t)=>{this.#t.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const a of this.listeners.get(e)||new Set)s?a(s,...t):a(...t)};startPluginsRun(){this.clear(),this.#o=new Promise(e=>{this.#i=e})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const e of this.#t.values())this.runListeners(...e);this.#t.clear()}startEsbuildRun(){this.#n=new Promise(e=>{this.#c=e})}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 z("build.reload_markdoc_options",async()=>{const e=w.instance(),s=await q(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?e.canAccessFeature(D[a]):!0));this.#s={...s,tags:t}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const s=this.globalData,t={...this.globalData,...e};this.globalData=t,JSON.stringify(t)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,t)};getGlobalData=()=>this.globalData;getKv=async()=>B.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(e,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of t?.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 t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&r.partials?.length)for(const i of t.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(e){return(await e.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(e){return(await e.cache.load(".","asyncapi-docs")).data}async loadGraphqlDefinitions(e){return(await e.cache.load(".","load-graphql-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);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}=R(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:t,unsetEnvVars:a,replacedValues:r}=J(e);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!w.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(e).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=t,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&$(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const s=h(e).toLowerCase(),t=x(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(y(t.to)){const a=h(t.to).toLowerCase();if(!a.endsWith("*")&&W(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:t.to,type:t.type}};createSharedData=async(e,s,t)=>{if(t&&this.#e[e]===t)return e;const a=JSON.stringify(s),r=t??_(a);return this.#e[e]===r||(this.#e[e]=r,await I(e,a,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const a=k(e),r=this.routesSharedData.get(a)||{};r[s]=t,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${e}, ${s}, ${t}`)};getRouteSharedDataByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=e=>{const s=this.getGlobalConfig(m)||{},t=this.routesPartials.get(e);if(!t||t.length===0)return{};const a=this.getGlobalConfig(O)||{},r=new Set(t),o=Array.from(t);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=e=>{const t={...U(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=A(e,g,r.code,a);this.addRouteSharedData(o,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s)this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(o=>o.name.toLowerCase())),r=[...(this.config.responseHeaders[e]??[]).filter(o=>!t.has(o.name.toLowerCase())),...s];this.config.responseHeaders[e]=r};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,a=this.getRedirect(e);return t&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!y(s.to))return!0;const t=h(s.to);return this.routesBySlug.has(t)};getRoutesByTemplateId=e=>this.newRoutes.filter(s=>s.templateId===e);getAllRoutesForLocale=(e=g)=>{const s=Array.from(this.routesBySlug.values()),t=e.toLowerCase();return s.filter(a=>e===g?!K(a.fsPath):a.slug.startsWith(`/${t}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,s)=>(this.templates.set(e,s),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,s)=>(this.apiRoutesRequestHandlers.set(e,s),e);clearRequestHandlersByPrefix=e=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(e)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(e,s)=>(this.serverPropsGetters.set(e,s),e);registerPagePropsGetter=(e,s)=>{this.pagePropsGetters.set(e,s)};async writeRouteStaticData(e,s){const t=await this.resolveRouteStaticData(e,s,!1);t&&V(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return N(e.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},r=await e.getStaticData?.(e,a)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.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(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...e.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:t||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,s){if(!e?.length)return;const t=typeof e[0]=="string"?e.join(""):H(e);t&&(s==="head"?this.ssr.headTags.push(t):s==="preBody"?this.ssr.preBodyTags.push(t):this.ssr.postBodyTags.push(t))}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 e=[];for(const[t,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[t].entries());e.push([t,r]);break;case"object":t==="config"&&e.push([t,await this.getConfigWithEnvPlaceholders()]),e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[E]=G.PLAN_GATES,s}static fromJson(e,s){const t=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":t[r]=new Map(e[r]);break;case"object":if(r==="config"){t.setGlobalConfig(e[r]);break}t[r]=e[r];break;default:throw new Error("Invalid format")}t.config[m]=Z(t.config[m]||{});const a=e[E];return a&&F("PLAN_GATES",a),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=R(e,a);if(o||!M(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Y.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await S.panicOnBuildContentError(s)}}function Z(C){return L(C,e=>b.Ast.fromJSON(JSON.stringify(e)))}export{P as Store,Te as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
1
|
+
import b from"@markdoc/markdoc";import{getPathnameForLocale as A}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as O}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as T}from"./constants/common.js";import{isObject as M}from"../utils/guards/is-object.js";import{mapObject as L}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 u}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 h}from"./tools/notifiers/logger.js";import{sha1 as H}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as G}from"./config/env-config.js";import{KvService as B}from"./persistence/kv/services/kv-service.js";import{writeSharedData as F}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as q}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 U}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as K}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as x}from"./utils/redirects/find-redirect.js";import{followRedirectChain as W}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as $}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as z}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"},E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Oe="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={};#o=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#i;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#n;userCodeReady;#s=Promise.resolve();#c;#l=Promise.resolve();#d;#u=Promise.resolve();#h;#e=!1;#r=0;#f=0;#a=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:a}){this.#i=s,this.outdir=e,this.serverMode=t,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#n=r})}on(e,s){const t=this.listeners.get(e);t?t.add(s):this.listeners.set(e,new Set([s]))}queueEvent=(e,s,...t)=>{this.#a.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const a of this.listeners.get(e)||new Set)s?a(s,...t):a(...t)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#l,this.#u])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#a.values())this.runListeners(...e);this.#a.clear()}startEsbuildRun(){this.#l=new Promise(e=>{this.#d=e})}finishEsbuildRun(){this.#d?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#u=new Promise(e=>{this.#h=e}))}noteRequestHandlersEntryBuildStart(){this.#f=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#f||(this.#e=!1,this.#h?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#i}markUserCodeReady(){this.#n?.(!0)}async reloadMarkdocOptions(){await z("build.reload_markdoc_options",async()=>{const e=w.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?e.canAccessFeature(D[a]):!0));this.#o={...s,tags:t}})}get markdocOptions(){return{...this.#o,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const s=this.globalData,t={...this.globalData,...e};this.globalData=t,JSON.stringify(t)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,t)};getGlobalData=()=>this.globalData;getKv=async()=>B.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await V(e,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of t?.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 t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&r.partials?.length)for(const i of t.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(e){return(await e.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(e){return(await e.cache.load(".","asyncapi-docs")).data}async loadGraphqlDefinitions(e){return(await e.cache.load(".","load-graphql-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);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(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:t,unsetEnvVars:a,replacedValues:r}=J(e);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!w.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=u(e).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=t,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&$(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const s=u(e).toLowerCase(),t=x(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(R(t.to)){const a=u(t.to).toLowerCase();if(!a.endsWith("*")&&W(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:t.to,type:t.type}};createSharedData=async(e,s,t)=>{if(t&&this.#t[e]===t)return e;const a=JSON.stringify(s),r=t??H(a);return this.#t[e]===r||(this.#t[e]=r,await F(e,a,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const a=k(e),r=this.routesSharedData.get(a)||{};r[s]=t,this.routesSharedData.set(a,r),h.verbose(`Adding shared data to ${e}, ${s}, ${t}`)};getRouteSharedDataByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=e=>{const s=this.getGlobalConfig(m)||{},t=this.routesPartials.get(e);if(!t||t.length===0)return{};const a=this.getGlobalConfig(T)||{},r=new Set(t),o=Array.from(t);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=e=>{const t={...K(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),h.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=A(e,g,r.code,a);this.addRouteSharedData(o,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),h.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s)this.mcpToolHandlers.set(t.name,{...t,importPath:e}),h.verbose("Created MCP tool %s",t.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=e=>{this.middleware.push(e),h.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(o=>o.name.toLowerCase())),r=[...(this.config.responseHeaders[e]??[]).filter(o=>!t.has(o.name.toLowerCase())),...s];this.config.responseHeaders[e]=r};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,a=this.getRedirect(e);return t&&a?this.routesBySlug.get(u(a.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!R(s.to))return!0;const t=u(s.to);return this.routesBySlug.has(t)};getRoutesByTemplateId=e=>this.newRoutes.filter(s=>s.templateId===e);getAllRoutesForLocale=(e=g)=>{const s=Array.from(this.routesBySlug.values()),t=e.toLowerCase();return s.filter(a=>e===g?!U(a.fsPath):a.slug.startsWith(`/${t}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,s)=>(this.templates.set(e,s),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,s)=>(this.apiRoutesRequestHandlers.set(e,s),e);clearRequestHandlersByPrefix=e=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(e)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(e,s)=>(this.serverPropsGetters.set(e,s),e);registerPagePropsGetter=(e,s)=>{this.pagePropsGetters.set(e,s)};async writeRouteStaticData(e,s){const t=await this.resolveRouteStaticData(e,s,!1);t&&q(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return N(e.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},r=await e.getStaticData?.(e,a)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.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(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...e.metadata},seo:{title:O,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:t||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,s){if(!e?.length)return;const t=typeof e[0]=="string"?e.join(""):I(e);t&&(s==="head"?this.ssr.headTags.push(t):s==="preBody"?this.ssr.preBodyTags.push(t):this.ssr.postBodyTags.push(t))}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 e=[];for(const[t,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[t].entries());e.push([t,r]);break;case"object":t==="config"&&e.push([t,await this.getConfigWithEnvPlaceholders()]),e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[E]=_.PLAN_GATES,s}static fromJson(e,s){const t=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":t[r]=new Map(e[r]);break;case"object":if(r==="config"){t.setGlobalConfig(e[r]);break}t[r]=e[r];break;default:throw new Error("Invalid format")}t.config[m]=Z(t.config[m]||{});const a=e[E];return a&&G("PLAN_GATES",a),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=y(e,a);if(o||!M(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Y.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await S.panicOnBuildContentError(s)}}function Z(C){return L(C,e=>b.Ast.fromJSON(JSON.stringify(e)))}export{P as Store,Oe as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -5,6 +5,12 @@ export type AiAgentRequestHeaders = {
|
|
|
5
5
|
signatureInput?: string;
|
|
6
6
|
userAgent?: string;
|
|
7
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* Returns true if the Accept header explicitly lists text/html with a non-zero
|
|
10
|
+
* quality value. The catch-all wildcard does not count, so non-browser
|
|
11
|
+
* clients (curl, MCP clients) are not treated as browsers.
|
|
12
|
+
*/
|
|
13
|
+
export declare function acceptsHtml(acceptHeader: string | null | undefined): boolean;
|
|
8
14
|
/**
|
|
9
15
|
* Returns true if the request appears to be from an AI agent or a client that
|
|
10
16
|
* should receive the markdown representation when llms.txt is enabled.
|