@redocly/reef 0.132.0-next.5 → 0.132.0-next.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/dist/cli/telemetry/index.js +1 -1
- package/dist/client/App.js +1 -1
- package/dist/client/app/CircularProgress.js +8 -8
- package/dist/client/app/hooks/utils/match-banner-target.d.ts +23 -1
- package/dist/client/app/hooks/utils/match-banner-target.js +1 -1
- package/dist/client/mcp-tool-handlers-entry.d.ts +3 -0
- package/dist/client/mcp-tool-handlers-entry.js +1 -0
- package/dist/client/templates/asyncapi-docs/helpers.d.ts +1 -1
- package/dist/client/types/ai-search.d.ts +5 -3
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/markdoc/nodes/fence/index.js +1 -1
- package/dist/markdoc/nodes/index.d.ts +1 -1
- package/dist/markdoc/nodes/index.js +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/config/env-schema.d.ts +6 -3
- package/dist/server/config/env-schemas/api-urls.d.ts +3 -3
- package/dist/server/config/env-schemas/api-urls.js +1 -1
- package/dist/server/config/env-schemas/auth.d.ts +3 -0
- package/dist/server/config/env-schemas/auth.js +1 -1
- package/dist/server/esbuild/esbuild.js +3 -3
- package/dist/server/esbuild/plugins/codegen/index.d.ts +1 -0
- package/dist/server/esbuild/plugins/codegen/index.js +7 -3
- package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.d.ts +7 -0
- package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.js +1 -0
- package/dist/server/plugins/catalog-entities/plugin.js +1 -1
- package/dist/server/plugins/config-parser/index.js +1 -1
- package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
- package/dist/server/plugins/default-theme/resolve-products-config.js +1 -1
- package/dist/server/plugins/dev-onboarding/api/adapter-factory.d.ts +10 -3
- package/dist/server/plugins/dev-onboarding/api/adapter-factory.js +1 -1
- package/dist/server/plugins/dev-onboarding/api/adapters/apigee/adapter.d.ts +5 -4
- package/dist/server/plugins/dev-onboarding/api/adapters/apigee/adapter.js +4 -4
- package/dist/server/plugins/dev-onboarding/api/adapters/gravitee/client.d.ts +3 -3
- package/dist/server/plugins/dev-onboarding/api/adapters/gravitee/client.js +1 -1
- package/dist/server/plugins/dev-onboarding/api/middlewares/integrations.d.ts +3 -2
- package/dist/server/plugins/dev-onboarding/api/middlewares/integrations.js +1 -1
- package/dist/server/plugins/dev-onboarding/api/routes/index.js +1 -1
- package/dist/server/plugins/dev-onboarding/api/types.d.ts +8 -0
- package/dist/server/plugins/dev-onboarding/template/components/ApiLogsActions.js +5 -5
- package/dist/server/plugins/dev-onboarding/template/components/DialogStyledComponents.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/MultiSelect.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/TextField.js +3 -3
- package/dist/server/plugins/enforce-login/index.js +1 -1
- package/dist/server/plugins/lifecycle.js +2 -2
- package/dist/server/plugins/markdown/attribute-resolvers/index.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-diagram-from-file.d.ts +4 -0
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-diagram-from-file.js +1 -0
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-native-md-link.js +1 -1
- package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +1 -1
- package/dist/server/plugins/markdown/markdoc/plugins/render-diagrams.d.ts +16 -0
- package/dist/server/plugins/markdown/markdoc/plugins/render-diagrams.js +1 -0
- package/dist/server/plugins/markdown/runtime-transform.js +1 -1
- package/dist/server/plugins/markdown/search/to-markdown.js +24 -16
- package/dist/server/plugins/markdown/search/walk-sections.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +7 -0
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.d.ts +4 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.js +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +10 -7
- package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +5 -10
- package/dist/server/plugins/mcp/docs-mcp/tools/search.js +3 -3
- package/dist/server/plugins/mcp/docs-mcp/tools/utils.d.ts +6 -3
- package/dist/server/plugins/mcp/docs-mcp/tools/utils.js +6 -6
- package/dist/server/plugins/mcp/docs-mcp/tools/whoami.d.ts +5 -9
- package/dist/server/plugins/mcp/docs-mcp/tools/whoami.js +1 -1
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
- package/dist/server/plugins/mcp/index.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.d.ts +13 -22
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/types.d.ts +24 -56
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +2 -2
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
- package/dist/server/plugins/openapi-docs/index.js +1 -1
- package/dist/server/plugins/openapi-docs/search-indexer.js +1 -1
- package/dist/server/store.d.ts +5 -2
- package/dist/server/store.js +1 -1
- package/dist/server/telemetry/index.js +1 -1
- package/dist/server/types/plugins/common.d.ts +15 -2
- package/dist/server/types/redirects.d.ts +6 -0
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/utils/redirects/find-redirect.d.ts +8 -31
- package/dist/server/utils/redirects/find-redirect.js +1 -1
- package/dist/server/utils/redirects/follow-redirect-chain.d.ts +9 -0
- package/dist/server/utils/redirects/follow-redirect-chain.js +1 -0
- package/dist/server/utils/redirects/validate-redirects.d.ts +8 -0
- package/dist/server/utils/redirects/validate-redirects.js +1 -0
- package/dist/server/web-server/routes/otel/otel.js +1 -1
- package/dist/server/workers/types.d.ts +2 -2
- package/dist/server/workers/worker-pool.js +1 -1
- package/dist/types/global-data.d.ts +7 -2
- package/package.json +10 -10
- package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.d.ts +0 -4
- package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.js +0 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +0 -55
- package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +0 -1
- package/dist/server/plugins/mcp/handlers/mcp-request-handler.d.ts +0 -11
- package/dist/server/plugins/mcp/handlers/mcp-request-handler.js +0 -1
- package/dist/server/plugins/mcp/servers/base-server.d.ts +0 -17
- package/dist/server/plugins/mcp/servers/base-server.js +0 -1
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 f}from"../constants/common.js";import{DEFAULT_TITLE as C}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as T}from"../utils/object/map-object.js";import{getValueDeep as S}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as M}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as p}from"../utils/path/normalize-route-slug.js";import{isLocalLink as L}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as g}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{writeEnvVariable as _}from"./utils/envs/write-env-variable.js";import{envConfig as F}from"./config/env-config.js";import{KvService as G}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as V}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as H}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as y}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as U}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as q}from"./utils/redirects/find-redirect.js";import{addWildcardRedirectToTree as x}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const R={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map"},m="markdown/partials",W="markdown/partials-deps",v="PLAN_GATES",z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],At="userDefinedApiFunctions";class E{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#e=new Map;constructor({outdir:t,contentDir:e,serverMode:s=!1,serverOutDir:a}){this.#r=e,this.outdir=t,this.serverMode=s,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(t,e){const s=this.listeners.get(t);s?s.add(e):this.listeners.set(t,new Set([e]))}queueEvent=(t,e,...s)=>{this.#e.set(t+String(e),[t,e,...s])};runListeners=(t,e,...s)=>{for(const a of this.listeners.get(t)||new Set)e?a(e,...s):a(...s)};startPluginsRun(){this.clear(),this.#o=new Promise(t=>{this.#i=t})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const t of this.#e.values())this.runListeners(...t);this.#e.clear()}startEsbuildRun(){this.#n=new Promise(t=>{this.#c=t})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const t=y.instance(),e=await H(this.serverOutDir),s=Object.fromEntries(Object.entries(e.tags).filter(([a])=>D[a]!=null?t.canAccessFeature(D[a]):!0));this.#s={...e,tags:s}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=t=>{const e=this.globalData,s={...this.globalData,...t};this.globalData=s,JSON.stringify(s)!==JSON.stringify(e)&&this.queueEvent("global-data-updated",void 0,s)};getGlobalData=()=>this.globalData;getKv=async()=>G.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:t,context:e,deps:s,resource:a})=>{const{data:{info:r,ast:c},compoundHash:l}=await j(t,this.markdocOptions,{actions:this,context:e},a);for(const i of r.sharedDataDeps||[]){for(const o of s?.routeSlugs||[])this.addRouteSharedData(o,i,i);for(const o of s?.sharedDataIds||[]){const n=this.sharedDataDeps.get(o)||new Set;n.add(i),this.sharedDataDeps.set(o,n)}}for(const i of r.dynamicMarkdocComponents||[]){for(const o of s?.routeSlugs||[]){const n=this.routesDynamicComponents.get(o)||new Set;n.add(i),this.routesDynamicComponents.set(o,n)}for(const o of s?.sharedDataIds||[]){const n=this.sharedDataMarkdocComponents.get(o)||new Set;n.add(i),this.sharedDataMarkdocComponents.set(o,n)}}if(s?.routeSlugs&&r.partials?.length)for(const i of s.routeSlugs){const o=this.routesPartials.get(i)||[];for(const n of r.partials)o.includes(n)||o.push(n);this.routesPartials.set(i,o)}return{info:r,ast:c,compoundHash:l}};async loadOpenApiDefinitions(t){return(await t.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(t){return(await t.cache.load(".","asyncapi-docs")).data}setSearchEngine(t){this.searchEngine=t}setSearchFacets=t=>{this.searchFacets=t};setGlobalConfig=t=>{const e=Object.keys(t);for(const c of e)for(const l in this.replacedEnvVars)if(l===c||l.startsWith(`${c}:`)){const i=l.split(":"),{error:o,value:n}=S(t,i);(o||n!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:s,unsetEnvVars:a,replacedValues:r}=J(t);for(const c of a)this.unsetEnvVars.add(c);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,s)};getConfig=()=>this.config;getGlobalConfig=t=>this.config[t];getSearchFacets=()=>this.searchFacets;addRedirect=(t,e)=>{if(!y.instance().canAccessFeature("redirects")&&t!=="/")return;this.config.redirects||(this.config.redirects={});const r=p(t).toLowerCase();this.config.redirects[r]=e,r.endsWith("*")&&x(this.config.wildcardRedirectsTree,r)};getRedirect=t=>{const e=p(t).toLowerCase();return q(e,this.config.redirects,this.config.wildcardRedirectsTree)};createSharedData=async(t,e,s)=>{if(s&&this.#t[t]===s)return t;const a=JSON.stringify(e),r=s??k(a);return this.#t[t]===r||(this.#t[t]=r,await B(t,a,this.outdir),this.queueEvent("shared-data-updated",t)),t};addRouteSharedData=(t,e,s)=>{const a=M(t),r=this.routesSharedData.get(a)||{};r[e]=s,this.routesSharedData.set(a,r),g.verbose(`Adding shared data to ${t}, ${e}, ${s}`)};getRouteSharedDataByFsPath=t=>{const e=this.routesByFsPath.get(t);return e?this.routesSharedData.get(e)||{}:{}};getPartialsForRoute=t=>{const e=this.getGlobalConfig(m)||{},s=this.routesPartials.get(t);if(!s||s.length===0)return{};const a=this.getGlobalConfig(W)||{},r=new Set(s),c=Array.from(s);for(let i=0;i<c.length;i++){const o=c[i],n=a[o]?.partials??[];for(const d of n)r.has(d)||(r.add(d),c.push(d))}const l={};for(const i of r)e[i]&&(l[i]=e[i]);return l};addRoute=t=>{const s={...U(t.fsPath,this.config.metadataGlobs),...t.metadata||{}};this.newRoutes.push({...t,metadata:s}),g.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,e,s)=>{const a=[f,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const c=A(t,f,r.code,a);this.addRouteSharedData(c,e,s)}};addApiRoute=t=>{this.apiRoutes.push(t),g.verbose("Created API route %s",t.slug)};addMiddleware=t=>{this.middleware.push(t),g.verbose("Created middleware %s",t.id)};getRouteByFsPath=t=>{const e=this.routesByFsPath.get(t);return e?this.getRouteBySlug(e):void 0};getRouteBySlug=(t,e={})=>{const{followRedirect:s=!0}=e,a=this.getRedirect(t);return s&&a?this.routesBySlug.get(p(a.to)):this.routesBySlug.get(t)};slugHasRouteOrRedirect=t=>{if(this.routesBySlug.has(t))return!0;const e=this.getRedirect(t);if(!e)return!1;if(!L(e.to))return!0;const s=p(e.to);return this.routesBySlug.has(s)};getRoutesByTemplateId=t=>this.newRoutes.filter(e=>e.templateId===t);getAllRoutesForLocale=(t=f)=>{const e=Array.from(this.routesBySlug.values()),s=t.toLowerCase();return e.filter(a=>t===f?!K(a.fsPath):a.slug.startsWith(`/${s}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=t=>this.templates.get(t);getRequestHandler=t=>this.apiRoutesRequestHandlers.get(t);createTemplate=(t,e)=>(this.templates.set(t,e),t);addBrowserPlugin=t=>{this.browserPlugins.add(t)};createRequestHandler=(t,e)=>(this.apiRoutesRequestHandlers.set(t,e),t);registerServerPropsGetter=(t,e)=>(this.serverPropsGetters.set(t,e),t);registerPagePropsGetter=(t,e)=>{this.pagePropsGetters.set(t,e)};async writeRouteStaticData(t,e){const s=await this.resolveRouteStaticData(t,e,!1);s&&V(t.slug,s,this.outdir)}async resolveRouteStaticData(t,e,s){if(this.serverMode)return N(t.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:n,context:d,resource:h})=>this.parseMarkdoc({input:n,context:d,deps:{routeSlugs:[t.slug]},resource:h})},r=await t.getStaticData?.(t,a)||{},c=new Set(this.routesDynamicComponents.get(t.slug)),l=this.routesSharedData.get(t.slug)||{};for(const n of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(n);d&&d.forEach(u=>c.add(u));const h=this.sharedDataDeps.get(n);h&&h.forEach(u=>this.addRouteSharedData(t.slug,u,u))}const i=this.getGlobalConfig("seo"),o=r?.frontmatter||{};return{...r,frontmatter:{...o,seo:{...o?.seo,title:o?.seo?.title||await t.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(c),metadata:{...r?.props?.metadata,...t.metadata},seo:{title:C,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:s||!t.fsPath?null:await this.lifecycleContext?.fs.getLastModified(t.fsPath)}}addSsrComponents(t,e){if(!t?.length)return;const s=typeof t[0]=="string"?t.join(""):I(t);s&&(e==="head"?this.ssr.headTags.push(s):e==="preBody"?this.ssr.preBodyTags.push(s):this.ssr.postBodyTags.push(s))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const t=[];for(const[s,a]of Object.entries(R))switch(a){case"map":const r=Array.from(this[s].entries());t.push([s,r]);break;case"object":s==="config"&&t.push([s,await this.getConfigWithEnvPlaceholders()]),t.push([s,this[s]]);break;default:throw new Error("Invalid format")}const e=Object.fromEntries(t);return e[v]=F.PLAN_GATES,e}static fromJson(t,e){const s=new E(e);for(const[r,c]of Object.entries(R))switch(c){case"map":s[r]=new Map(t[r]);break;case"object":if(r==="config"){s.setGlobalConfig(t[r]);break}s[r]=t[r];break;default:throw new Error("Invalid format")}s.config[m]=Y(s.config[m]||{});const a=t[v];return a&&_("PLAN_GATES",a),s}async getConfigWithEnvPlaceholders(){const t=JSON.parse(JSON.stringify(this.config));for(const e in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[e],a=e.split(":"),r=a.pop(),{error:c,value:l}=S(t,a);if(c||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${e}`);continue}l[r]=s}return t}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const t=Array.from(this.unsetEnvVars).filter(s=>!z.includes(s));if(t.length===0)return;const e=`Failed to resolve config. The following environment variables are not set: ${t.join(", ")}`;await w.panicOnBuildContentError(e)}}function Y(P){return T(P,t=>b.Ast.fromJSON(JSON.stringify(t)))}export{m as MARKDOC_PARTIALS_DATA_KEY,W as MARKDOC_PARTIALS_DEPS_KEY,E as Store,At as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
1
|
+
import A from"@markdoc/markdoc";import{getPathnameForLocale as C}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{writeEnvVariable as _}from"./utils/envs/write-env-variable.js";import{envConfig as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as V}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as H}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as R}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as U}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as q}from"./utils/redirects/find-redirect.js";import{followRedirectChain as x}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Tt="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#e=new Map;constructor({outdir:t,contentDir:s,serverMode:e=!1,serverOutDir:a}){this.#r=s,this.outdir=t,this.serverMode=e,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(t,s){const e=this.listeners.get(t);e?e.add(s):this.listeners.set(t,new Set([s]))}queueEvent=(t,s,...e)=>{this.#e.set(t+String(s),[t,s,...e])};runListeners=(t,s,...e)=>{for(const a of this.listeners.get(t)||new Set)s?a(s,...e):a(...e)};startPluginsRun(){this.clear(),this.#o=new Promise(t=>{this.#i=t})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const t of this.#e.values())this.runListeners(...t);this.#e.clear()}startEsbuildRun(){this.#n=new Promise(t=>{this.#c=t})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const t=R.instance(),s=await H(this.serverOutDir),e=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?t.canAccessFeature(D[a]):!0));this.#s={...s,tags:e}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=t=>{const s=this.globalData,e={...this.globalData,...t};this.globalData=e,JSON.stringify(e)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,e)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:t,context:s,deps:e,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(t,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of e?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of e?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of e?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of e?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(e?.routeSlugs&&r.partials?.length)for(const i of e.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(t){return(await t.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(t){return(await t.cache.load(".","asyncapi-docs")).data}setSearchEngine(t){this.searchEngine=t}setSearchFacets=t=>{this.searchFacets=t};setGlobalConfig=t=>{const s=Object.keys(t);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(t,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:e,unsetEnvVars:a,replacedValues:r}=J(t);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,e)};getConfig=()=>this.config;getGlobalConfig=t=>this.config[t];getSearchFacets=()=>this.searchFacets;addRedirect=(t,s,e={})=>{if(!R.instance().canAccessFeature("redirects")&&t!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(t).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=e,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=t=>{const s=h(t).toLowerCase(),e=q(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!e)return null;if(S(e.to)){const a=h(e.to).toLowerCase();if(!a.endsWith("*")&&x(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:e.to,type:e.type}};createSharedData=async(t,s,e)=>{if(e&&this.#t[t]===e)return t;const a=JSON.stringify(s),r=e??k(a);return this.#t[t]===r||(this.#t[t]=r,await B(t,a,this.outdir),this.queueEvent("shared-data-updated",t)),t};addRouteSharedData=(t,s,e)=>{const a=L(t),r=this.routesSharedData.get(a)||{};r[s]=e,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${t}, ${s}, ${e}`)};getRouteSharedDataByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=t=>{const s=this.getGlobalConfig(m)||{},e=this.routesPartials.get(t);if(!e||e.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(e),o=Array.from(e);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=t=>{const e={...U(t.fsPath,this.config.metadataGlobs),...t.metadata||{}};this.newRoutes.push({...t,metadata:e}),u.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,s,e)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=C(t,g,r.code,a);this.addRouteSharedData(o,s,e)}};addApiRoute=t=>{this.apiRoutes.push(t),u.verbose("Created API route %s",t.slug)};addMcpTools=(t,s)=>{for(const e of s)this.mcpToolHandlers.set(e.name,{...e,importPath:t}),u.verbose("Created MCP tool %s",e.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=t=>{this.middleware.push(t),u.verbose("Created middleware %s",t.id)};getRouteByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(t,s={})=>{const{followRedirect:e=!0}=s,a=this.getRedirect(t);return e&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(t)};slugHasRouteOrRedirect=t=>{if(this.routesBySlug.has(t))return!0;const s=this.getRedirect(t);if(!s)return!1;if(!S(s.to))return!0;const e=h(s.to);return this.routesBySlug.has(e)};getRoutesByTemplateId=t=>this.newRoutes.filter(s=>s.templateId===t);getAllRoutesForLocale=(t=g)=>{const s=Array.from(this.routesBySlug.values()),e=t.toLowerCase();return s.filter(a=>t===g?!K(a.fsPath):a.slug.startsWith(`/${e}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=t=>this.templates.get(t);getRequestHandler=t=>this.apiRoutesRequestHandlers.get(t);createTemplate=(t,s)=>(this.templates.set(t,s),t);addBrowserPlugin=t=>{this.browserPlugins.add(t)};createRequestHandler=(t,s)=>(this.apiRoutesRequestHandlers.set(t,s),t);registerServerPropsGetter=(t,s)=>(this.serverPropsGetters.set(t,s),t);registerPagePropsGetter=(t,s)=>{this.pagePropsGetters.set(t,s)};async writeRouteStaticData(t,s){const e=await this.resolveRouteStaticData(t,s,!1);e&&V(t.slug,e,this.outdir)}async resolveRouteStaticData(t,s,e){if(this.serverMode)return N(t.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[t.slug]},resource:f})},r=await t.getStaticData?.(t,a)||{},o=new Set(this.routesDynamicComponents.get(t.slug)),l=this.routesSharedData.get(t.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(t.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await t.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...t.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:e||!t.fsPath?null:await this.lifecycleContext?.fs.getLastModified(t.fsPath)}}addSsrComponents(t,s){if(!t?.length)return;const e=typeof t[0]=="string"?t.join(""):I(t);e&&(s==="head"?this.ssr.headTags.push(e):s==="preBody"?this.ssr.preBodyTags.push(e):this.ssr.postBodyTags.push(e))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const t=[];for(const[e,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[e].entries());t.push([e,r]);break;case"object":e==="config"&&t.push([e,await this.getConfigWithEnvPlaceholders()]),t.push([e,this[e]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(t);return s[E]=G.PLAN_GATES,s}static fromJson(t,s){const e=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":e[r]=new Map(t[r]);break;case"object":if(r==="config"){e.setGlobalConfig(t[r]);break}e[r]=t[r];break;default:throw new Error("Invalid format")}e.config[m]=Z(e.config[m]||{});const a=t[E];return a&&_("PLAN_GATES",a),e}async getConfigWithEnvPlaceholders(){const t=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:e}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=y(t,a);if(o||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=e}return t}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const t=Array.from(this.unsetEnvVars).filter(e=>!Y.includes(e));if(t.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${t.join(", ")}`;await w.panicOnBuildContentError(s)}}function Z(b){return M(b,t=>A.Ast.fromJSON(JSON.stringify(t)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Tt as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AsyncApiRealmAPI as o}from"@redocly/realm-asyncapi-sdk";import{envConfig as e}from"../config/env-config.js";import{PACKAGE_NAME as t}from"../../config/product-gates.js";import{OTEL_TRACES_DEV_URL as i,TELEMETRY_ENABLED as s}from"../constants/common.js";class l extends o.Telemetry{constructor(){super(),this.updateCloudEventData(()=>({organizationId:e.ORGANIZATION_ID||"",organizationSlug:e.ORGANIZATION_SLUG||"",projectId:e.PROJECT_ID||"",projectSlug:"",origin:"realmApi",actor:{id:"Anonymous",object:"user",uri:""},source:"server"}))}initialize(r=!1){this.init({otel:{serviceName:"realm-server",serviceVersion:`${t}@${e.REDOCLY_PORTAL_VERSION||""}`,collectorTraceUrl:r?i:e.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",isProd:e.isProductionEnv,version:"1.0",tracerName:"server-telemetry",delayMillis:100},disabled:r?e.TELEMETRY_DEV_DEBUG!=="true":!s})}}const A=new l;export{A as telemetry};
|
|
1
|
+
import{AsyncApiRealmAPI as o}from"@redocly/realm-asyncapi-sdk";import{envConfig as e}from"../config/env-config.js";import{PACKAGE_NAME as t}from"../../config/product-gates.js";import{OTEL_TRACES_DEV_URL as i,TELEMETRY_ENABLED as s}from"../constants/common.js";class l extends o.Telemetry{constructor(){super(),this.updateCloudEventData(()=>({organizationId:e.ORGANIZATION_ID||"",organizationSlug:e.ORGANIZATION_SLUG||"",projectId:e.PROJECT_ID||"",projectSlug:e.PROJECT_SLUG||"",origin:"realmApi",actor:{id:"Anonymous",object:"user",uri:""},source:"server",env:e.redoclyEnv}))}initialize(r=!1){this.init({otel:{serviceName:"realm-server",serviceVersion:`${t}@${e.REDOCLY_PORTAL_VERSION||""}`,collectorTraceUrl:r?i:e.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",isProd:e.isProductionEnv,version:"1.0",tracerName:"server-telemetry",delayMillis:100},disabled:r?e.TELEMETRY_DEV_DEBUG!=="true":!s})}}const A=new l;export{A as telemetry};
|
|
@@ -115,6 +115,14 @@ export type ApiRoute = RouteDetails & {
|
|
|
115
115
|
httpMethod: ApiRouteMethod;
|
|
116
116
|
requestHandlerId: string;
|
|
117
117
|
};
|
|
118
|
+
export type McpToolSchema = {
|
|
119
|
+
name: string;
|
|
120
|
+
description: string;
|
|
121
|
+
schema: Record<string, unknown>;
|
|
122
|
+
};
|
|
123
|
+
export type McpToolRegistration = McpToolSchema & {
|
|
124
|
+
importPath: string;
|
|
125
|
+
};
|
|
118
126
|
export type MiddlewareDetails = {
|
|
119
127
|
id: string;
|
|
120
128
|
importPath: string;
|
|
@@ -124,6 +132,9 @@ export type PathVersionInfo = {
|
|
|
124
132
|
isDefault: boolean;
|
|
125
133
|
versionFolderId: string;
|
|
126
134
|
};
|
|
135
|
+
export type RedirectOptions = {
|
|
136
|
+
trackOriginalSource?: boolean;
|
|
137
|
+
};
|
|
127
138
|
export type ProcessContentActions = {
|
|
128
139
|
createSharedData(id: string, data: unknown, hash?: string): Promise<string>;
|
|
129
140
|
addRouteSharedData(slug: string, dataKey: string, dataId: string): void;
|
|
@@ -141,8 +152,10 @@ export type ProcessContentActions = {
|
|
|
141
152
|
getSearchFacets: () => Map<string, SearchFacet>;
|
|
142
153
|
addRoute: (route: PageRouteInit) => void;
|
|
143
154
|
addApiRoute: (route: ApiRoute) => void;
|
|
155
|
+
addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
|
|
156
|
+
getMcpTools: () => McpToolRegistration[];
|
|
144
157
|
createRequestHandler: (id: string, importPath: string) => void;
|
|
145
|
-
addRedirect: (from: string, to: RedirectConfig) => void;
|
|
158
|
+
addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
|
|
146
159
|
createTemplate: (id: string, importPath: string) => string;
|
|
147
160
|
addBrowserPlugin: (importPath: string) => void;
|
|
148
161
|
registerServerPropsGetter: (id: string, importPath: string) => string;
|
|
@@ -176,7 +189,7 @@ export type AfterRoutesCreatedActions = {
|
|
|
176
189
|
setSearchFacets: (facets: Map<string, SearchFacet>) => void;
|
|
177
190
|
getSearchFacets: () => Map<string, SearchFacet>;
|
|
178
191
|
setSearchEngine: (engine: SearchEngine) => void;
|
|
179
|
-
addRedirect: (from: string, to: RedirectConfig) => void;
|
|
192
|
+
addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
|
|
180
193
|
contentDir: string;
|
|
181
194
|
outdir: string;
|
|
182
195
|
serverOutDir: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import y from"path";import T from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as _,REDOCLY_ROUTE_RBAC as R}from"@redocly/config";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as x,ServerRoutes as w,PUBLIC_RBAC_SCOPE_ITEM as A,RBAC_ALL_OTHER_TEAMS as u,DEFAULT_RBAC_SCOPE as S}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as N}from"../constants/common.js";import{removeTrailingSlash as k}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as B}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as b}from"../../utils/path/parse-path-versions.js";import{reporter as M}from"../tools/notifiers/reporter.js";import{bold as W}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as U}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as $}from"../../utils/guards/is-truthy.js";import{canExpandConfig as v,expandRbacConfig as Y,getTeamFolderDefaults as z,parseTeamFoldersTemplate as K,parseTeamNameTemplate as H}from"./rbac-expand.js";import{getUserParamsFromCookies as G}from"../web-server/auth.js";import{getDeeperGlobPattern as V}from"./globs.js";import{EntitlementsProvider as J}from"../entitlements/entitlements-provider.js";const C=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],Q=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Ot(t,e){const r=C.indexOf(t.toUpperCase()),n=C.indexOf(e.toUpperCase());return r>n?t:e}const E={};function O(t,e){if(!t?.content)return A;const r=t.content,{slug:n,fsPath:s}=e;if(!n&&!s)return A;const o=f=>{const d=`slug:${f}`,p=E[d]??T(f);E[d]=p;const D=`fsPath:${f}`,L=E[D]??T(B(f));return E[D]=L,!!(n&&p(n))||!!(s&&L(s))};if(q(n||s||"")&&Object.keys(r).filter(p=>o(p)).length===0)return r[S]||A;const i=Object.keys(r).filter(f=>o(f));if(i.length==0)return A;const l=i.map(f=>T.scan(f,{tokens:!0,parts:!0}));let h=l[0];for(let f=1;f<l.length;f++)h=V(h,l[f]);return r[h.input]}function Pt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const s=r.features?.[t];return s?e.teams.some(o=>s[o]&&s[o].toLowerCase()!=="none"):!0}function Tt(t,e){return P(t,{isAuthenticated:!1,teams:[x]},e.access?.rbac||{},e.access?.requiresLogin||!1)}function P(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(w).some(i=>{const l=i.split(":")[0].replace(/\/$/,"");return t.slug===l||t.slug?.startsWith(i)})||typeof t.slug=="string"&&t.slug?.endsWith("/mcp")&&J.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const s=Y(r,e.teams||[]),o=t[_]||O(s,t[R]||{});if(Object.keys(o||{}).length===0)return!1;if(Object.keys(o).length===1&&o[u]&&o[u].toLowerCase()!=="none")return!0;const c=(e?.email?[...e?.teams||[],e?.email]:e?.teams)||[],a=[];for(const i of c??[])o[i]?a.push(o[i]):o[u]&&i!==e?.email&&a.push(o[u]);return a.length?a.some(i=>i.toLowerCase()!=="none"):!1}function xt(t,e,r,n){if(!t.startsWith(I)&&!t.startsWith(j))return!0;const s=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${j}/`),""),c=s==="."?"":s,a={[R]:{slug:t,fsPath:c},slug:t};return P(a,n,e,r)}function gt(t,e,r,n,s){if(!t.startsWith(N))return!0;const o=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!o)return!0;const c=n[o];if(!c)return!0;const{base:a,ext:i}=y.parse(t),l=a.split(".")[0],h=i.split(".").join(""),d=c==="."?"":c,p={[R]:{slug:t,fsPath:y.posix.join(d,`${l}.${h}`)},slug:t};return P(p,s,e,r)}async function Dt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:s,federatedIdToken:o,...c}=await G(t,e),{teams:a=[]}=c;let i;return r?i=a.filter(l=>l!==x):i=[x],{isAuthenticated:r,idpAccessToken:n,teams:i,claims:c}}function F(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const s=[];for(const o of t){const c=F(o,e,r,n);c!==void 0&&s.push(c)}return s}if(typeof t=="object"){if(!P(t,e,r,n))return;let s=!1;const o={};for(const c in t){if(c===_||c===R)continue;if(Q.has(c)){o[c]=t[c];continue}const a=F(t[c],e,r,n);if(c==="items"&&Array.isArray(a)&&a.length===0&&t[c].length!==0){s=!0;continue}a!==void 0&&(o[c]=a),c==="paths"&&X(a)&&Z(a)}return s?void 0:o}return t}function Lt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function _t(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([o,c])=>o===S?[[o,c]]:[[o,c],...t.localeFolders.map(a=>[o.startsWith("/")?`/${a.toLocaleLowerCase()}${o}`:y.posix.join(t.localizationFolder,a,o),c])]),s=Object.fromEntries(n);return{...e,content:s}}async function St(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:s})=>{const{versionFolderPath:o}=b(s)||{},c=y.dirname(s);return o?[o,c]:c}));for(const s of n)r[U(s)]=s;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function X(t){return m(t)&&Object.keys(t).length>0}function Z(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function q(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const tt=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},jt=async t=>{if(t){if(Object.keys(t).length===0)return{};if(tt(t))return et(t);await M.panicOnContentError(`You are using an incorrect format of ${W("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},et=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const s=k(n);r[s]=e.content[n]}e.content=r}return e};function It(t,e){const r=t.fsPath,n=t.slug,s=[];if(v(e)&&(r||n)){const o=[r,n].filter($),c=K(e,o);if(c){const a=e?.teamNamePatterns?.map(l=>l.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];s.push(...a);const i=O({content:{...z(e),...e.content}},t);s.push(...g(i))}else{const a=O(e,t);s.push(...g(a))}}else{const o=O(e,t);s.push(...g(o))}return rt(e,s)}function g(t){if(!t)return[];const e=[],r=u in t?{authenticated:t[u],anonymous:t[u]}:{};for(const[n,s]of Object.entries({...r,...t}))s.toLowerCase()!=="none"&&n!==u&&e.push(n);return e}function rt(t,e){return e.map(n=>H(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{C as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,_t as applyL10nToRbacConfig,gt as canAccessAsset,Pt as canAccessFeature,P as canAccessResource,xt as canDownloadApiDefinition,rt as expandTeamsForRead,g as extractTeamsFromScopeItems,F as filterDataByAccessDeep,Dt as getAuthDetailsFromCookies,Ot as getHigherRole,It as getRbacTeamsListForResource,O as getScopeItemsForResource,tt as isRbacConfigValid,Tt as isResourcePubliclyAccessible,et as normalizeRbacConfig,jt as parseRbacConfig,Lt as parseTeamClaimToArray,St as resolveDirectoryHashes};
|
|
@@ -1,39 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RedirectConfig, RedirectsConfig } from '@redocly/config';
|
|
2
2
|
import type { WildcardRedirectsTree } from '../../types';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Looks up a redirect rule for a slug
|
|
5
5
|
*
|
|
6
6
|
* **IMPORTANT:** The `slug` parameter must be normalized before passing to this function.
|
|
7
|
-
* This function does NOT perform normalization internally.
|
|
8
7
|
*
|
|
9
|
-
* -
|
|
10
|
-
* -
|
|
11
|
-
* - For wildcard matches, preserves the remaining path after the wildcard prefix if the redirect target also ends with `*`.
|
|
8
|
+
* - For wildcard rules whose target ends with `*`, the remainder of the path is preserved.
|
|
9
|
+
* - `from` is the matched config key (path or pattern); exposed for `followRedirectChain` rule tracking.
|
|
12
10
|
*
|
|
13
|
-
* @
|
|
14
|
-
* @param redirects - The redirects configuration object.
|
|
15
|
-
* @param wildcardRedirectsTree - The wildcard redirects converted to a tree structure to optimize the search.
|
|
16
|
-
* @returns An object containing the redirect `to` URL and optional `type`, or `null` if no redirect is found.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* // Direct redirect
|
|
20
|
-
* findRedirect('/old-page', { '/old-page': { to: '/new-page', type: 301 } }, {});
|
|
21
|
-
* // Returns: { to: '/new-page', type: 301 }
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* // Wildcard redirect with path preservation
|
|
25
|
-
* findRedirect('/docs/guide/intro', { '/docs/*': { to: '/documentation/*', type: 301 } }, { 'docs': { '*': '/docs/*' } });
|
|
26
|
-
* // Returns: { to: '/documentation/guide/intro', type: 301 }
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* // Wildcard redirect to fixed destination
|
|
30
|
-
* findRedirect('/old/anything', { '/old/*': { to: '/new-home', type: 302 } }, { 'old': { '*': '/old/*' } });
|
|
31
|
-
* // Returns: { to: '/new-home', type: 302 }
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* // No match found
|
|
35
|
-
* findRedirect('/some-page', {}, {});
|
|
36
|
-
* // Returns: null
|
|
11
|
+
* @returns Redirect config with resolved `to`, plus `from`, or `null` if no rule matches or the rule would not change the slug.
|
|
37
12
|
*/
|
|
38
|
-
export declare function findRedirect(slug: string, redirects: RedirectsConfig, wildcardRedirectsTree: WildcardRedirectsTree): WithRequired<RedirectConfig, 'to'>
|
|
13
|
+
export declare function findRedirect(slug: string, redirects: RedirectsConfig, wildcardRedirectsTree: WildcardRedirectsTree): (WithRequired<RedirectConfig, 'to'> & {
|
|
14
|
+
from: string;
|
|
15
|
+
}) | null;
|
|
39
16
|
//# sourceMappingURL=find-redirect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{removeLeadingSlash as
|
|
1
|
+
import{normalizeRouteSlug as a}from"../../../utils/path/normalize-route-slug.js";import{removeLeadingSlash as d}from"../../../utils/url/remove-leading-slash.js";function m(t,o,f){const r=o[t];if(r?.to){const i=r.to;return a(i).toLowerCase()===t?null:{to:i,type:r.type,from:t}}const e=u(t,f);if(!e)return null;const c=o[e],l=c?.to;if(!l)return null;let n=l;if(n.endsWith("*")){const i=e.split("*")[0];n=n.replace(/\*$/,t.substring(i.length))}return a(n).toLowerCase()===t?null:{...c,to:n,from:e}}function u(t,o){const f=d(t).split("/");let r=o;for(const e of f){if(!r[e])break;r=r[e]}return r["*"]||null}export{m as findRedirect};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RedirectsConfig } from '@redocly/config';
|
|
2
|
+
import type { FollowRedirectChainResult, WildcardRedirectsTree } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Follows the redirect chain from startSlug. Returns when:
|
|
5
|
+
* - A cycle is detected (revisiting a slug or redirect rule) -> { type: 'cycle', cycle }
|
|
6
|
+
* - No redirect / external / wildcard -> { type: 'no-cycle' }
|
|
7
|
+
*/
|
|
8
|
+
export declare function followRedirectChain(startSlug: string, initialChain: string[], redirects: RedirectsConfig, wildcardRedirectsTree: WildcardRedirectsTree, resolveWildcards?: boolean): FollowRedirectChainResult;
|
|
9
|
+
//# sourceMappingURL=follow-redirect-chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{normalizeRouteSlug as a}from"../../../utils/path/normalize-route-slug.js";import{isLocalLink as p}from"../../../utils/path/is-local-link.js";import{findRedirect as u}from"./find-redirect.js";function x(r,n,c,y,d=!0){const f=new Set(n),i=new Set,e=[...n];function l(o){if(f.has(o)){const m=e.indexOf(o);return{type:"cycle",cycle:m>=0?e.slice(m).concat(o):[]}}f.add(o),e.push(o);const t=d?u(o,c,y):c[o]?.to?{to:c[o].to,from:o}:null;if(!t?.to||!p(t.to))return{type:"no-cycle"};if(t.from){if(i.has(t.from))return{type:"cycle",cycle:[...e,t.from,t.to,t.from]};i.add(t.from)}const s=a(t.to).toLowerCase();return s.endsWith("*")?{type:"no-cycle"}:l(s)}return l(r)}export{x as followRedirectChain};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Store } from '../../store';
|
|
2
|
+
/**
|
|
3
|
+
* Validates redirects configuration: detects self-redirects, circular redirects,
|
|
4
|
+
* and redirects that point to a non-existent page. Reports each issue
|
|
5
|
+
* via the link checker so they appear in validation output.
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateRedirects(store: Store): void;
|
|
8
|
+
//# sourceMappingURL=validate-redirects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import h from"node:path";import{existsSync as R,lstatSync as w,readdirSync as N}from"node:fs";import{CONFIG_FILE_NAME as y}from"../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as F}from"../../constants/common.js";import{normalizeRouteSlug as s}from"../../../utils/path/normalize-route-slug.js";import{isLocalLink as C}from"../../../utils/path/is-local-link.js";import{reporter as T}from"../../tools/notifiers/reporter.js";import{followRedirectChain as k}from"./follow-redirect-chain.js";function D(e){const i=e.getConfig().redirects;if(!i)return;const o=e.getGlobalConfig("wildcardRedirectsTree")??{},c=e.getGlobalConfig("originalRedirectSources");for(const[r,l]of Object.entries(i)){const t=l?.to;if(!t||c&&!c.includes(r))continue;const d=r.toLowerCase(),L=t.toLowerCase(),m=r.endsWith("*"),f=t.endsWith("*");if(f)continue;const u=a=>{T.reportBrokenLink({type:"BROKEN_LINK",brokenLinkType:"LINK",sourceFileRelativePath:y,sourceFileLocation:{line:0},title:r,link:t,rawLink:t,message:a})};if(z(r,t,m,f)){u(`Redirect from "${r}" points to the same page. This causes an infinite redirect loop.`);continue}if(m&&!f&&C(t)){const a=s(r.split("*")[0]).toLowerCase(),p=s(L);if(a===p){u(`Circular redirect: "${r}" points to the same base path "${t}", causing an infinite redirect loop.`);continue}}if(!m&&!f&&C(t)){const a=s(d),p=s(L),g=k(p,[a],i,o,!1);if(g.type==="cycle"&&g.cycle.length>0){u(`Circular redirect: ${g.cycle.join(" \u2192 ")}.`);continue}}C(t)&&I(t,e)&&u(`Redirect target "${t}" does not exist. Check that the page or route exists.`)}}function z(e,n,i,o){if(!i&&!o){const c=s(e).toLowerCase(),r=s(n).toLowerCase();return c===r}return!1}function I(e,n){const i=s(e).toLowerCase();return n.slugHasRouteOrRedirect(i)?!1:!v(e,n)}function v(e,n){const o=decodeURI(e.split("?")[0].split("#")[0]).replace(/^\/+/,"");if(!o)return!1;const c=n.contentDir;return c?S(c,o)||S(h.join(c,F),o):!1}function S(e,n){const i=x(e,n);return i?P(i):!1}function x(e,n){const i=n.split("/").filter(Boolean);let o=e;for(const c of i){const r=h.join(o,c);if(R(r)){o=r;continue}let l;try{l=N(o)}catch{return null}const t=l.find(d=>d.toLowerCase()===c.toLowerCase());if(!t)return null;o=h.join(o,t)}return o}function P(e){if(!R(e))return!1;try{return w(e).isFile()}catch{return!1}}export{D as validateRedirects};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{envConfig as c}from"../../../config/env-config.js";import{getClientIp as v}from"../../utils/get-client-ip.js";import{
|
|
1
|
+
import{envConfig as c}from"../../../config/env-config.js";import{getClientIp as v}from"../../utils/get-client-ip.js";import{toAttribute as t,getAttributesStringValue as _}from"./otlp.js";const g=c.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces";async function h(e){const s=await e.req.json(),u=m(e),o={resourceSpans:s.resourceSpans.map(n=>{const r=_(n.resource.attributes.find(i=>i.key==="session_id"));return r?{...n,resource:{...n.resource,attributes:[...n.resource.attributes]},scopeSpans:n.scopeSpans.map(i=>({...i,spans:i.spans.map(a=>({...a,attributes:a.name.startsWith("event.")&&a.name!=="event.undefined"?b(a,u,r):a.attributes}))}))}:n})};return await fetch(g,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)}),e.newResponse(null,200,{})}function m(e){const s=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,u=v(e.req.raw)||e.req.raw.context.remoteAddr?.hostname,o=e.req.raw.headers.get("user-agent"),n=e.req.raw.headers.get("accept-language"),r=n?.split(",")[0];return{userId:s,clientIp:u,userAgent:o||void 0,acceptLanguage:n||void 0,locale:r}}function p(e,s,u){const o=f(e.userId,s),n=new Date(Math.floor(Number(u.startTimeUnixNano)/1e6)).toISOString(),r=u.attributes.find(d=>d.key==="cloudevents.event_data.uri"),i=r&&"stringValue"in r.value?[t("cloudevents.event_data.page.uri",r.value.stringValue)]:[];return[t("cloudevents.event_spec_version","1.0"),t("cloudevents.event_object","event"),t("cloudevents.event_origin","realm-ui"),t("cloudevents.event_env",c.redoclyEnv),t("cloudevents.event_source",o.uri),t("cloudevents.event_source_details.id",o.id),t("cloudevents.event_source_details.object",o.object),t("cloudevents.event_source_details.uri",o.uri),t("cloudevents.event_actor.id",o.id),t("cloudevents.event_actor.object",o.object),t("cloudevents.event_actor.uri",o.uri),t("cloudevents.event_data_content_type","application/json; charset=utf-8"),t("cloudevents.event_organization_id",c.ORGANIZATION_ID),t("cloudevents.event_organization_slug",c.ORGANIZATION_SLUG),t("cloudevents.event_project_id",c.PROJECT_ID),t("cloudevents.event_project_slug",c.PROJECT_SLUG),t("cloudevents.event_session_id",s),t("cloudevents.event_time",n),t("cloudevents.event_client_ip",e.clientIp),t("cloudevents.event_user_agent",e.userAgent),...i]}function b(e,s,u){return[...e.attributes.filter(n=>{const r="stringValue"in n.value&&n.value.stringValue==="",i=/cloudevents\.event_source_details\..+/.test(n.key);return!(r||i)}),...p(s,u,e)].filter(n=>n!==void 0)}function f(e,s){return e?{id:e,object:"user",uri:`${c.MAIN_API_URL}/users/${e}`}:{id:l(s),object:"anonymous",uri:`${c.MAIN_API_URL}/anonymous/${l(s)}`}}function l(e){return e.replace("ses_","ann_")}export{h as otelTracesHandler,b as toCloudEventAttributes,f as toSource};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ApiRoutesWorkerParams, ApiRoutesWorkerResponse } from '../types/plugins/api-routes.js';
|
|
2
2
|
import type { RenderPayload } from '../../types/ssr.js';
|
|
3
3
|
import type { ScorecardsWorkerParams, ScorecardsWorkerResponse } from '../types/plugins/scorecards.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { McpToolExecutionParams, McpToolWorkerResponse } from '../plugins/mcp/types.js';
|
|
5
5
|
import type { SCORECARDS_WORKER_KEY } from './scorecards-worker-pool.js';
|
|
6
6
|
import type { API_ROUTES_WORKER_KEY } from './api-routes-worker-pool.js';
|
|
7
7
|
import type { SSR_WORKER_KEY } from './ssr-worker-pool.js';
|
|
@@ -25,7 +25,7 @@ export type WorkerTypeMapping = {
|
|
|
25
25
|
response: ScorecardsWorkerResponse;
|
|
26
26
|
};
|
|
27
27
|
[MCP_TOOL_WORKER_KEY]: {
|
|
28
|
-
params: [
|
|
28
|
+
params: [McpToolExecutionParams];
|
|
29
29
|
response: McpToolWorkerResponse;
|
|
30
30
|
};
|
|
31
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import n from"workerpool";import{basename as a,dirname as s,resolve as l}from"node:path";import{fileURLToPath as h}from"node:url";import{envConfig as m}from"../config/env-config.js";class w{#t=null;#r;constructor(o){this.#r=o,this.#r.lazy||(this.#t=this.#o())}#o(){const{workerScript:o,lazy:t,...r}=this.#r;let e=this.#e(o);return n.pool(e,{...r})}#e(o){let t=o;if(!t.endsWith(".js")&&!t.endsWith(".mjs")&&(t=`${t}.${m.isDevelopMode?"js":"mjs"}`),!t.startsWith("."))return t;const r=s(h(import.meta.url)),e=a(r)==="chunks"?s(r):r;return l(e,t)}#i(){return this.#t||(this.#t=this.#o()),this.#t}async exec(o,t,r){let i=this.#i().exec(o,t);return r?.timeout&&(i=i.timeout(r.timeout)),await i}async terminate(){this.#t&&(await this.#t.terminate(),this.#t=null)}}export{w as WorkerPool};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthProviderType, REDOCLY_TEAMS_RBAC, RbacScopeItems } from '@redocly/config';
|
|
1
|
+
import type { AuthProviderType, REDOCLY_TEAMS_RBAC, REDOCLY_ROUTE_RBAC, RbacScopeItems } from '@redocly/config';
|
|
2
2
|
import type { UiAccessibleConfig } from '@redocly/config';
|
|
3
3
|
export type GlobalData = UiAccessibleConfig & {
|
|
4
4
|
authIdps?: Array<{
|
|
@@ -8,7 +8,12 @@ export type GlobalData = UiAccessibleConfig & {
|
|
|
8
8
|
rbac?: object;
|
|
9
9
|
apiProducts?: {
|
|
10
10
|
[apiProductId: string]: {
|
|
11
|
-
slug
|
|
11
|
+
slug?: string;
|
|
12
|
+
[REDOCLY_TEAMS_RBAC]?: RbacScopeItems;
|
|
13
|
+
[REDOCLY_ROUTE_RBAC]?: {
|
|
14
|
+
slug?: string;
|
|
15
|
+
fsPath?: string;
|
|
16
|
+
};
|
|
12
17
|
};
|
|
13
18
|
};
|
|
14
19
|
l10n?: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/reef",
|
|
3
|
-
"version": "0.132.0-next.
|
|
3
|
+
"version": "0.132.0-next.7",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@opentelemetry/sdk-trace-web": "2.0.1",
|
|
30
30
|
"@opentelemetry/semantic-conventions": "1.34.0",
|
|
31
31
|
"@redocly/ajv": "8.18.0",
|
|
32
|
-
"@redocly/openapi-core": "2.
|
|
32
|
+
"@redocly/openapi-core": "2.25.2",
|
|
33
33
|
"@shikijs/transformers": "3.21.0",
|
|
34
34
|
"@tanstack/react-query": "5.62.3",
|
|
35
35
|
"@tanstack/react-table": "8.21.3",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"openapi-sampler": "^1.7.2",
|
|
68
68
|
"os-browserify": "0.3.0",
|
|
69
69
|
"path-browserify": "1.0.1",
|
|
70
|
-
"picomatch": "2.3.
|
|
70
|
+
"picomatch": "2.3.2",
|
|
71
71
|
"react": "^19.2.4",
|
|
72
72
|
"react-calendar": "5.1.0",
|
|
73
73
|
"react-date-picker": "11.0.0",
|
|
@@ -91,14 +91,14 @@
|
|
|
91
91
|
"xpath": "0.0.34",
|
|
92
92
|
"yaml-ast-parser": "0.0.43",
|
|
93
93
|
"zod": "^3.25.76",
|
|
94
|
-
"@redocly/asyncapi-docs": "1.9.0-next.
|
|
95
|
-
"@redocly/config": "0.
|
|
96
|
-
"@redocly/graphql-docs": "1.9.0-next.
|
|
97
|
-
"@redocly/openapi-docs": "3.20.0-next.
|
|
94
|
+
"@redocly/asyncapi-docs": "1.9.0-next.6",
|
|
95
|
+
"@redocly/config": "0.46.1",
|
|
96
|
+
"@redocly/graphql-docs": "1.9.0-next.6",
|
|
97
|
+
"@redocly/openapi-docs": "3.20.0-next.6",
|
|
98
98
|
"@redocly/portal-legacy-ui": "0.15.0-next.0",
|
|
99
|
-
"@redocly/portal-plugin-mock-server": "0.17.0-next.
|
|
100
|
-
"@redocly/realm-asyncapi-sdk": "0.10.0-next.
|
|
101
|
-
"@redocly/theme": "0.64.0-next.
|
|
99
|
+
"@redocly/portal-plugin-mock-server": "0.17.0-next.6",
|
|
100
|
+
"@redocly/realm-asyncapi-sdk": "0.10.0-next.1",
|
|
101
|
+
"@redocly/theme": "0.64.0-next.4"
|
|
102
102
|
},
|
|
103
103
|
"peerDependencies": {
|
|
104
104
|
"react": "^19.2.4",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{nanoid as R}from"nanoid";import{envConfig as i}from"../../../../config/env-config.js";import{logger as h}from"../../../../tools/notifiers/logger.js";import{sha as g}from"../../../../utils/crypto/sha.js";const s={};function c(t){if(t.toLowerCase().includes("gantt")&&!t.toLowerCase().includes("todaymarker off")){const o=new Date().toISOString().split("T")[0];return g(t+o)}return g(t)}async function O(t,d="default"){if(t.length===0)return[];const r=[];for(let e=0;e<t.length;e++){const n=c(t[e]);s[n]||r.push(t[e])}if(r.length){const e=i.REDOCLY_MERMAID_MICROSERVICE_URL||"https://api.redocly.com/mermaid",n=h.startTiming(),f=R(),m=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","x-request-id":i.REQUEST_ID||""},body:JSON.stringify({definitions:r,rayId:f,theme:d,organizationId:i.ORGANIZATION_ID})});if(m.status!==200)throw new Error(`Something went wrong during remote rendering. Please, save this Ray ID: ${f} and contact Redocly team.`);h.verboseTime(n,"Rendered mermaid diagrams (%s)",r.length);const l=await m.json();for(let a=0;a<r.length;a++){const p=c(r[a]);s[p]=l[a]}}const o=[];for(let e=0;e<t.length;e++){const n=c(t[e]);o.push(s[n])}return o}export{s as cache,c as generateDiagramHash,O as renderMermaid};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { JSONSchemaType } from '@redocly/ajv';
|
|
2
|
-
import type { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
3
|
-
import type { OpenAPIDefinition } from '@redocly/openapi-docs';
|
|
4
|
-
import type { AccessInfo, ApiDescriptionInfo, McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
|
|
5
|
-
export type DocsMcpToolRegistrationOptions = {
|
|
6
|
-
server: McpServer;
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
outdir: string;
|
|
9
|
-
apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
|
|
10
|
-
headers?: Record<string, string | string[] | undefined>;
|
|
11
|
-
accessInfo: AccessInfo;
|
|
12
|
-
products?: string[];
|
|
13
|
-
};
|
|
14
|
-
/** Keys that can be passed to the tool context (excludes 'server' which is not serializable) */
|
|
15
|
-
export type ContextKey = Exclude<keyof DocsMcpToolRegistrationOptions, 'server'>;
|
|
16
|
-
export type ApiDefinitionResult = {
|
|
17
|
-
success: true;
|
|
18
|
-
definition: OpenAPIDefinition;
|
|
19
|
-
} | {
|
|
20
|
-
success: false;
|
|
21
|
-
response: McpToolWorkerResponse;
|
|
22
|
-
};
|
|
23
|
-
export declare abstract class DocsMcpTool<TName extends keyof ToolArgsMap> {
|
|
24
|
-
abstract readonly name: TName;
|
|
25
|
-
abstract readonly description: string;
|
|
26
|
-
readonly schema: JSONSchemaType<ToolArgsMap[TName]>;
|
|
27
|
-
/**
|
|
28
|
-
* Array of context keys that this tool requires.
|
|
29
|
-
* The base class will extract these from DocsMcpToolRegistrationOptions
|
|
30
|
-
* and pass them to executeAction.
|
|
31
|
-
*/
|
|
32
|
-
abstract readonly requiredContext: readonly ContextKey[];
|
|
33
|
-
constructor(schema: JSONSchemaType<ToolArgsMap[TName]>);
|
|
34
|
-
/**
|
|
35
|
-
* Builds the context object by picking only the required keys from options.
|
|
36
|
-
*/
|
|
37
|
-
protected getContext(options: DocsMcpToolRegistrationOptions): McpToolWorkerParams['context'];
|
|
38
|
-
register(options: DocsMcpToolRegistrationOptions): void;
|
|
39
|
-
/**
|
|
40
|
-
* Wraps the tool execution with telemetry and error handling.
|
|
41
|
-
* Subclasses should call this method and implement executeAction for the actual logic.
|
|
42
|
-
*/
|
|
43
|
-
execute(args: ToolArgsMap[TName], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
|
|
44
|
-
/**
|
|
45
|
-
* Implement the actual tool logic here. Called by execute() which handles telemetry.
|
|
46
|
-
*/
|
|
47
|
-
protected abstract executeAction(args: ToolArgsMap[TName], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
|
|
48
|
-
/**
|
|
49
|
-
* Helper method for tools that need to load an API definition.
|
|
50
|
-
* Handles finding the API by name and loading the definition from the file system.
|
|
51
|
-
* Requires 'outdir' and 'accessInfo' in requiredContext.
|
|
52
|
-
*/
|
|
53
|
-
protected getApiDefinition(name: string, context: McpToolWorkerParams['context']): Promise<ApiDefinitionResult>;
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=docs-mcp-tool.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{telemetry as o}from"../../../../telemetry/index.js";import{mcpToolWorkers as n,MCP_TOOL_WORKER_KEY as a}from"../../../../workers/mcp-tool-worker-pool.js";import{findApiDescriptionByName as p}from"../utils.js";import{getApiDescriptionFromFs as m}from"./utils.js";function u(i,t,s){return{toolName:i,args:t,context:s}}class g{schema;constructor(t){this.schema=t}getContext(t){const s={};for(const e of this.requiredContext)s[e]=t[e];return{...s,apiDescriptionsMap:t.apiDescriptionsMap}}register(t){const s=async(e,r)=>{const c=u(this.name,e,this.getContext(t));return await n.exec(a,[c],{timeout:6e4})};t.server.tool(this.name,this.description,this.schema,s)}async execute(t,s){try{const e=await this.executeAction(t,s);return e.isError?o.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:this.name,message:`${e.content.map(({text:r})=>r).join(" ")}`,stack:""}]):o.sendMcpToolCalledMessage([{object:"mcp_server",server_type:"docs",tool:this.name}]),e}catch(e){throw o.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:this.name,message:e instanceof Error?e.message:String(e),stack:e instanceof Error&&e.stack||""}]),e}}async getApiDefinition(t,s){if(!s.outdir||!s.accessInfo)throw new Error("Missing required context: outdir and accessInfo");const e=p(s.apiDescriptionsMap,t);if(!e)return{success:!1,response:{content:[{type:"text",text:`No API found matching "${t}".`}]}};const r=await m({relativePath:e.relativePath||"",outdir:s.outdir,accessInfo:s.accessInfo});return r?{success:!0,definition:r}:{success:!1,response:{content:[{type:"text",text:`Spec not found from the file system with "${t}".`}]}}}}export{g as DocsMcpTool};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ApiFunctionsContext, ApiRoutesHandler, PageStaticData } from '@redocly/config';
|
|
2
|
-
import type { McpServerInstance, McpServerType } from '../types.js';
|
|
3
|
-
export type McpRequestHandlerDependencies = {
|
|
4
|
-
createServerInstance: (context: ApiFunctionsContext, staticData: PageStaticData, headers: Record<string, string | string[] | undefined>, request: Request) => Promise<McpServerInstance>;
|
|
5
|
-
serverType: McpServerType;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Creates a standardized MCP request handler
|
|
9
|
-
*/
|
|
10
|
-
export declare function createMcpRequestHandler(dependencies: McpRequestHandlerDependencies): ApiRoutesHandler;
|
|
11
|
-
//# sourceMappingURL=mcp-request-handler.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{toFetchResponse as p,toReqRes as h}from"fetch-to-node";import{createMethodNotAllowedError as w,withErrorHandling as y}from"./errors.js";function m(s){const{createServerInstance:a,serverType:c}=s;return async(e,d,i)=>{let r;return y(async()=>{const n={};e.headers.forEach((t,l)=>{n[l]=t});const{req:u,res:o}=h(e);switch(e.method){case"GET":return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need register it in your MCP Client (VS Code, Cursor, Claude Code, etc.) using that URL: ${e.url}`}),{status:405,headers:{"Content-Type":"application/json"}});case"POST":{r=await a(d,i,n,e);const t=await e.json();return await r.transport.handleRequest(u,o,t),p(o)}default:return w()}},c,async()=>{r&&(await r.cleanup(),r=void 0)})}}export{m as createMcpRequestHandler};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
2
|
-
import { StreamableHTTPServerTransport } from '@redocly/mcp-typescript-sdk/server/streamableHttp.js';
|
|
3
|
-
import type { Implementation } from '@redocly/mcp-typescript-sdk/types.js';
|
|
4
|
-
import type { McpServerInstance, McpServerType } from '../types.js';
|
|
5
|
-
export declare abstract class BaseMcpServer {
|
|
6
|
-
#private;
|
|
7
|
-
protected server: McpServer;
|
|
8
|
-
protected transport: StreamableHTTPServerTransport;
|
|
9
|
-
constructor(config: Implementation);
|
|
10
|
-
protected abstract registerTools(): void;
|
|
11
|
-
initialize(): Promise<McpServerInstance>;
|
|
12
|
-
clearCleanupTimeout(): void;
|
|
13
|
-
cleanup(): Promise<void>;
|
|
14
|
-
protected abstract getServerType(): McpServerType;
|
|
15
|
-
}
|
|
16
|
-
export declare function createMcpServerInstance<T extends BaseMcpServer>(serverClass: new (...args: any[]) => T, ...args: any[]): Promise<McpServerInstance>;
|
|
17
|
-
//# sourceMappingURL=base-server.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{McpServer as t}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as s}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{telemetry as i}from"../../../telemetry/index.js";class p{server;transport;#r;#t=!1;constructor(e){this.server=new t(e,{capabilities:{logging:{}}}),this.transport=new s({sessionIdGenerator:void 0})}async initialize(){return this.registerTools(),await this.server.connect(this.transport),{server:this.server,transport:this.transport,cleanup:this.cleanup.bind(this)}}clearCleanupTimeout(){this.#r&&(clearTimeout(this.#r),this.#r=void 0)}#e;async cleanup(){return this.#e?this.#e:(this.#e=this.#s(),this.#e)}async#s(){if(!this.#t){this.#t=!0,this.clearCleanupTimeout();try{this.transport.close()}catch(e){throw i.sendMcpErrorMessage([{object:"mcp_server",server_type:this.getServerType(),message:e?.message||"Unknown cleanup error",stack:e?.stack||""}]),e}}}}async function h(r,...e){return await new r(...e).initialize()}export{p as BaseMcpServer,h as createMcpServerInstance};
|