@redocly/realm 0.137.0 → 0.138.0-next.0
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 +38 -2
- package/dist/bin.js +1 -1
- package/dist/cli/eject/themeOperations.js +1 -1
- package/dist/cli/generate/generate-tag.js +1 -1
- package/dist/cli/generate/generate.js +1 -1
- package/dist/client/app/hooks/catalog/useCatalog.d.ts +1 -2
- package/dist/client/app/l10n/hooks/useL10n.js +1 -1
- package/dist/client/app/l10n/index.js +1 -1
- package/dist/client/app/search/sse-parser.d.ts +5 -2
- package/dist/client/app/search/sse-parser.js +2 -2
- package/dist/client/constants/ai-search.d.ts +8 -0
- package/dist/client/constants/ai-search.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/markdoc/helpers/guards/is-example-node.d.ts +2 -1
- package/dist/markdoc/helpers/guards/is-example-node.js +1 -1
- package/dist/markdoc/nodes/fence/index.js +1 -1
- package/dist/server/constants/entitlements.d.ts +1 -2
- package/dist/server/esbuild/plugins/styled-components-ssr.js +1 -1
- package/dist/server/esbuild/plugins/themes-resolver.js +2 -2
- package/dist/server/fs/cache.js +1 -1
- package/dist/server/fs/fs.js +1 -1
- package/dist/server/fs/utils/remove-l10n-prefix.js +1 -1
- package/dist/server/persistence/file-hashes/repositories/file-hashes-repository.d.ts +1 -2
- package/dist/server/persistence/file-hashes/services/file-hashes-service.d.ts +1 -2
- package/dist/server/plugins/analytics/rudderstack/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/segment/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/segment/build-script.js +3 -3
- package/dist/server/plugins/api-docs/loader.d.ts +2 -3
- package/dist/server/plugins/api-docs/options.d.ts +1 -1
- package/dist/server/plugins/api-docs/search/get-ai-search-documents.d.ts +1 -1
- package/dist/server/plugins/api-docs/utils/decorators.js +1 -1
- package/dist/server/plugins/api-functions/index.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/types/extractors.d.ts +1 -2
- package/dist/server/plugins/catalog-entities/utils/openapi-component-content-extractor.d.ts +1 -2
- package/dist/server/plugins/catalog-entities/utils/openapi-schema-resolver.d.ts +1 -2
- package/dist/server/plugins/config-parser/format-error.js +4 -4
- package/dist/server/plugins/l10n/index.js +1 -1
- package/dist/server/plugins/lifecycle.js +2 -2
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-svg-content.js +1 -1
- package/dist/server/plugins/markdown/compiler.js +1 -1
- package/dist/server/plugins/markdown/errors.js +1 -1
- package/dist/server/plugins/markdown/markdoc/reparse-example-fences.d.ts +7 -0
- package/dist/server/plugins/markdown/markdoc/reparse-example-fences.js +1 -0
- package/dist/server/plugins/markdown/markdoc/resolve-raw-partials.js +1 -1
- package/dist/server/plugins/markdown/runtime-transform.js +1 -1
- package/dist/server/plugins/markdown/search/to-markdown.js +20 -20
- package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +7 -2
- package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -1
- package/dist/server/plugins/mcp/codemode/invoke-tool.js +1 -1
- package/dist/server/plugins/mcp/codemode/sandbox/unknown-tool-hint.d.ts +5 -1
- package/dist/server/plugins/mcp/codemode/sandbox/unknown-tool-hint.js +2 -2
- package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/tool-errors.d.ts +4 -0
- package/dist/server/plugins/mcp/codemode/tools/tool-errors.js +1 -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/tool-schemas.d.ts +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/submit-feedback.d.ts +7 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/core/submit-feedback.js +3 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/core/types.d.ts +6 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +1 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoint-info.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoints.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-full-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-security-schemes.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.d.ts +16 -4
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/utils/api-name-matching.d.ts +6 -1
- package/dist/server/plugins/mcp/docs-mcp/utils/api-name-matching.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/utils/api-titles.d.ts +8 -0
- package/dist/server/plugins/mcp/docs-mcp/utils/api-titles.js +1 -1
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/index.js +1 -1
- package/dist/server/plugins/nav-utils.js +1 -1
- package/dist/server/plugins/search/llmstxt/is-included-in-llms-txt.d.ts +1 -2
- package/dist/server/sandbox/constants/host-functions.d.ts +3 -0
- package/dist/server/sandbox/constants/host-functions.js +1 -1
- package/dist/server/sandbox/constants/sandbox.d.ts +10 -0
- package/dist/server/sandbox/constants/sandbox.js +1 -1
- package/dist/server/sandbox/sandbox.js +3 -3
- package/dist/server/sandbox/types.d.ts +3 -0
- package/dist/server/sandbox/utils/read-result.d.ts +8 -0
- package/dist/server/sandbox/utils/read-result.js +1 -0
- package/dist/server/sandbox/utils/setup-host-functions.js +3 -3
- package/dist/server/ssr/index.js +1 -1
- package/dist/server/store.d.ts +1 -1
- package/dist/server/store.js +1 -1
- package/dist/server/tools/notifiers/helpers/privacy/remove-pii.js +1 -1
- package/dist/server/types/plugins/common.d.ts +1 -2
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.d.ts +1 -1
- package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.js +1 -1
- package/dist/server/web-server/routes/feedback.d.ts +3 -1
- package/dist/server/web-server/routes/feedback.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/otel/otel.js +1 -1
- package/dist/server/web-server/utils/legacy-openapi-redirects.js +1 -1
- package/dist/types/global-data.d.ts +1 -2
- package/dist/utils/slugger.js +1 -1
- package/dist/utils/url/sanitize-redirect-pathname.js +1 -1
- package/package.json +4 -4
package/dist/server/ssr/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withPathPrefix as O}from"@redocly/theme/core/utils";import{SSR_RENDER_MODE as y}from"../constants/common.js";import{logger as b}from"../tools/notifiers/logger.js";import{canAccessResource as L,filterDataByAccessDeep as d,isResourcePubliclyAccessible as _}from"../utils/rbac.js";import{readSharedData as x}from"../utils/index.js";import{render as C}from"./render.js";import{getServerProps as T}from"./server-side-props/get-server-props.js";import{ssrWorkers as
|
|
1
|
+
import{withPathPrefix as O}from"@redocly/theme/core/utils";import{SSR_RENDER_MODE as y}from"../constants/common.js";import{logger as b}from"../tools/notifiers/logger.js";import{canAccessResource as L,filterDataByAccessDeep as d,isResourcePubliclyAccessible as _}from"../utils/rbac.js";import{readSharedData as x}from"../utils/index.js";import{render as C}from"./render.js";import{getServerProps as T}from"./server-side-props/get-server-props.js";import{ssrWorkers as $,SSR_WORKER_KEY as j}from"../workers/ssr-worker-pool.js";async function G(e,s,a,r,o,c=!1){const w=b.startTiming(),E=r.routesSharedData.get(e.slug)||{},S=s.sharedDataIds||{},m={...E,...S},{isAuthenticated:g,teams:u,claims:{name:q,picture:I,email:f}}=a?.get("auth")||{claims:{}},t={isAuthenticated:g,email:f,teams:u},R=Object.fromEntries(await Promise.all(Object.entries(m).map(async([H,D])=>[D,await x(D,r.outdir)]))),P=d(R,t,r.config.access?.rbac,r.config.access?.requiresLogin),v=d(r.globalData,t,r.config.access?.rbac,r.config.access?.requiresLogin),p=L(e,t,r.config.access?.rbac,r.config.access?.requiresLogin),A=!!r.compilationErrors?.length?{templateId:"compilation-error",props:{compilationErrors:r.compilationErrors},sharedDataIds:{}}:null,h={page:{templateId:e.templateId,isPublic:_(e,r.config),slug:O(e.slug),versions:d(e.versions,t,r.config.access?.rbac,r.config.access?.requiresLogin),props:s,sharedDataIds:p?m:{},product:e.product,request:{search:a?.req.raw.context.url?.search||"",url:a?.req.raw.context.url?.href||""},userInfo:{isAuthenticated:g,name:q,picture:I,email:f,teams:u},...A},store:{globalData:v,config:r.config,ssr:r.ssr,hasSitemap:r.hasSitemap},sharedData:p?P:{},serverOutDir:r.serverOutDir,outdir:r.outdir,ssrHref:k(a),userAgent:a?.req.raw.headers.get("user-agent")||"",telemetry:o,omitSuspense:c};let i,n,l;return y==="worker"?{html:i,statusCode:n,error:l}=await $.exec(j,[h]):{html:i,statusCode:n,error:l}=await C(h),b.verboseTime(w,`Page rendered ${e.slug}`),{html:i,props:s,statusCode:n,error:l}}function k(e){const s=e?.req.raw.url;if(!s)return"";const a=new URL(s),r=e?.req.raw.headers,o=r?.get("x-forwarded-proto")||a.protocol.replace(":",""),c=r?.get("x-forwarded-host")||a.host;return`${o}://${c}`}export{T as getServerProps,G as renderPage};
|
package/dist/server/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Node } from '@markdoc/markdoc';
|
|
2
2
|
import type { JSX } from 'react';
|
|
3
3
|
import type { CommonError, GlobalData } from '../types/index.js';
|
|
4
4
|
import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts, WildcardRedirectsTree, RedirectOptions, McpToolRegistration, McpToolSchema, MarkdocOptions } from './types';
|
package/dist/server/store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import A from"@markdoc/markdoc";import{getPathnameForLocale as T}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as M}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as O}from"./constants/common.js";import{isObject as k}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 D}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 H}from"./utils/crypto/sha1.js";import{envConfig as G,setEnv as _}from"./config/env-config.js";import{KvService as B}from"./persistence/kv/services/kv-service.js";import{SandboxContext as F}from"./utils/sandbox-context.js";import{writeSharedData as I}from"./utils/index.js";import{renderComponents as N}from"./ssr/render.js";import{readStaticData as V,writeStaticData as q}from"./utils/static-data.js";import{parseAndResolveMarkdoc as U}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as v}from"./entitlements/entitlements-provider.js";import{isL10nPath as x}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 W}from"./utils/redirects/find-redirect.js";import{followRedirectChain as $}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as z}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Y}from"../cli/telemetry/helpers/trace-step.js";const E={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},P="PLAN_GATES",Z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Oe="userDefinedApiFunctions";class b{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;skills=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:r}){this.#i=s,this.outdir=e,this.serverMode=t,this.serverOutDir=r,F.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(a=>{this.#n=a})}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 r of this.listeners.get(e)||new Set)s?r(s,...t):r(...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 Y("com.redocly.build.reloadMarkdocOptions",async()=>{const e=v.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!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:r})=>{const{data:{info:a,ast:i},compoundHash:l}=await U(e,this.markdocOptions,{actions:this,context:s},r);for(const o of a.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,o,o);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(o),this.sharedDataDeps.set(n,c)}}for(const o of a.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(o),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(o),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&a.partials?.length)for(const o of t.routeSlugs){const n=this.routesPartials.get(o)||[];for(const c of a.partials)n.includes(c)||n.push(c);this.routesPartials.set(o,n)}return{info:a,ast:i,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);for(const l of s)for(const o in this.replacedEnvVars)if(o===l||o.startsWith(`${l}:`)){const n=o.split(":"),{error:c,value:d}=y(e,n);(c||d!==this.replacedEnvVars[o].replaced)&&delete this.replacedEnvVars[o]}const{resolvedObj:t,unsetEnvVars:r,replacedValues:a}=J(e);for(const l of r)this.unsetEnvVars.add(l);Object.assign(this.replacedEnvVars,a);const i=t.seo?.siteUrl?.trim();i&&(t.seo={...t.seo,siteUrl:URL.canParse(i)?new URL(i).origin:D(i)}),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!v.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const i=h(e).toLowerCase();this.config.redirects[i]=s;const{trackOriginalSource:l=!0}=t,o=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(o)&&!o.includes(i)&&o.push(i),i.endsWith("*")&&z(this.config.wildcardRedirectsTree,i)};getRedirect=e=>{const s=h(e).toLowerCase(),t=W(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(S(t.to)){const r=h(t.to).toLowerCase();if(!r.endsWith("*")&&$(r,[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 r=JSON.stringify(s),a=t??H(r);return this.#t[e]===a||(this.#t[e]=a,await I(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const r=D(e),a=this.routesSharedData.get(r)||{};a[s]=t,this.routesSharedData.set(r,a),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 r=this.getGlobalConfig(O)||{},a=new Set(t),i=Array.from(t);for(let o=0;o<i.length;o++){const n=i[o],c=r[n]?.partials??[];for(const d of c)a.has(d)||(a.add(d),i.push(d))}const l={};for(const o of a)s[o]&&(l[o]=s[o]);return l};addRoute=e=>{const t={...K(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 r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(a=>({code:a,name:a}));for(const a of r){const i=T(e,g,a.code,r);this.addRouteSharedData(i,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s){const r=this.mcpToolHandlers.get(t.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',t.name,e,r.importPath),this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const s of e){const t=this.mcpToolHandlers.get(s);t&&this.mcpToolHandlers.set(s,{...t,hasAvailabilityGate:!0})}};addSkills=e=>{for(const s of e)this.skills.set(s.slug,s),u.verbose("Discovered skill %s",s.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const s of e)this.mcpToolHandlers.delete(s)};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(i=>i.name.toLowerCase())),a=[...(this.config.responseHeaders[e]??[]).filter(i=>!t.has(i.name.toLowerCase())),...s];this.config.responseHeaders[e]=a};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,r=this.getRedirect(e);return t&&r?this.routesBySlug.get(h(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!S(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(r=>e===g?!x(r.fsPath):r.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 V(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},a=await e.getStaticData?.(e,r)||{},i=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=>i.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const o=this.getGlobalConfig("seo"),n=a?.frontmatter||{};return{...a,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...a.props,dynamicMarkdocComponents:Array.from(i),metadata:{...a?.props?.metadata,...e.metadata},seo:{title:M,...o,...a.props?.seo,siteUrl:o?.siteUrl},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(""):N(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.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,r]of Object.entries(E))switch(r){case"map":const a=Array.from(this[t].entries());e.push([t,a]);break;case"object":if(t==="config"){e.push([t,await this.getConfigWithEnvPlaceholders()]);break}e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[P]=G.PLAN_GATES,s}static fromJson(e,s){const t=new b(s);for(const[a,i]of Object.entries(E))switch(i){case"map":t[a]=new Map(e[a]);break;case"object":if(a==="config"){t.setGlobalConfig(e[a]);break}t[a]=e[a];break;default:throw new Error("Invalid format")}t.config[m]=Q(t.config[m]||{});const r=e[P];return r&&_("PLAN_GATES",r),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],r=s.split(":"),a=r.pop(),{error:i,value:l}=y(e,r);if(i||!k(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[a]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Z.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await w.panicOnBuildContentError(s)}}function Q(C){return L(C,e=>A.Ast.fromJSON(JSON.stringify(e)))}export{b as Store,Oe as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
1
|
+
import A from"@markdoc/markdoc";import{parseAndResolveMarkdoc as T}from"./plugins/markdown/compiler.js";import{getPathnameForLocale as M}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as O,MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as k}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{isObject as L}from"../utils/guards/is-object.js";import{mapObject as H}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as D}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 G}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as B}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{SandboxContext as I}from"./utils/sandbox-context.js";import{writeSharedData as N}from"./utils/index.js";import{renderComponents as V}from"./ssr/render.js";import{readStaticData as q,writeStaticData as U}from"./utils/static-data.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as v}from"./entitlements/entitlements-provider.js";import{isL10nPath as x}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 W}from"./utils/redirects/find-redirect.js";import{followRedirectChain as $}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as z}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Y}from"../cli/telemetry/helpers/trace-step.js";const E={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},P="PLAN_GATES",Z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Me="userDefinedApiFunctions";class b{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;skills=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:r}){this.#i=s,this.outdir=e,this.serverMode=t,this.serverOutDir=r,I.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(a=>{this.#n=a})}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 r of this.listeners.get(e)||new Set)s?r(s,...t):r(...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 Y("com.redocly.build.reloadMarkdocOptions",async()=>{const e=v.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!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()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:r})=>{const{data:{info:a,ast:i},compoundHash:l}=await T(e,this.markdocOptions,{actions:this,context:s},r);for(const o of a.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,o,o);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(o),this.sharedDataDeps.set(n,c)}}for(const o of a.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(o),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(o),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&a.partials?.length)for(const o of t.routeSlugs){const n=this.routesPartials.get(o)||[];for(const c of a.partials)n.includes(c)||n.push(c);this.routesPartials.set(o,n)}return{info:a,ast:i,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);for(const l of s)for(const o in this.replacedEnvVars)if(o===l||o.startsWith(`${l}:`)){const n=o.split(":"),{error:c,value:d}=y(e,n);(c||d!==this.replacedEnvVars[o].replaced)&&delete this.replacedEnvVars[o]}const{resolvedObj:t,unsetEnvVars:r,replacedValues:a}=J(e);for(const l of r)this.unsetEnvVars.add(l);Object.assign(this.replacedEnvVars,a);const i=t.seo?.siteUrl?.trim();i&&(t.seo={...t.seo,siteUrl:URL.canParse(i)?new URL(i).origin:D(i)}),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!v.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const i=h(e).toLowerCase();this.config.redirects[i]=s;const{trackOriginalSource:l=!0}=t,o=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(o)&&!o.includes(i)&&o.push(i),i.endsWith("*")&&z(this.config.wildcardRedirectsTree,i)};getRedirect=e=>{const s=h(e).toLowerCase(),t=W(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(S(t.to)){const r=h(t.to).toLowerCase();if(!r.endsWith("*")&&$(r,[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 r=JSON.stringify(s),a=t??G(r);return this.#t[e]===a||(this.#t[e]=a,await N(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const r=D(e),a=this.routesSharedData.get(r)||{};a[s]=t,this.routesSharedData.set(r,a),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 r=this.getGlobalConfig(k)||{},a=new Set(t),i=Array.from(t);for(let o=0;o<i.length;o++){const n=i[o],c=r[n]?.partials??[];for(const d of c)a.has(d)||(a.add(d),i.push(d))}const l={};for(const o of a)s[o]&&(l[o]=s[o]);return l};addRoute=e=>{const t={...K(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 r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(a=>({code:a,name:a}));for(const a of r){const i=M(e,g,a.code,r);this.addRouteSharedData(i,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s){const r=this.mcpToolHandlers.get(t.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',t.name,e,r.importPath),this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const s of e){const t=this.mcpToolHandlers.get(s);t&&this.mcpToolHandlers.set(s,{...t,hasAvailabilityGate:!0})}};addSkills=e=>{for(const s of e)this.skills.set(s.slug,s),u.verbose("Discovered skill %s",s.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const s of e)this.mcpToolHandlers.delete(s)};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(i=>i.name.toLowerCase())),a=[...(this.config.responseHeaders[e]??[]).filter(i=>!t.has(i.name.toLowerCase())),...s];this.config.responseHeaders[e]=a};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,r=this.getRedirect(e);return t&&r?this.routesBySlug.get(h(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!S(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(r=>e===g?!x(r.fsPath):r.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&&U(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return q(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},a=await e.getStaticData?.(e,r)||{},i=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=>i.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const o=this.getGlobalConfig("seo"),n=a?.frontmatter||{};return{...a,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...a.props,dynamicMarkdocComponents:Array.from(i),metadata:{...a?.props?.metadata,...e.metadata},seo:{title:O,...o,...a.props?.seo,siteUrl:o?.siteUrl},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(""):V(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.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,r]of Object.entries(E))switch(r){case"map":{const a=Array.from(this[t].entries());e.push([t,a]);break}case"object":if(t==="config"){e.push([t,await this.getConfigWithEnvPlaceholders()]);break}e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[P]=_.PLAN_GATES,s}static fromJson(e,s){const t=new b(s);for(const[a,i]of Object.entries(E))switch(i){case"map":t[a]=new Map(e[a]);break;case"object":if(a==="config"){t.setGlobalConfig(e[a]);break}t[a]=e[a];break;default:throw new Error("Invalid format")}t.config[m]=Q(t.config[m]||{});const r=e[P];return r&&B("PLAN_GATES",r),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],r=s.split(":"),a=r.pop(),{error:i,value:l}=y(e,r);if(i||!L(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[a]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Z.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await w.panicOnBuildContentError(s)}}function Q(C){return H(C,e=>A.Ast.fromJSON(JSON.stringify(e)))}export{b as Store,Me as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isString as m}from"../../../../../utils/string/is-string.js";const s={email:{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[email_removed]"},phone:{pattern:/(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})(?:\s?(?:ext|x|extension)\.?\s?(\d+))?/g,replacement:"[phone_removed]"},ssn:{pattern:/\b(?!000|666|9\d{2})\d{3}-?(?!00)\d{2}-?(?!0000)\d{4}\b/g,replacement:"[SSN_removed]"},creditCard:{pattern:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,replacement:"[credit_card_removed]"},address:{pattern:/\b\d+\s+[A-Za-z0-9\s,.-]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Lane|Ln|Drive|Dr|Court|Ct|Circle|Cir|Way|Place|Pl|Parkway|Pkwy|Terrace|Ter)\b/gi,replacement:"[address_removed]"},passport:{pattern:/\b[A-Z]{2}[0-9]{7}\b/g,replacement:"[passport_number_removed]"},driversLicense:{pattern:/\b[A-Z]{1,2}[0-9]{6,9}\b/g,replacement:"[driver_license_removed]"},zipCode:{pattern:/(?<!\d-)\b\d{5}(?:-\d{4})?\b(?!-\d)/g,replacement:"[zip_code_removed]"},bankAccount:{pattern:/\b\d{8,17}\b/g,replacement:"[bank_account_removed]"},dateOfBirth:{pattern:/\b(?:0[1-9]|1[0-2])[
|
|
1
|
+
import{isString as m}from"../../../../../utils/string/is-string.js";const s={email:{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[email_removed]"},phone:{pattern:/(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})(?:\s?(?:ext|x|extension)\.?\s?(\d+))?/g,replacement:"[phone_removed]"},ssn:{pattern:/\b(?!000|666|9\d{2})\d{3}-?(?!00)\d{2}-?(?!0000)\d{4}\b/g,replacement:"[SSN_removed]"},creditCard:{pattern:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,replacement:"[credit_card_removed]"},address:{pattern:/\b\d+\s+[A-Za-z0-9\s,.-]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Lane|Ln|Drive|Dr|Court|Ct|Circle|Cir|Way|Place|Pl|Parkway|Pkwy|Terrace|Ter)\b/gi,replacement:"[address_removed]"},passport:{pattern:/\b[A-Z]{2}[0-9]{7}\b/g,replacement:"[passport_number_removed]"},driversLicense:{pattern:/\b[A-Z]{1,2}[0-9]{6,9}\b/g,replacement:"[driver_license_removed]"},zipCode:{pattern:/(?<!\d-)\b\d{5}(?:-\d{4})?\b(?!-\d)/g,replacement:"[zip_code_removed]"},bankAccount:{pattern:/\b\d{8,17}\b/g,replacement:"[bank_account_removed]"},dateOfBirth:{pattern:/\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12][0-9]|3[01])[-/](?:19|20)\d{2}\b/g,replacement:"[date_removed]"}};function l(n={}){const e={email:{enabled:!0,replacement:"[email_removed]"},phone:{enabled:!0,replacement:"[phone_removed]"},ssn:{enabled:!0,replacement:"[SSN_removed]"},creditCard:{enabled:!0,replacement:"[credit_card_removed]"},address:{enabled:!0,replacement:"[address_removed]"},passport:{enabled:!0,replacement:"[passport_number_removed]"},driversLicense:{enabled:!0,replacement:"[driver_license_removed]"},zipCode:{enabled:!0,replacement:"[zip_code_removed]"},bankAccount:{enabled:!0,replacement:"[bank_account_removed]"},dateOfBirth:{enabled:!0,replacement:"[date_removed]"}};for(const[r,t]of Object.entries(n))e[r]?e[r]={...e[r],...t}:e[r]=t;return e}function b(n,e={}){if(!m(n))return n;const r=l(e);let t=n;for(const[c,a]of Object.entries(r)){if(!a.enabled)continue;const d=s[c],o=d?.pattern||a.pattern,p=a.replacement||d?.replacement||"[PII removed]";o&&(t=t.replace(o,p))}return t}export{b as removePii};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { REDOCLY_ROUTE_RBAC, REDOCLY_TEAMS_RBAC } from '@redocly/config';
|
|
1
|
+
import type { REDOCLY_ROUTE_RBAC, REDOCLY_TEAMS_RBAC, RbacScopeItems, RedirectConfig, RedoclyConfig, ServerPropsContext, ServerPropsRequest, PageProps, PageStaticData, NavItem, ResolvedNavItem, Version, MdOptions, KvService } from '@redocly/config';
|
|
2
2
|
import type { JSX } from 'react';
|
|
3
3
|
import type { JSONSchemaType } from '@redocly/ajv';
|
|
4
4
|
import type { Node } from '@markdoc/markdoc';
|
|
@@ -6,7 +6,6 @@ import type { ProductConfig } from '@redocly/theme/config';
|
|
|
6
6
|
import type { SearchFacet } from '@redocly/theme/core/types';
|
|
7
7
|
import type { GlobalData, Feature } from '../../../types/index.js';
|
|
8
8
|
import type { SearchDocument } from '../../types';
|
|
9
|
-
import type { RbacScopeItems, RedirectConfig, RedoclyConfig, ServerPropsContext, ServerPropsRequest, PageProps, PageStaticData, NavItem, ResolvedNavItem, Version, MdOptions, KvService } from '@redocly/config';
|
|
10
9
|
import type { LoaderFn } from '../fs';
|
|
11
10
|
import type { BundledApiDefinition } from '../../plugins/api-docs/loader';
|
|
12
11
|
import type { Cache } from '../../fs/cache';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as g,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as w}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as B}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as S,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as M}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as U}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as b}from"../constants/rbac.js";import{removeTrailingSlash as W}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const I=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Ct(t,e){const r=I.indexOf(t.toUpperCase()),n=I.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const _=`fsPath:${a}`,D=E[_]??P($(a));return E[_]=D,!!(n&&p(n))||!!(o&&D(o))};if(ot(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[L]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function jt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?F(o,e.teams):!0}function It(t,e){return O(t,b,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(B).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||(t.slug===k||t.slug===w||t.slug===U)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[g]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:F(s,e?.teams||[],e?.email)}function Ft(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(C))return!0;const o=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${C}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function Nt(t,e,r,n,o){if(!t.startsWith(M))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[
|
|
1
|
+
import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as g,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as w}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as B}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as S,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as M}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as U}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as b}from"../constants/rbac.js";import{removeTrailingSlash as W}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const I=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Ct(t,e){const r=I.indexOf(t.toUpperCase()),n=I.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const _=`fsPath:${a}`,D=E[_]??P($(a));return E[_]=D,!!(n&&p(n))||!!(o&&D(o))};if(ot(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[L]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function jt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?F(o,e.teams):!0}function It(t,e){return O(t,b,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(B).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||(t.slug===k||t.slug===w||t.slug===U)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[g]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:F(s,e?.teams||[],e?.email)}function Ft(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(C))return!0;const o=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${C}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function Nt(t,e,r,n,o){if(!t.startsWith(M))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function kt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==S):f=[S],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=N(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===g||c===A)continue;if(et.has(c)){s[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&rt(i)&&nt(i)}return o?void 0:s}return t}function wt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Bt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===L?[[s,c]]:[[s,c],...t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c])]),o=Object.fromEntries(n);return{...e,content:o}}async function Mt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function rt(t){return m(t)&&Object.keys(t).length>0}function nt(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function ot(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const st=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},Ut=async t=>{if(t){if(Object.keys(t).length===0)return{};if(st(t))return ct(t);await Y.panicOnContentError(`You are using an incorrect format of ${z("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},ct=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=W(n);r[o]=e.content[n]}e.content=r}return e};function bt(t,e){const r=t.fsPath,n=t.slug,o=[];if(G(e)&&(r||n)){const s=[r,n].filter(K),c=Q(e,s);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i);const f=T({content:{...J(e),...e.content}},t);o.push(...x(f))}else{const i=T(e,t);o.push(...x(i))}}else{const s=T(e,t);o.push(...x(s))}return it(e,o)}function x(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function it(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{I as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Bt as applyL10nToRbacConfig,Nt as canAccessAsset,jt as canAccessFeature,O as canAccessResource,Ft as canDownloadApiDefinition,it as expandTeamsForRead,x as extractTeamsFromScopeItems,N as filterDataByAccessDeep,kt as getAuthDetailsFromCookies,Ct as getHigherRole,bt as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,st as isRbacConfigValid,It as isResourcePubliclyAccessible,ct as normalizeRbacConfig,Ut as parseRbacConfig,wt as parseTeamClaimToArray,Mt as resolveDirectoryHashes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{entityFileSchema as
|
|
1
|
+
import{entityFileSchema as o,entityBaseProperties as p}from"@redocly/config";function a(r,t){const i=o.oneOf.find(e=>e.properties.type.const===t);if(!i){const e=Object.keys(r.entityTypes??{}).find(n=>n===t);if(!e)throw new Error(`Entity type: ${t} not found`);return{type:"object",properties:{...p,type:{const:e},metadata:{additionalProperties:!0,...r.entityTypes?.[e].metadataSchema},revision:{type:"string"}},additionalProperties:!1}}return{properties:{...i.properties,revision:{type:"string"}},additionalProperties:!1}}export{a as createEntityUpdateSchema};
|
|
@@ -8,6 +8,7 @@ type FeedbackData = {
|
|
|
8
8
|
lang?: string;
|
|
9
9
|
agent?: string;
|
|
10
10
|
targetFeature?: string;
|
|
11
|
+
origin?: string;
|
|
11
12
|
metadata?: Record<string, any>;
|
|
12
13
|
score?: number | string;
|
|
13
14
|
reasons?: string[];
|
|
@@ -16,7 +17,7 @@ type FeedbackData = {
|
|
|
16
17
|
email?: string;
|
|
17
18
|
};
|
|
18
19
|
export declare function normalizeFeedbackMetadata(metadata?: FeedbackData['metadata']): Record<string, any> | undefined;
|
|
19
|
-
export declare function normalizeFeedbackData({ component, path, location, lang, agent, targetFeature, score, max, reasons, comment, metadata, email, }: FeedbackData): {
|
|
20
|
+
export declare function normalizeFeedbackData({ component, path, location, lang, agent, targetFeature, origin, score, max, reasons, comment, metadata, email, }: FeedbackData): {
|
|
20
21
|
feedbackComponent: string;
|
|
21
22
|
path: string | undefined;
|
|
22
23
|
location: string | undefined;
|
|
@@ -28,6 +29,7 @@ export declare function normalizeFeedbackData({ component, path, location, lang,
|
|
|
28
29
|
email: string | undefined;
|
|
29
30
|
agent: string | undefined;
|
|
30
31
|
targetFeature: string | undefined;
|
|
32
|
+
origin: string | undefined;
|
|
31
33
|
metadata: Record<string, any> | undefined;
|
|
32
34
|
};
|
|
33
35
|
export declare function feedbackHandler(store: Store): (ctx: Context) => Promise<(Response & import("hono").TypedResponse<any, 200, "json">) | (Response & import("hono").TypedResponse<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FEEDBACK_API_URL as
|
|
1
|
+
import{FEEDBACK_API_URL as T}from"../../constants/common.js";import{fetchWithClient as k}from"../../utils/fetch-with-client.js";import{MAX_AGENT_LENGTH as y,MAX_CONTEXT_LENGTH as A,MAX_EMAIL_LENGTH as N,MAX_LANG_LENGTH as C,MAX_PATH_LENGTH as L,MAX_REASONS_COUNT as F,MAX_TARGET_FEATURE_LENGTH as j}from"../../constants/feedback.js";import{mapObject as S}from"../../../utils/object/map-object.js";import{getFeedbackClientIp as R}from"../utils/feedback-ip.js";import{canAccessResource as G}from"../../utils/rbac.js";const E=["form","api","mcp"];function t(n,e){if(n!=null)return String(n).replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,"").trim().slice(0,e)||void 0}function w(n){if(!n)return n;const e=["userAgent","firstName","lastName","auth_time","platform","id","email","ipAddress"];return S(n,(o,s)=>e.includes(s)?o:"*****")}function M({component:n,path:e,location:o,lang:s,agent:p,targetFeature:m,origin:f,score:r,max:i,reasons:c,comment:l,metadata:g,email:h}){const u=Array.isArray(c)?c.map(a=>t(String(a),A)).filter(a=>!!a).slice(0,F):void 0;return{feedbackComponent:n.toUpperCase(),path:t(e,L),location:t(o,A),lang:t(s,C),score:typeof r=="number"?r:void 0,maxScore:typeof i=="number"?i:void 0,reasons:u?.length?u:void 0,comment:t(l,A),email:t(h,N),agent:t(p,y),targetFeature:t(m,j),origin:f?.toUpperCase(),metadata:w(g)}}async function O(n,e){return(await k(T,{method:"POST",body:JSON.stringify(M(n)),headers:e})).json()}function z(n){return async e=>{const o=await e.req.json(),s=e.req.header("user-agent"),p=R(e.req.raw),m=e.req.header("Sec-Ch-Ua-Platform"),f={...o.metadata,userAgent:s,ipAddress:p,platform:m?m.replace(/"/g,""):"unknown"},r=[];(!o.path||o.path==="")&&r.push("`path` is required");const i=["sentiment","rating","comment","problem","mood","scale"];if(i.includes(o.component)||r.push(`\`component\` field should be one of ${i.join(", ")}.`),o.origin!==void 0&&!E.includes(String(o.origin).toLowerCase())&&r.push(`\`origin\` field should be one of ${E.join(", ")}.`),r.length)return e.json({errors:r},400);const{claims:c,isAuthenticated:l,teams:g}=e.get("auth"),h={isAuthenticated:l,email:c?.email,teams:g};if(Object.keys(n.config.access?.rbac||{}).length>0){const d=o.path,_=new URL(d).pathname,b=n.getRouteBySlug(_);if(!b)return e.json({errors:["Resource not found"]},404);if(!G(b,h,n.config.access?.rbac,n.config.access?.requiresLogin))return e.json({errors:["Forbidden: no permission to send feedback for resource"]},403)}const u={"Content-Type":"application/json"},a=c?.email||o?.email||f?.email;try{const d=await O({...o,email:a,metadata:{email:a,...f}},u);return e.json({message:"Thanks for your feedback",...d},200,{})}catch(d){return e.json({errors:["Failed to send feedback",d.message]},500)}}}export{z as feedbackHandler,M as normalizeFeedbackData,w as normalizeFeedbackMetadata};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCookie as A}from"hono/cookie";import{createHash as J,timingSafeEqual as K}from"node:crypto";import{ulid as V}from"ulid";import{isMcpContentProtected as P}from"../../../plugins/mcp/auth/auth-handlers.js";import{SUPPORTED_MCP_SCOPES as y}from"../../../plugins/mcp/constants.js";import{isRedoclySso as Y,isOidcProviderConfig as v}from"../../auth.js";import{AUTH_URL as Z,JWT_SECRET_KEY as m,MCP_ACCESS_TOKEN_TTL_SEC as $,MCP_REFRESH_SESSION_LIFETIME_SEC as W}from"../../../constants/common.js";import{ServerRoutes as T}from"../../../../constants/api.js";import{AuthCookieNames as R}from"../../../../constants/common.js";import{withPathPrefix as I}from"@redocly/theme/core/utils";import{telemetry as M}from"../../../telemetry/index.js";import{envConfig as U}from"../../../config/env-config.js";import{createMcpAuthorizationCode as x,verifyMcpAuthorizationCode as Q,createMcpRefreshToken as j,verifyMcpRefreshToken as X,createMcpSessionResource as w,oidcJwksCache as z,oidcRefreshTokenGrant as ee,getOidcMetadata as re,discoverJwks as te}from"../../auth.js";import*as S from"../../jwt/jwt.js";import{AlgorithmTypes as D,JwtAlgorithmNotImplemented as ne,JwtTokenExpired as oe,JwtTokenInvalid as ie,JwtTokenNotBefore as se,JwtTokenSignatureMismatched as ce}from"../../jwt/types.js";import{getRequestOrigin as q}from"../../utils/get-request-origin.js";import{encryptClaimValue as L}from"../../../utils/crypto/encrypt-claim-value.js";import{decryptAesGcm as de}from"../../../utils/crypto/decrypt-aes-gcm.js";import{encryptAesGcm as F}from"../../../utils/crypto/encrypt-aes-gcm.js";import{fetchClientMetadataDocument as ae,isClientMetadataDocumentUrl as N,isRedirectUriRegistered as le}from"./mcp-client-metadata.js";const s=(r,e,t=200,o)=>r.json(e,t,{"Content-Type":"application/json",...o??{}}),H=new Set(["S256"]),b=["authorization_code","refresh_token"],pe="https://claude.ai/oauth/claude-code-client-metadata";function _e(r,e,t){if(!H.has(e||""))return!1;const o=J("sha256").update(t).digest("base64url"),c=Buffer.from(o),i=Buffer.from(r);return c.length!==i.length?!1:K(c,i)}async function ue(r){const e=Math.floor(Date.now()/1e3);return S.sign({type:"mcp_context",...r,iat:e,exp:e+600},m,D.HS256)}async function fe(r){await S.verify(r,m,D.HS256);const{payload:e}=S.decode(r);if(e.type!=="mcp_context")throw new Error("Invalid context token type");return e}function He(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);if(e.req.method!=="GET")return s(e,{error:"Method not allowed"},405,{Allow:"GET"});const t=q(e);return s(e,{resource:`${t}${I("/mcp")}`,authorization_servers:[t],bearer_methods_supported:["header"],resource_documentation:`${t}${T.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:[...y],bearer_token_types_supported:["Bearer"]},200,{"Access-Control-Allow-Origin":"*"})}}function be(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);const t=q(e);return s(e,{issuer:t,authorization_endpoint:`${t}${I(T.MCP_AUTHORIZATION)}`,token_endpoint:`${t}${I(T.MCP_TOKEN_PORTAL)}`,scopes_supported:[...y],registration_endpoint:`${t}${I(T.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,response_types_supported:["code"],grant_types_supported:[...b],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none"],client_id_metadata_document_supported:!0},200,{"Access-Control-Allow-Origin":"*"})}}function $e(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{return s(e,{client_id:U.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:[...b],response_types:["code"],scope:y.join(" "),subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201,{"Access-Control-Allow-Origin":"*"})}catch(t){return s(e,{error:"invalid_request",error_description:t?.message||"Unable to register client"},500,{"Access-Control-Allow-Origin":"*"})}}}function G(r){const e=r||{},t=Object.keys(e),o=t.find(i=>v(e[i])&&Y(e[i])),c=t.find(i=>v(e[i]));return o||c||t[0]}function je(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);const t=new URL(e.req.url),{searchParams:o}=t,c=o.get("redirect_uri"),i=o.get("client_id"),a=o.get("code_challenge"),n=o.get("code_challenge_method"),l=V();if(a&&!H.has(n||""))return s(e,{error:"invalid_request",error_description:`Unsupported code_challenge_method. Supported: ${[...H].join(", ")}`},400);if(N(i)&&!a)return s(e,{error:"invalid_request",error_description:"code_challenge is required for client_id_metadata_document clients"},400);if(N(i)&&c)try{const d=await ae(i),p=i===pe;if(!le(c,d.redirect_uris,{ignorePort:p}))return s(e,{error:"invalid_request",error_description:"redirect_uri is not registered for this client"},400)}catch(d){const p=d instanceof Error?d.message:String(d);return s(e,{error:"invalid_client",error_description:`Unable to resolve client metadata document: ${p}`},400)}M.sendMcpAuthorizationStartedMessage([{...w(l),redirect_uri:c||null}]);const f=q(e),_={isMcpFlow:!0,originalRedirectUri:c,mcpClientId:i,mcpState:o.get("state"),mcpSessionId:l,mcpCodeChallenge:a,mcpCodeChallengeMethod:a?n:null,timestamp:Date.now()};try{const d=await ue(_),p=new URL(I(T.IDP_LOGIN),f);p.searchParams.set("redirectTo",`${T.MCP_CALLBACK}/${d}`);const k=G(r.getConfig().ssoDirect);return k?(p.searchParams.set("idpId",k),e.redirect(p.toString())):s(e,{error:"not_found"},404)}catch(d){const p=d instanceof Error?d.message:String(d),k=d instanceof Error?d.stack:String(d);M.sendMcpAuthorizationFailedMessage([{...w(l),error:p,error_details:k}]);const C=new URL(I(`${Z}/oauth2/auth`));return C.search=o.toString(),e.redirect(C.toString())}}}async function B(r){const e=Math.floor(Date.now()/1e3),t=await S.sign({...r.claims,...r.idpId?{idpId:r.idpId}:{},...r.idpAccessTokenEnc?{idp_access_token:r.idpAccessTokenEnc}:{},...r.ttlSec?{iat:e,exp:e+r.ttlSec}:{}},m,D.HS256,r.kid),o=r.ttlSec??(typeof r.claims.exp=="number"?Math.max(r.claims.exp-e,0):$);return{accessToken:t,expiresIn:o}}async function he(r,e,t){const o=g=>s(r,{error:"invalid_grant",error_description:g},400),c=r.get("logger"),i=t.get("refresh_token"),a=t.get("client_id")||void 0;if(!i)return s(r,{error:"invalid_request",error_description:"refresh_token is required"},400);let n;try{n=await X(i)}catch(g){return c?.warn("MCP refresh token rejected: %s",g instanceof Error?g.message:String(g)),o("Invalid refresh token")}if(a&&a!==n.client_id)return o("Client mismatch");const l=n.idp_id?e.getConfig().ssoDirect?.[n.idp_id]:void 0;let f,_,d=n.idp_access_token_enc,p=n.idp_refresh_token_enc;if(n.idp_refresh_token_enc){let g;try{g=de(n.idp_refresh_token_enc,m)}catch{return o("Invalid refresh token")}if(!n.idp_id||!v(l))return o("Unknown identity provider");let u;try{const h=await re(n.idp_id,l);if(!h?.token_endpoint)return o("Identity provider has no token endpoint");u=await ee(h.token_endpoint,g,l)}catch(h){return c?.warn("MCP refresh failed to reach the IdP token endpoint: %s",h instanceof Error?h.message:String(h)),s(r,{error:"server_error",error_description:"Failed to refresh session"},500)}if(u.error||!(u.id_token||u.access_token))return c?.warn("MCP refresh rejected by IdP: %s",u.error||"empty token response"),o("Refresh rejected by identity provider");if(u.refresh_token&&(p=F(u.refresh_token,m)),u.access_token&&(d=L(u.access_token,m)),u.id_token)try{const h=S.decode(u.id_token);f=h.payload,_=h.header.kid}catch{return o("Invalid token response from identity provider")}}const k=v(l)&&l.tokenExpirationTime||$,C=f??n.claims,E=await B({claims:C,kid:_,idpId:n.idp_id,idpAccessTokenEnc:d,ttlSec:f?void 0:k}),O=await j({clientId:n.client_id,idpId:n.idp_id,claims:C,idpAccessTokenEnc:d,idpRefreshTokenEnc:p,sessionExp:n.session_exp});return s(r,{access_token:E.accessToken,token_type:"Bearer",expires_in:E.expiresIn,refresh_token:O,scope:y.join(" ")},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}function ze(r){return async e=>{if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{const t=await e.req.formData(),o=t.get("grant_type"),c=t.get("code"),i=t.get("redirect_uri")||void 0,a=t.get("code_verifier")||void 0;if(!b.includes(o))return s(e,{error:"invalid_request",error_description:"Invalid grant type"},400);if(o==="refresh_token")return await he(e,r,t);if(!c)return s(e,{error:"invalid_request",error_description:"Missing authorization code"},400);try{const n=await Q(c);if(i&&i!==n.redirect_uri)return s(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(n.code_challenge){if(!a)return s(e,{error:"invalid_grant",error_description:"code_verifier required"},400);if(!_e(n.code_challenge,n.code_challenge_method,a))return s(e,{error:"invalid_grant",error_description:"code_verifier mismatch"},400)}if(U.OAUTH_CLIENT_ID&&n.client_id&&!N(n.client_id)&&n.client_id!==U.OAUTH_CLIENT_ID)return s(e,{error:"invalid_client",error_description:"Client mismatch"},400);const l=n.id_token;if(typeof l!="string"||l.length===0)return s(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400);const f=n.idp_access_token_enc??(n.idp_access_token?L(n.idp_access_token,m):void 0),_=S.decode(l),{accessToken:d,expiresIn:p}=await B({claims:_.payload,kid:_.header.kid,idpId:n.idp_id,idpAccessTokenEnc:f}),C=Math.floor(Date.now()/1e3)+W,E=await j({clientId:n.client_id,idpId:n.idp_id,claims:_.payload,idpAccessTokenEnc:f,idpRefreshTokenEnc:n.idp_refresh_token_enc,sessionExp:C}),O={access_token:d,token_type:"Bearer",expires_in:p,refresh_token:E,scope:y.join(" "),id_token:l};return s(e,O,200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch(n){return e.get("logger")?.warn("MCP token exchange failed: %s",n instanceof Error?n.message:String(n)),s(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(t){const o=t instanceof Error?t.message:String(t);return s(e,{error:"server_error",error_description:"Failed to process token request",error_details:o},500)}}}async function me(r,e){try{const{payload:t,header:o}=S.decode(r);if(typeof t.idpId=="string"&&t.idpId)return t.idpId;if(o.kid){z.jwks[o.kid]==null&&await te(e||{});const c=z.jwks[o.kid];if(c?.idpId)return c.idpId}}catch{}return G(e)}function Fe(r){return async e=>{const t=new URL(e.req.url);let o=t.searchParams.get("context");if(!o&&t.pathname.startsWith(I(`${T.MCP_CALLBACK}/`))){const i=t.pathname.split("/");o=i[i.length-1]}if(!o)return e.text("Missing context parameter",400);let c=null;try{const i=await fe(o);if(c=i.mcpSessionId||null,!i.isMcpFlow||!i.originalRedirectUri)throw new Error("Invalid MCP context");const a=A(e,R.IDP_ID_TOKEN)||A(e,R.AUTHORIZATION),n=A(e,R.IDP_ACCESS_TOKEN),l=A(e,R.IDP_REFRESH_TOKEN);if(!a)return M.sendMcpAuthorizationFailedMessage([{...w(c),error:"Authentication required",error_details:null}]),e.text("Authentication required",401);const f=await x({idToken:a,idpId:await me(a,r.getConfig().ssoDirect),idpAccessTokenEnc:n?L(n,m):void 0,idpRefreshTokenEnc:l?F(l,m):void 0,clientId:i.mcpClientId||"",redirectUri:i.originalRedirectUri,codeChallenge:i.mcpCodeChallenge||void 0,codeChallengeMethod:i.mcpCodeChallengeMethod||void 0,ttlSec:600}),_=new URL(i.originalRedirectUri);return _.searchParams.set("code",f),i.mcpState&&_.searchParams.set("state",i.mcpState),M.sendMcpAuthorizationCompletedMessage([{...w(c),redirect_uri:i.originalRedirectUri||null}]),e.redirect(_.toString())}catch(i){const a=ge(i);return M.sendMcpAuthorizationFailedMessage([{...w(c),...a}]),e.text(`Invalid MCP callback: ${a.error}`,400)}}}function ge(r){return r instanceof Error&&[ne,oe,ie,se,ce].some(e=>r instanceof e)?{error:r.name,error_details:null}:r instanceof Error?{error:r.message,error_details:r.stack??null}:{error:String(r),error_details:null}}export{b as SUPPORTED_MCP_GRANT_TYPES,ue as createMcpContextToken,je as mcpAuthorizationHandler,Fe as mcpCallbackHandler,$e as mcpDynamicClientRegistrationHandler,be as mcpOAuthAuthorizationServerHandler,He as mcpOAuthProtectedResourceHandler,ze as mcpTokenPortalHandler,G as resolveMcpIdpId,fe as verifyAndParseMcpContextToken,_e as verifyPkce};
|
|
1
|
+
import{getCookie as A}from"hono/cookie";import{createHash as J,timingSafeEqual as K}from"node:crypto";import{ulid as V}from"ulid";import{isRedoclySso as Y,isOidcProviderConfig as P,createMcpAuthorizationCode as Z,verifyMcpAuthorizationCode as W,createMcpRefreshToken as $,verifyMcpRefreshToken as x,createMcpSessionResource as y,oidcJwksCache as j,oidcRefreshTokenGrant as Q,getOidcMetadata as X,discoverJwks as ee}from"../../auth.js";import{isMcpContentProtected as v}from"../../../plugins/mcp/auth/auth-handlers.js";import{SUPPORTED_MCP_SCOPES as M}from"../../../plugins/mcp/constants.js";import{AUTH_URL as re,JWT_SECRET_KEY as m,MCP_ACCESS_TOKEN_TTL_SEC as z,MCP_REFRESH_SESSION_LIFETIME_SEC as te}from"../../../constants/common.js";import{ServerRoutes as T}from"../../../../constants/api.js";import{AuthCookieNames as R}from"../../../../constants/common.js";import{withPathPrefix as I}from"@redocly/theme/core/utils";import{telemetry as w}from"../../../telemetry/index.js";import{envConfig as U}from"../../../config/env-config.js";import*as S from"../../jwt/jwt.js";import{AlgorithmTypes as D,JwtAlgorithmNotImplemented as ne,JwtTokenExpired as oe,JwtTokenInvalid as ie,JwtTokenNotBefore as se,JwtTokenSignatureMismatched as ce}from"../../jwt/types.js";import{getRequestOrigin as q}from"../../utils/get-request-origin.js";import{encryptClaimValue as L}from"../../../utils/crypto/encrypt-claim-value.js";import{decryptAesGcm as de}from"../../../utils/crypto/decrypt-aes-gcm.js";import{encryptAesGcm as F}from"../../../utils/crypto/encrypt-aes-gcm.js";import{fetchClientMetadataDocument as ae,isClientMetadataDocumentUrl as N,isRedirectUriRegistered as le}from"./mcp-client-metadata.js";const s=(r,e,t=200,o)=>r.json(e,t,{"Content-Type":"application/json",...o??{}}),H=new Set(["S256"]),b=["authorization_code","refresh_token"],pe="https://claude.ai/oauth/claude-code-client-metadata";function _e(r,e,t){if(!H.has(e||""))return!1;const o=J("sha256").update(t).digest("base64url"),c=Buffer.from(o),i=Buffer.from(r);return c.length!==i.length?!1:K(c,i)}async function ue(r){const e=Math.floor(Date.now()/1e3);return S.sign({type:"mcp_context",...r,iat:e,exp:e+600},m,D.HS256)}async function fe(r){await S.verify(r,m,D.HS256);const{payload:e}=S.decode(r);if(e.type!=="mcp_context")throw new Error("Invalid context token type");return e}function Ne(r){return async e=>{if(!v(r))return s(e,{error:"not_found"},404);if(e.req.method!=="GET")return s(e,{error:"Method not allowed"},405,{Allow:"GET"});const t=q(e);return s(e,{resource:`${t}${I("/mcp")}`,authorization_servers:[t],bearer_methods_supported:["header"],resource_documentation:`${t}${T.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:[...M],bearer_token_types_supported:["Bearer"]},200,{"Access-Control-Allow-Origin":"*"})}}function He(r){return async e=>{if(!v(r))return s(e,{error:"not_found"},404);const t=q(e);return s(e,{issuer:t,authorization_endpoint:`${t}${I(T.MCP_AUTHORIZATION)}`,token_endpoint:`${t}${I(T.MCP_TOKEN_PORTAL)}`,scopes_supported:[...M],registration_endpoint:`${t}${I(T.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,response_types_supported:["code"],grant_types_supported:[...b],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"],token_endpoint_auth_methods_supported:["none"],client_id_metadata_document_supported:!0},200,{"Access-Control-Allow-Origin":"*"})}}function be(r){return async e=>{if(!v(r))return s(e,{error:"not_found"},404);if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{return s(e,{client_id:U.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:[...b],response_types:["code"],scope:M.join(" "),subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201,{"Access-Control-Allow-Origin":"*"})}catch(t){return s(e,{error:"invalid_request",error_description:t?.message||"Unable to register client"},500,{"Access-Control-Allow-Origin":"*"})}}}function G(r){const e=r||{},t=Object.keys(e),o=t.find(i=>P(e[i])&&Y(e[i])),c=t.find(i=>P(e[i]));return o||c||t[0]}function $e(r){return async e=>{if(!v(r))return s(e,{error:"not_found"},404);const t=new URL(e.req.url),{searchParams:o}=t,c=o.get("redirect_uri"),i=o.get("client_id"),a=o.get("code_challenge"),n=o.get("code_challenge_method"),l=V();if(a&&!H.has(n||""))return s(e,{error:"invalid_request",error_description:`Unsupported code_challenge_method. Supported: ${[...H].join(", ")}`},400);if(N(i)&&!a)return s(e,{error:"invalid_request",error_description:"code_challenge is required for client_id_metadata_document clients"},400);if(N(i)&&c)try{const d=await ae(i),p=i===pe;if(!le(c,d.redirect_uris,{ignorePort:p}))return s(e,{error:"invalid_request",error_description:"redirect_uri is not registered for this client"},400)}catch(d){const p=d instanceof Error?d.message:String(d);return s(e,{error:"invalid_client",error_description:`Unable to resolve client metadata document: ${p}`},400)}w.sendMcpAuthorizationStartedMessage([{...y(l),redirect_uri:c||null}]);const f=q(e),_={isMcpFlow:!0,originalRedirectUri:c,mcpClientId:i,mcpState:o.get("state"),mcpSessionId:l,mcpCodeChallenge:a,mcpCodeChallengeMethod:a?n:null,timestamp:Date.now()};try{const d=await ue(_),p=new URL(I(T.IDP_LOGIN),f);p.searchParams.set("redirectTo",`${T.MCP_CALLBACK}/${d}`);const k=G(r.getConfig().ssoDirect);return k?(p.searchParams.set("idpId",k),e.redirect(p.toString())):s(e,{error:"not_found"},404)}catch(d){const p=d instanceof Error?d.message:String(d),k=d instanceof Error?d.stack:String(d);w.sendMcpAuthorizationFailedMessage([{...y(l),error:p,error_details:k}]);const C=new URL(I(`${re}/oauth2/auth`));return C.search=o.toString(),e.redirect(C.toString())}}}async function B(r){const e=Math.floor(Date.now()/1e3),t=await S.sign({...r.claims,...r.idpId?{idpId:r.idpId}:{},...r.idpAccessTokenEnc?{idp_access_token:r.idpAccessTokenEnc}:{},...r.ttlSec?{iat:e,exp:e+r.ttlSec}:{}},m,D.HS256,r.kid),o=r.ttlSec??(typeof r.claims.exp=="number"?Math.max(r.claims.exp-e,0):z);return{accessToken:t,expiresIn:o}}async function he(r,e,t){const o=g=>s(r,{error:"invalid_grant",error_description:g},400),c=r.get("logger"),i=t.get("refresh_token"),a=t.get("client_id")||void 0;if(!i)return s(r,{error:"invalid_request",error_description:"refresh_token is required"},400);let n;try{n=await x(i)}catch(g){return c?.warn("MCP refresh token rejected: %s",g instanceof Error?g.message:String(g)),o("Invalid refresh token")}if(a&&a!==n.client_id)return o("Client mismatch");const l=n.idp_id?e.getConfig().ssoDirect?.[n.idp_id]:void 0;let f,_,d=n.idp_access_token_enc,p=n.idp_refresh_token_enc;if(n.idp_refresh_token_enc){let g;try{g=de(n.idp_refresh_token_enc,m)}catch{return o("Invalid refresh token")}if(!n.idp_id||!P(l))return o("Unknown identity provider");let u;try{const h=await X(n.idp_id,l);if(!h?.token_endpoint)return o("Identity provider has no token endpoint");u=await Q(h.token_endpoint,g,l)}catch(h){return c?.warn("MCP refresh failed to reach the IdP token endpoint: %s",h instanceof Error?h.message:String(h)),s(r,{error:"server_error",error_description:"Failed to refresh session"},500)}if(u.error||!(u.id_token||u.access_token))return c?.warn("MCP refresh rejected by IdP: %s",u.error||"empty token response"),o("Refresh rejected by identity provider");if(u.refresh_token&&(p=F(u.refresh_token,m)),u.access_token&&(d=L(u.access_token,m)),u.id_token)try{const h=S.decode(u.id_token);f=h.payload,_=h.header.kid}catch{return o("Invalid token response from identity provider")}}const k=P(l)&&l.tokenExpirationTime||z,C=f??n.claims,E=await B({claims:C,kid:_,idpId:n.idp_id,idpAccessTokenEnc:d,ttlSec:f?void 0:k}),O=await $({clientId:n.client_id,idpId:n.idp_id,claims:C,idpAccessTokenEnc:d,idpRefreshTokenEnc:p,sessionExp:n.session_exp});return s(r,{access_token:E.accessToken,token_type:"Bearer",expires_in:E.expiresIn,refresh_token:O,scope:M.join(" ")},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}function je(r){return async e=>{if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{const t=await e.req.formData(),o=t.get("grant_type"),c=t.get("code"),i=t.get("redirect_uri")||void 0,a=t.get("code_verifier")||void 0;if(!b.includes(o))return s(e,{error:"invalid_request",error_description:"Invalid grant type"},400);if(o==="refresh_token")return await he(e,r,t);if(!c)return s(e,{error:"invalid_request",error_description:"Missing authorization code"},400);try{const n=await W(c);if(i&&i!==n.redirect_uri)return s(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(n.code_challenge){if(!a)return s(e,{error:"invalid_grant",error_description:"code_verifier required"},400);if(!_e(n.code_challenge,n.code_challenge_method,a))return s(e,{error:"invalid_grant",error_description:"code_verifier mismatch"},400)}if(U.OAUTH_CLIENT_ID&&n.client_id&&!N(n.client_id)&&n.client_id!==U.OAUTH_CLIENT_ID)return s(e,{error:"invalid_client",error_description:"Client mismatch"},400);const l=n.id_token;if(typeof l!="string"||l.length===0)return s(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400);const f=n.idp_access_token_enc??(n.idp_access_token?L(n.idp_access_token,m):void 0),_=S.decode(l),{accessToken:d,expiresIn:p}=await B({claims:_.payload,kid:_.header.kid,idpId:n.idp_id,idpAccessTokenEnc:f}),C=Math.floor(Date.now()/1e3)+te,E=await $({clientId:n.client_id,idpId:n.idp_id,claims:_.payload,idpAccessTokenEnc:f,idpRefreshTokenEnc:n.idp_refresh_token_enc,sessionExp:C}),O={access_token:d,token_type:"Bearer",expires_in:p,refresh_token:E,scope:M.join(" "),id_token:l};return s(e,O,200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch(n){return e.get("logger")?.warn("MCP token exchange failed: %s",n instanceof Error?n.message:String(n)),s(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(t){const o=t instanceof Error?t.message:String(t);return s(e,{error:"server_error",error_description:"Failed to process token request",error_details:o},500)}}}async function me(r,e){try{const{payload:t,header:o}=S.decode(r);if(typeof t.idpId=="string"&&t.idpId)return t.idpId;if(o.kid){j.jwks[o.kid]==null&&await ee(e||{});const c=j.jwks[o.kid];if(c?.idpId)return c.idpId}}catch{}return G(e)}function ze(r){return async e=>{const t=new URL(e.req.url);let o=t.searchParams.get("context");if(!o&&t.pathname.startsWith(I(`${T.MCP_CALLBACK}/`))){const i=t.pathname.split("/");o=i[i.length-1]}if(!o)return e.text("Missing context parameter",400);let c=null;try{const i=await fe(o);if(c=i.mcpSessionId||null,!i.isMcpFlow||!i.originalRedirectUri)throw new Error("Invalid MCP context");const a=A(e,R.IDP_ID_TOKEN)||A(e,R.AUTHORIZATION),n=A(e,R.IDP_ACCESS_TOKEN),l=A(e,R.IDP_REFRESH_TOKEN);if(!a)return w.sendMcpAuthorizationFailedMessage([{...y(c),error:"Authentication required",error_details:null}]),e.text("Authentication required",401);const f=await Z({idToken:a,idpId:await me(a,r.getConfig().ssoDirect),idpAccessTokenEnc:n?L(n,m):void 0,idpRefreshTokenEnc:l?F(l,m):void 0,clientId:i.mcpClientId||"",redirectUri:i.originalRedirectUri,codeChallenge:i.mcpCodeChallenge||void 0,codeChallengeMethod:i.mcpCodeChallengeMethod||void 0,ttlSec:600}),_=new URL(i.originalRedirectUri);return _.searchParams.set("code",f),i.mcpState&&_.searchParams.set("state",i.mcpState),w.sendMcpAuthorizationCompletedMessage([{...y(c),redirect_uri:i.originalRedirectUri||null}]),e.redirect(_.toString())}catch(i){const a=ge(i);return w.sendMcpAuthorizationFailedMessage([{...y(c),...a}]),e.text(`Invalid MCP callback: ${a.error}`,400)}}}function ge(r){return r instanceof Error&&[ne,oe,ie,se,ce].some(e=>r instanceof e)?{error:r.name,error_details:null}:r instanceof Error?{error:r.message,error_details:r.stack??null}:{error:String(r),error_details:null}}export{b as SUPPORTED_MCP_GRANT_TYPES,ue as createMcpContextToken,$e as mcpAuthorizationHandler,ze as mcpCallbackHandler,be as mcpDynamicClientRegistrationHandler,He as mcpOAuthAuthorizationServerHandler,Ne as mcpOAuthProtectedResourceHandler,je as mcpTokenPortalHandler,G as resolveMcpIdpId,fe as verifyAndParseMcpContextToken,_e as verifyPkce};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AsyncApiRealmAPI as N}from"@redocly/realm-asyncapi-sdk";import{envConfig as o}from"../../../config/env-config.js";import{getClientIp as
|
|
1
|
+
import{AsyncApiRealmAPI as N}from"@redocly/realm-asyncapi-sdk";import{getAttributesStringValue as _,mergeAttributes as R,toAttribute as h}from"./otlp.js";import{envConfig as o}from"../../../config/env-config.js";import{getClientIp as O}from"../../utils/get-client-ip.js";const C=o.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",v="cloudevents.event_session_id";class w extends N.OtelClient{initTracer(){}}let d=null;function E(){return d||(d=new w,d.init({collectorTraceUrl:void 0,serviceName:"realm-ui",serviceVersion:"1.0",isProd:o.isProductionEnv,version:"1.0",tracerName:"attribute-processor"})),d}async function k(e){const t=await e.req.json();return t.resourceSpans?.length&&(P(t,L(e)),await fetch(C,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),e.newResponse(null,200)}function P(e,t){for(const s of e.resourceSpans){const r=s.resource.attributes.find(u=>u.key==="session_id");if(!r)continue;const i=_(r);if(!i)continue;const l=U(t.userId,i),p=new Date,g={organizationId:o.ORGANIZATION_ID||"",organizationSlug:o.ORGANIZATION_SLUG||"",projectId:o.PROJECT_ID||"",projectSlug:o.PROJECT_SLUG||"",env:o.REDOCLY_ENV||"",source:"urn:redocly:realm:ui",actor:{id:l.id,object:l.object,uri:l.uri},clientIp:t.clientIp,userAgent:t.userAgent},c=(u,n)=>{const a=u.attributes.find(f=>f.key===n);return a?_(a):""};for(const u of s.scopeSpans)for(const n of u.spans){if(!n.name.startsWith("event.")||n.name==="event.undefined")continue;const a=c(n,"cloudevents.event_spec_version"),f=c(n,"cloudevents.event_object"),b=c(n,"cloudevents.event_data_content_type"),S=c(n,"cloudevents.event_origin"),m=c(n,"cloudevents.event_time"),I=m?new Date(m):p,A=Number.isNaN(I.getTime())?p:I,T={...g,id:c(n,"cloudevents.event_id"),specversion:a,type:n.name.slice(6),object:f,datacontenttype:b,time:A,origin:S},y=E().processAttributes(T,A);R(n,y,{overwrite:!0}),j(n,t.sessionId)}}}function j(e,t){const s=e.attributes.findIndex(i=>i.key===v),r=h(v,t);r?s===-1?e.attributes.push(r):e.attributes[s]=r:s!==-1&&e.attributes.splice(s,1)}function L(e){const t=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,s=e.get("auth")?.claims?.sessionId,r=O(e.req.raw)||e.req.raw.context?.remoteAddr?.hostname,i=e.req.raw.headers.get("user-agent");return{userId:t,sessionId:s||void 0,clientIp:r??void 0,userAgent:i??void 0}}function U(e,t){if(e)return{id:e,object:"user",uri:`${o.MAIN_API_URL}/users/${e}`};const s=t.replace("ses_","ann_");return{id:s,object:"anonymous",uri:`${o.MAIN_API_URL}/anonymous/${s}`}}export{k as otelTracesHandler,U as toActor};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const a=[{oldPattern:/\/tag\/([
|
|
1
|
+
const a=[{oldPattern:/\/tag\/([^/]+)(?:\/operation\/([^/]+))?/,newPath(t){return t.replace(this.oldPattern,(e,r,n)=>{const o=n?`/${n}`:"";return`/${r}${o}`}).replace(/\/{2,}/g,"/")}}];function c(t){for(const e of a)if(t.match(e.oldPattern))return e.newPath(t).toLowerCase();return null}export{c as getRedirectRoute};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { AuthProviderType, REDOCLY_TEAMS_RBAC, REDOCLY_ROUTE_RBAC, RbacScopeItems } from '@redocly/config';
|
|
2
|
-
import type { UiAccessibleConfig } from '@redocly/config';
|
|
1
|
+
import type { AuthProviderType, REDOCLY_TEAMS_RBAC, REDOCLY_ROUTE_RBAC, RbacScopeItems, UiAccessibleConfig } from '@redocly/config';
|
|
3
2
|
export type GlobalData = UiAccessibleConfig & {
|
|
4
3
|
authIdps?: Array<{
|
|
5
4
|
idpId: string;
|
package/dist/utils/slugger.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{UniqueKeyResolver as B}from"./conflict-resolvers.js";const e=/[\0-\x1F
|
|
1
|
+
import{UniqueKeyResolver as B}from"./conflict-resolvers.js";const e=/[\0-\x1F!-,:-@[-^`{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g;class r{#u=new B;slug(C,E={}){let F=s(C,E);return F=this.#u.resolve(F),F}reset(){this.#u.reset()}}const l=new r;function s(D,C={}){if(typeof D!="string")return"";const{maintainCase:E=!1,replaceDots:F=!1,replaceSlashes:A=!1}=C;E||(D=D.toLowerCase());let u=D.replace(e,"").replace(/ /g,"-");return F&&(u=u.replace(/\./g,"")),A&&(u=u.replace(/\//g,"")),u===""?"_":u}export{r as GithubSlugger,s as slug,l as slugger};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function d(e){const c=decodeURI(e);return encodeURI(c.replace(/^[
|
|
1
|
+
function d(e){const c=decodeURI(e);return encodeURI(c.replace(/^[/\s\u0000]+/g,"/"))}export{d as sanitizeRedirectPathname};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/realm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.138.0-next.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"@opentelemetry/sdk-trace-web": "2.8.0",
|
|
34
34
|
"@opentelemetry/semantic-conventions": "1.40.0",
|
|
35
35
|
"@redocly/ajv": "8.18.0",
|
|
36
|
-
"@redocly/api-docs": "0.
|
|
36
|
+
"@redocly/api-docs": "0.3.0-next.0",
|
|
37
37
|
"@redocly/config": "0.56.0",
|
|
38
38
|
"@redocly/openapi-core": "2.53.0",
|
|
39
39
|
"@redocly/portal-legacy-ui": "0.19.0",
|
|
40
40
|
"@redocly/portal-plugin-mock-server": "0.22.0",
|
|
41
|
-
"@redocly/realm-asyncapi-sdk": "0.
|
|
42
|
-
"@redocly/theme": "0.
|
|
41
|
+
"@redocly/realm-asyncapi-sdk": "0.16.0-next.0",
|
|
42
|
+
"@redocly/theme": "0.70.0-next.0",
|
|
43
43
|
"@shikijs/transformers": "3.21.0",
|
|
44
44
|
"@tanstack/react-query": "5.62.3",
|
|
45
45
|
"@tanstack/react-table": "8.21.3",
|