@redocly/realm 0.137.0-next.9 → 0.137.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.
Files changed (105) hide show
  1. package/CHANGELOG.md +213 -1
  2. package/dist/cli/build/index.js +1 -1
  3. package/dist/client/app/Sidebar/useActions.js +1 -1
  4. package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
  5. package/dist/client/app/hooks/catalog/useCatalogClassic.js +1 -1
  6. package/dist/client/app/hooks/catalog/useCatalogFilter.js +1 -1
  7. package/dist/client/app/search/useFacets.js +1 -1
  8. package/dist/client/app/seo/SeoTags.js +1 -1
  9. package/dist/client/app/utils/loadAndNavigate.js +1 -1
  10. package/dist/server/config/env-config.d.ts +2 -0
  11. package/dist/server/config/env-schema.d.ts +5 -0
  12. package/dist/server/config/env-schemas/feature-flags.d.ts +4 -0
  13. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  14. package/dist/server/constants/plugins/search.js +1 -1
  15. package/dist/server/esbuild/esbuild-logger.d.ts +2 -2
  16. package/dist/server/esbuild/esbuild-logger.js +3 -3
  17. package/dist/server/plugins/api-docs/options.js +1 -1
  18. package/dist/server/plugins/api-docs/search/create-indexer.d.ts +5 -0
  19. package/dist/server/plugins/api-docs/search/create-indexer.js +1 -0
  20. package/dist/server/plugins/api-docs/search/get-ai-search-documents.d.ts +1 -1
  21. package/dist/server/plugins/api-docs/search/get-ai-search-documents.js +41 -41
  22. package/dist/server/plugins/api-docs/search/search-resolver.js +1 -1
  23. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -1
  24. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +1 -1
  25. package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.js +1 -1
  26. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
  27. package/dist/server/plugins/config-parser/loaders/versions-config-loader.js +1 -1
  28. package/dist/server/plugins/dev-onboarding/template/components/EditAppDescriptionDialog.js +1 -1
  29. package/dist/server/plugins/dev-onboarding/template/components/EditAppDialog.js +1 -1
  30. package/dist/server/plugins/dev-onboarding/template/components/EditCallbackUrlDialog.js +1 -1
  31. package/dist/server/plugins/markdown/is-partial.js +1 -1
  32. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +5 -4
  33. package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +5 -2
  34. package/dist/server/plugins/mcp/codemode/capabilities/utils.js +4 -4
  35. package/dist/server/plugins/mcp/codemode/code-execution-audit.js +1 -1
  36. package/dist/server/plugins/mcp/codemode/prompts.d.ts +1 -1
  37. package/dist/server/plugins/mcp/codemode/prompts.js +7 -6
  38. package/dist/server/plugins/mcp/codemode/sandbox/create-sandbox-setup.d.ts +2 -2
  39. package/dist/server/plugins/mcp/codemode/sandbox/create-sandbox-setup.js +1 -11
  40. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/console.d.ts +2 -0
  41. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/console.js +7 -0
  42. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/index.d.ts +1 -0
  43. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/index.js +2 -2
  44. package/dist/server/plugins/mcp/codemode/sandbox/tool-input-validator.d.ts +5 -0
  45. package/dist/server/plugins/mcp/codemode/sandbox/tool-input-validator.js +1 -0
  46. package/dist/server/plugins/mcp/codemode/sandbox/unknown-tool-hint.d.ts +8 -0
  47. package/dist/server/plugins/mcp/codemode/sandbox/unknown-tool-hint.js +2 -0
  48. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +3 -1
  49. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  50. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.d.ts +2 -2
  51. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  52. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  53. package/dist/server/plugins/mcp/docs-mcp/tools/core/create-anonymous-session.js +1 -1
  54. package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +2 -2
  55. package/dist/server/plugins/mcp/docs-mcp/tools/core/types.d.ts +2 -2
  56. package/dist/server/plugins/mcp/docs-mcp/tools/graphql/get-graphql-type.js +5 -5
  57. package/dist/server/plugins/mcp/docs-mcp/tools/graphql/types.d.ts +2 -1
  58. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
  59. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.d.ts +4 -2
  60. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.js +1 -1
  61. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/types.d.ts +6 -2
  62. package/dist/server/plugins/mcp/docs-mcp/utils/api-titles.d.ts +6 -0
  63. package/dist/server/plugins/mcp/docs-mcp/utils/api-titles.js +1 -0
  64. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +11 -0
  65. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -5
  66. package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.js +1 -1
  67. package/dist/server/plugins/mcp/gateway-mcp/fetch/url-placeholders.d.ts +5 -0
  68. package/dist/server/plugins/mcp/gateway-mcp/fetch/url-placeholders.js +1 -0
  69. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  70. package/dist/server/plugins/mcp/servers/mcp-server.js +3 -3
  71. package/dist/server/plugins/mcp/types.d.ts +1 -0
  72. package/dist/server/plugins/mcp/utils/available-sandbox-tools.js +1 -1
  73. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  74. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +1 -1
  75. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  76. package/dist/server/plugins/search/engines/flexsearch/search-index.d.ts +8 -4
  77. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  78. package/dist/server/plugins/search/llmstxt/create-llms-txt-generator.js +1 -1
  79. package/dist/server/plugins/search/llmstxt/index.d.ts +3 -1
  80. package/dist/server/plugins/search/llmstxt/index.js +9 -9
  81. package/dist/server/sandbox/sandbox.js +2 -2
  82. package/dist/server/sandbox/types.d.ts +9 -0
  83. package/dist/server/sandbox/utils/execution-budget.js +1 -1
  84. package/dist/server/sandbox/utils/return-last-expression.d.ts +6 -0
  85. package/dist/server/sandbox/utils/return-last-expression.js +1 -0
  86. package/dist/server/sandbox/utils/returns-from-top-level.d.ts +1 -2
  87. package/dist/server/sandbox/utils/returns-from-top-level.js +1 -1
  88. package/dist/server/sandbox/utils/setup-host-functions.d.ts +1 -0
  89. package/dist/server/sandbox/utils/setup-host-functions.js +2 -2
  90. package/dist/server/ssr/render.js +1 -1
  91. package/dist/server/store.js +1 -1
  92. package/dist/server/types/plugins/search.d.ts +7 -2
  93. package/dist/server/utils/globs.d.ts +4 -0
  94. package/dist/server/utils/globs.js +1 -1
  95. package/dist/server/utils/search/highlight-text-for-search.js +1 -1
  96. package/dist/server/web-server/middleware/ensureSearchData.js +1 -1
  97. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  98. package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
  99. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  100. package/dist/{server/plugins/catalog-entities/utils/version-compare.d.ts → utils/version/compare-versions.d.ts} +1 -16
  101. package/dist/utils/version/compare-versions.js +1 -0
  102. package/package.json +11 -10
  103. package/dist/server/plugins/api-docs/search/search-indexer.d.ts +0 -9
  104. package/dist/server/plugins/api-docs/search/search-indexer.js +0 -1
  105. package/dist/server/plugins/catalog-entities/utils/version-compare.js +0 -1
@@ -1,13 +1,13 @@
1
- import d from"picomatch";import{dirname as T,resolve as x}from"node:path";import{access as $,readFile as E,constants as F}from"fs/promises";import{removeTrailingSlash as w}from"../../../../utils/url/remove-trailing-slash.js";import{logger as g}from"../../../tools/notifiers/logger.js";import{withPathPrefix as y}from"@redocly/theme/core/utils";import{envConfig as I}from"../../../config/env-config.js";import{getLlmsTxtMdPathBySlug as v}from"../../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";const a="llms.txt",u="Table of contents";async function D(t,e,n={title:a,description:void 0},o){if(!e)return{title:n.title||a,description:n.description,details:void 0,sections:[{title:u,description:void 0,llmstxts:t}]};const s=e.title||n.title||a,r=e.description||n.description,i=await M(e,o),c=e.sections?.map(l=>{const{title:f,description:h,excludeFiles:m,includeFiles:L}=l,P=p(t,{excludeFiles:m,includeFiles:L});return{title:f,description:h,llmstxts:P}});return{title:s,description:r,details:i,sections:c||[{title:u,description:void 0,llmstxts:p(t,{includeFiles:["**/*"],excludeFiles:[]})}]}}async function M(t,e){const n=await e.getConfig();if(t?.details?.path&&n.configPath)try{const o=e.fs.getFileInfo(n.configPath);if(!o)throw new Error(`Config file ${n.configPath} not found`);const s=x(e.fs.cwd,T(o.relativePath),t.details.path);return await $(s,F.R_OK),E(s,"utf-8")}catch{throw new Error(`${t.details.path} is not accessible`)}if(t?.details?.content)return t.details.content}function p(t,e){const{excludeFiles:n,includeFiles:o}=e,s=n?.map(i=>d(i)),r=o?.map(i=>d(i));return t.filter(i=>s?.some(l=>l(i.fsPath))?!1:r?.some(l=>l(i.fsPath)))}async function j(t,e,n={title:a,description:void 0},o){const s=await D(t,e,n,o),r=[`# ${s.title}
1
+ import d from"picomatch";import{dirname as T,resolve as $}from"node:path";import{access as x,readFile as E,constants as F}from"fs/promises";import{removeTrailingSlash as w}from"../../../../utils/url/remove-trailing-slash.js";import{logger as g}from"../../../tools/notifiers/logger.js";import{withPathPrefix as U}from"@redocly/theme/core/utils";import{envConfig as y}from"../../../config/env-config.js";import{getLlmsTxtMdPathBySlug as I}from"../../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";const a="llms.txt",u="Table of contents";async function v(e,i,n={title:a,description:void 0},r){if(!i)return{title:n.title||a,description:n.description,details:void 0,sections:[{title:u,description:void 0,llmstxts:e}]};const s=i.title||n.title||a,l=i.description||n.description,t=await D(i,r),o=i.sections?.map(c=>{const{title:f,description:h,excludeFiles:m,includeFiles:L}=c,P=p(e,{excludeFiles:m,includeFiles:L});return{title:f,description:h,llmstxts:P}});return{title:s,description:l,details:t,sections:o||[{title:u,description:void 0,llmstxts:p(e,{includeFiles:["**/*"],excludeFiles:[]})}]}}async function D(e,i){const n=await i.getConfig();if(e?.details?.path&&n.configPath)try{const r=i.fs.getFileInfo(n.configPath);if(!r)throw new Error(`Config file ${n.configPath} not found`);const s=$(i.fs.cwd,T(r.relativePath),e.details.path);return await x(s,F.R_OK),E(s,"utf-8")}catch{throw new Error(`${e.details.path} is not accessible`)}if(e?.details?.content)return e.details.content}function p(e,i){const{excludeFiles:n,includeFiles:r}=i,s=n?.map(t=>d(t)),l=r?.map(t=>d(t));return e.filter(t=>s?.some(c=>c(t.fsPath))?!1:l?.some(c=>c(t.fsPath)))}async function b(e,i,n={title:a,description:void 0,siteUrl:void 0},r){const s=await v(e,i,n,r),l=n.siteUrl,t=[`# ${s.title}
2
2
 
3
- `];return s.description&&r.push(`> ${s.description}
3
+ `];return s.description&&t.push(`> ${s.description}
4
4
 
5
- `),s.details&&r.push(`${s.details}
5
+ `),s.details&&t.push(`${s.details}
6
6
 
7
- `),s.sections.forEach(i=>{if(!i.llmstxts.length){g.warn(`llms.txt: No links found for section "${i.title}". Please check the includeFiles/excludeFiles patterns.`);return}r.push(`## ${i.title}
8
- `),i.description?r.push(`${i.description.replace(/\n+$/,"")}
7
+ `),s.sections.forEach(o=>{if(!o.llmstxts.length){g.warn(`llms.txt: No links found for section "${o.title}". Please check the includeFiles/excludeFiles patterns.`);return}t.push(`## ${o.title}
8
+ `),o.description?t.push(`${o.description.replace(/\n+$/,"")}
9
9
 
10
- `):r.push(`
11
- `),i.llmstxts.forEach(c=>{r.push(` - ${_({title:c.title,description:c.description,slug:v(c.slug)})}`)}),r.push(`
12
- `)}),r.join("")}function _({title:t,description:e,slug:n}){const o=e?.replace(/\s+/g," ").trim();return`[${t}](${w(I.REDOCLY_PUBLIC_URL||"")}${encodeURI(y(n))})${o?`: ${o}`:""}
13
- `}function K(t){if(t?.details?.path&&t?.details?.content)throw new Error('"details.path" and "details.content" are mutually exclusive. Please use only one of them.')}export{j as generateLLMsTxt,_ as llmsTxtLink,K as validateLLMsTxtConfig};
10
+ `):t.push(`
11
+ `),o.llmstxts.forEach(c=>{t.push(` - ${M({title:c.title,description:c.description,slug:I(c.slug),siteUrl:l})}`)}),t.push(`
12
+ `)}),t.join("")}function M({title:e,description:i,slug:n,siteUrl:r}){const l=`${w(r?.trim()||y.REDOCLY_PUBLIC_URL||"")}${encodeURI(U(n))}`,t=i?.replace(/\s+/g," ").trim();return`[${e}](${l})${t?`: ${t}`:""}
13
+ `}function j(e){if(e?.details?.path&&e?.details?.content)throw new Error('"details.path" and "details.content" are mutually exclusive. Please use only one of them.')}export{b as generateLLMsTxt,M as llmsTxtLink,j as validateLLMsTxtConfig};
@@ -1,3 +1,3 @@
1
- import p from"@jitl/quickjs-singlefile-mjs-release-sync";import{newQuickJSWASMModuleFromVariant as _,newVariant as E}from"quickjs-emscripten-core";import{createExecutionBudget as S}from"./utils/execution-budget.js";import{returnsFromTopLevel as A}from"./utils/returns-from-top-level.js";import{DEFAULT_MAX_LIFETIME_MS as y,DEFAULT_TIMEOUT_MS as b,INITIAL_TOTAL_MEMORY_BYTES as h,MAX_ALLOCATION_BYTES as L,MAX_RESULT_BYTES as g,MAX_STACK_SIZE_BYTES as w,MAX_TOTAL_MEMORY_BYTES as x,WASM_PAGE_BYTES as d}from"./constants/sandbox.js";let c;function I(){return c??=_(E(p,{wasmMemory:new WebAssembly.Memory({initial:h/d,maximum:x/d})}))}async function P(t,l={}){const{timeoutMs:m=b,maxLifetimeMs:f=y,setupContext:M}=l,e=(await I()).newContext();let n,i,r;try{e.runtime.setMemoryLimit(L),e.runtime.setMaxStackSize(w),n=S(e,m,f),i=M?.(e,n)??void 0,r=e.unwrapResult(e.evalCode(`(async () => {
1
+ import p from"@jitl/quickjs-singlefile-mjs-release-sync";import{newQuickJSWASMModuleFromVariant as _,newVariant as S}from"quickjs-emscripten-core";import{createExecutionBudget as A}from"./utils/execution-budget.js";import{returnsFromTopLevel as x}from"./utils/returns-from-top-level.js";import{DEFAULT_MAX_LIFETIME_MS as b,DEFAULT_TIMEOUT_MS as y,INITIAL_TOTAL_MEMORY_BYTES as g,MAX_ALLOCATION_BYTES as L,MAX_RESULT_BYTES as h,MAX_STACK_SIZE_BYTES as w,MAX_TOTAL_MEMORY_BYTES as I,WASM_PAGE_BYTES as f}from"./constants/sandbox.js";let M;function O(){return M??=_(S(p,{wasmMemory:new WebAssembly.Memory({initial:g/f,maximum:I/f})}))}async function X(t,s={}){const{timeoutMs:n=y,maxLifetimeMs:u=b,setupContext:E,authoredCode:T=t}=s,e=(await O()).newContext();let r,l,a;try{e.runtime.setMemoryLimit(L),e.runtime.setMaxStackSize(w),r=A(e,n,u),l=E?.(e,r)??void 0,a=e.unwrapResult(e.evalCode(`(async () => {
2
2
  ${t}
3
- })()`));const o=e.resolvePromise(r);e.runtime.executePendingJobs();const T=await Promise.race([o,n.aborted]),u=e.unwrapResult(T),s=e.dump(u);if(u.dispose(),s===void 0)return{error:A(e,t)?"The code returned undefined: the `return` ran but produced no value. Read fields off the declared return types \u2014 a field name that does not exist reads as undefined \u2014 and do not `return;` or `return undefined`.":"The code returned undefined because nothing was returned. Add a top-level `return`: a value computed inside a function or IIFE is discarded unless you return it, and a promise chain has to be returned to be awaited."};const a=JSON.stringify(s??null).length;return a>g?{error:`Result is too large (${a} bytes); return less data`}:{result:s}}catch(o){return{error:v(o)}}finally{n?.dispose(),r?.dispose();try{i?.()}catch{}try{e.dispose()}catch{c=void 0}}}function v(t){return t instanceof Error?t.message:String(t)}export{P as runInSandbox};
3
+ })()`,k));const i=e.resolvePromise(a);e.runtime.executePendingJobs();const d=await Promise.race([i,r.aborted]),o=e.unwrapResult(d),c=e.dump(o);if(o.dispose(),c===void 0)return{error:x(T)?"The code returned undefined: the `return` ran but produced no value. Read fields off the declared return types \u2014 a field name that does not exist reads as undefined \u2014 and do not `return;` or `return undefined`.":"The code returned undefined because nothing was returned. Add a top-level `return` of the value to send back."};const m=JSON.stringify(c??null).length;return m>h?{error:`Result is too large (${m} bytes); return less data`}:{result:c}}catch(i){const d=r?.expiredMessage();if(d!==void 0)return{error:d};const o=Y(i);return{error:R(i),...o?{errorPosition:o}:{}}}finally{r?.dispose(),a?.dispose();try{l?.()}catch{}try{e.dispose()}catch{M=void 0}}}function R(t){return t instanceof Error?t.message:String(t)}const k="sandbox-code.js",v=/sandbox-code\.js:(\d+):(\d+)/;function Y(t){const s=t.cause?.stack,n=typeof s=="string"?v.exec(s):null;if(!n)return;const u=Number(n[1])-1;return u>=1?{line:u,column:Number(n[2])}:void 0}export{X as runInSandbox};
@@ -1,7 +1,13 @@
1
1
  import type { QuickJSContext } from 'quickjs-emscripten-core';
2
+ /** 1-based position in the submitted code where the guest error was thrown. */
3
+ export type GuestPosition = {
4
+ line: number;
5
+ column: number;
6
+ };
2
7
  export type SandboxResult = {
3
8
  result?: unknown;
4
9
  error?: string;
10
+ errorPosition?: GuestPosition;
5
11
  };
6
12
  export type ExecutionBudget = {
7
13
  /**
@@ -13,6 +19,8 @@ export type ExecutionBudget = {
13
19
  hostCall<T>(work: () => Promise<T>): Promise<T>;
14
20
  /** Rejects when a wall-clock deadline fires */
15
21
  aborted: Promise<never>;
22
+ /** The message of the deadline that fired, or `undefined` while the run is still in budget */
23
+ expiredMessage(): string | undefined;
16
24
  dispose(): void;
17
25
  };
18
26
  export type SetupSandboxContext = (context: QuickJSContext, budget: ExecutionBudget) => void | (() => void);
@@ -20,6 +28,7 @@ export type RunInSandboxOptions = {
20
28
  timeoutMs?: number;
21
29
  maxLifetimeMs?: number;
22
30
  setupContext?: SetupSandboxContext;
31
+ authoredCode?: string;
23
32
  };
24
33
  export type SandboxHostFunction = (input: unknown) => Promise<unknown> | unknown;
25
34
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- function f(c,t,i){const d=Date.now()+i;let l=Date.now()+t,u=t,a=()=>{};const T=new Promise((e,o)=>{a=r=>o(new Error(r))});let n;const m=()=>{clearTimeout(n),n=setTimeout(()=>a(`Execution timed out after ${t}ms`),t)};c.runtime.setInterruptHandler(()=>{const e=Date.now();return e>l||e>d}),m();const w=setTimeout(()=>a(`Exceeded the maximum lifetime of ${i}ms`),i);let s=0;return{hostCall:e=>{u=l-Date.now(),s++,clearTimeout(n);const o=()=>{c.alive&&(l=Date.now()+u,--s===0&&m())},r=e();return r.then(o,o),r},aborted:T,dispose(){clearTimeout(n),clearTimeout(w)}}}export{f as createExecutionBudget};
1
+ function h(c,i,l){const u=`Execution timed out after ${i}ms`,m=`Exceeded the maximum lifetime of ${l}ms`,w=Date.now()+l;let s=Date.now()+i,d=i,e,a=()=>{};const p=new Promise((t,r)=>{a=n=>{e=n,r(new Error(n))}});let o;const f=()=>{clearTimeout(o),o=setTimeout(()=>a(u),i)};c.runtime.setInterruptHandler(()=>{const t=Date.now();return t>s?e=u:t>w&&(e=m),e!==void 0}),f();const D=setTimeout(()=>a(m),l);let T=0;return{hostCall:t=>{d=s-Date.now(),T++,clearTimeout(o);const r=()=>{c.alive&&(s=Date.now()+d,--T===0&&f())},n=t();return n.then(r,r),n},aborted:p,expiredMessage:()=>e,dispose(){clearTimeout(o),clearTimeout(D)}}}export{h as createExecutionBudget};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Prefixes the last top-level statement with `return ` when it is a bare expression, so sandbox
3
+ * code reads like a REPL. Code that ends in anything else stays byte-identical.
4
+ */
5
+ export declare function returnLastExpression(code: string): string;
6
+ //# sourceMappingURL=return-last-expression.d.ts.map
@@ -0,0 +1 @@
1
+ import{parse as e}from"acorn";function i(t){let r;try{r=e(t,{ecmaVersion:"latest",sourceType:"script",allowAwaitOutsideFunction:!0,allowReturnOutsideFunction:!0}).body.at(-1)}catch{return t}return r?.type!=="ExpressionStatement"||r.directive!==void 0?t:`${t.slice(0,r.start)}return ${t.slice(r.start)}`}export{i as returnLastExpression};
@@ -1,4 +1,3 @@
1
- import type { QuickJSContext } from 'quickjs-emscripten-core';
2
1
  /** Whether `code` returns from the guest wrapper itself rather than from a nested function. */
3
- export declare function returnsFromTopLevel(context: QuickJSContext, code: string): boolean;
2
+ export declare function returnsFromTopLevel(code: string): boolean;
4
3
  //# sourceMappingURL=returns-from-top-level.d.ts.map
@@ -1 +1 @@
1
- const o="return not in a function";function u(r,t){let e;try{e=r.evalCode(t,"return-probe.js",{type:"module",compileOnly:!0})}catch{return!1}if(!e.error)return e.value.dispose(),!1;const n=r.dump(e.error);return e.error.dispose(),String(n?.message??"").includes(o)}export{u as returnsFromTopLevel};
1
+ import{parse as n}from"acorn";const u=new Set(["FunctionDeclaration","FunctionExpression","ArrowFunctionExpression"]);function o(t){try{const r=n(t,{ecmaVersion:"latest",sourceType:"script",allowAwaitOutsideFunction:!0,allowReturnOutsideFunction:!0});return e(r)}catch{return!1}}function e(t){if(Array.isArray(t))return t.some(e);if(t===null||typeof t!="object")return!1;const{type:r}=t;return r==="ReturnStatement"?!0:typeof r=="string"&&u.has(r)?!1:Object.values(t).some(e)}export{o as returnsFromTopLevel};
@@ -10,6 +10,7 @@ export declare function setupHostFunctions(context: QuickJSContext, hostFunction
10
10
  globalName?: string;
11
11
  budget?: ExecutionBudget;
12
12
  maxCalls?: number;
13
+ maxOutputBytes?: number;
13
14
  messages?: {
14
15
  outputTooLarge?: (bytes: number) => string;
15
16
  callLimitExceeded?: (max: number) => string;
@@ -1,5 +1,5 @@
1
- import{DEFAULT_GLOBAL_NAME as v,MAX_HOST_OUTPUT_BYTES as _}from"../constants/host-functions.js";import{evalGuestCode as E}from"./eval-guest-code.js";function w(e,o,s){const l=s?.globalName??v,u=s?.maxCalls,f=s?.messages?.outputTooLarge??(n=>`Host function output is too large (${n} bytes); request narrower data instead`),m=s?.messages?.callLimitExceeded??(n=>`Exceeded the limit of ${n} host calls`),d=s?.budget?.hostCall??(n=>n()),c=new Set;let S=0;return e.newFunction("__invoke",(n,a)=>{const h=e.getString(n),p=JSON.parse(e.getString(a)),r=e.newPromise();return c.add(r),u!==void 0&&++S>u?e.newError(m(u)).consume(r.reject):d(()=>Promise.resolve().then(()=>o[h](p))).then(t=>{if(!e.alive)return;let i;try{i=JSON.stringify(t??null)}catch(g){const b=g instanceof Error?g.message:String(g);e.newError(`Host function output is not serializable: ${b}`).consume(r.reject);return}i.length>_?e.newError(f(i.length)).consume(r.reject):e.newString(i).consume(r.resolve)},t=>{if(!e.alive)return;const i=t instanceof Error?t.message:String(t);e.newError(i).consume(r.reject)}),r.settled.then(()=>{e.alive&&e.runtime.executePendingJobs()}),r.handle}).consume(n=>e.setProp(e.global,"__invoke",n)),E(e,O(Object.keys(o),l)),function(){for(const a of c)a.alive&&a.dispose()}}function O(e,o){const s=e.map(l=>`${JSON.stringify(l)}: (input) => invoke(${JSON.stringify(l)}, JSON.stringify(input ?? {})).then(JSON.parse)`).join(", ");return`(() => {
1
+ import{DEFAULT_GLOBAL_NAME as v,MAX_HOST_OUTPUT_BYTES as _}from"../constants/host-functions.js";import{evalGuestCode as E}from"./eval-guest-code.js";function w(e,o,n){const l=n?.globalName??v,u=n?.maxCalls,m=n?.maxOutputBytes??_,f=n?.messages?.outputTooLarge??(s=>`Host function output is too large (${s} bytes); request narrower data instead`),d=n?.messages?.callLimitExceeded??(s=>`Exceeded the limit of ${s} host calls`),p=n?.budget?.hostCall??(s=>s()),c=new Set;let S=0;return e.newFunction("__invoke",(s,a)=>{const h=e.getString(s),O=JSON.parse(e.getString(a)),r=e.newPromise();return c.add(r),u!==void 0&&++S>u?e.newError(d(u)).consume(r.reject):p(()=>Promise.resolve().then(()=>o[h](O))).then(i=>{if(!e.alive)return;let t;try{t=JSON.stringify(i??null)}catch(g){const b=g instanceof Error?g.message:String(g);e.newError(`Host function output is not serializable: ${b}`).consume(r.reject);return}t.length>m?e.newError(f(t.length)).consume(r.reject):e.newString(t).consume(r.resolve)},i=>{if(!e.alive)return;const t=i instanceof Error?i.message:String(i);e.newError(t).consume(r.reject)}),r.settled.then(()=>{e.alive&&e.runtime.executePendingJobs()}),r.handle}).consume(s=>e.setProp(e.global,"__invoke",s)),E(e,y(Object.keys(o),l)),function(){for(const a of c)a.alive&&a.dispose()}}function y(e,o){const n=e.map(l=>`${JSON.stringify(l)}: (input) => invoke(${JSON.stringify(l)}, JSON.stringify(input ?? {})).then(JSON.parse)`).join(", ");return`(() => {
2
2
  const invoke = globalThis.__invoke;
3
3
  delete globalThis.__invoke;
4
- globalThis[${JSON.stringify(o)}] = Object.freeze({ ${s} });
4
+ globalThis[${JSON.stringify(o)}] = Object.freeze({ ${n} });
5
5
  })();`}export{w as setupHostFunctions};
@@ -1 +1 @@
1
- import{pathToFileURL as z}from"url";import{HelmetProvider as G}from"@dr.pogodin/react-helmet";import{renderToString as l}from"react-dom/server";import{StaticRouterProvider as J,createStaticHandler as K,createStaticRouter as Q}from"react-router";import r from"react";import{readFile as V}from"fs/promises";import{join as W}from"path";import{withPathPrefix as m,getLocaleFromPathname as X,withoutPathPrefix as Y,removeTrailingSlash as Z}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as tt}from"../../utils/path/slash.js";import{reporter as et}from"../tools/notifiers/reporter.js";import{envConfig as p}from"../config/env-config.js";import{slug as rt}from"../../utils/slugger.js";import{shouldForwardProp as ot}from"../../utils/should-forward-prop.js";import{htmlTemplate as st}from"./template.js";import{detectColorSchemaScript as nt,generatePreloadPageData as at,generatePreloadSharedData as it}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as ct}from"./get-sitemap-link-tag.js";let g="";async function lt(t){return p.isRuntimeMode?await import("../../client/server-entry.js"):await import(z(`${tt(t)}/server-entry.js`)+"?"+new Date)}async function Bt(t){if(!p.isRuntimeMode){const e=et.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:u,App:R,routes:w,ServerStyleSheet:E,StyleSheetManager:P,ErrorDetails:C,initL10n:D}=await lt(t.serverOutDir),{page:h,store:{globalData:S,hasSitemap:y},sharedData:v,ssrHref:b}=t,d=S?.l10n,i=X(Y(h.slug),d?.defaultLocale,d?.locales),f=t.page.request?.url||"http://localhost/";await u.prepare({...h,slug:Z(new URL(f).pathname)},v,S,i),await D(i);const c=new E,{query:M,dataRoutes:x}=K([{Component:R,path:m("*"),children:w}]),s=await M(new Request(f));if(s instanceof Response)throw s;const B=Q(x,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=l(r.createElement(G,{context:e},r.createElement(P,{sheet:c.instance,shouldForwardProp:ot},r.createElement(J,{router:B,context:s})))),L=y?ct():"",a=e.helmet,j=a?.title.toString()||"",k=t.store.globalData?.logo?.favicon,o=t.store.config,_=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${m("/app-data.json")}" />`,F=at(t.page.slug),H=it(t.page.sharedDataIds),U=nt(o),A=t.page.product?.name?`product-${rt(t.page.product.name)}`:"",$=t.store.ssr.headTags.join(""),I=t.store.ssr.postBodyTags.join(""),N=t.store.ssr.preBodyTags.join(""),O=`<link rel="stylesheet" href="${m(T)}/browser-entry.css" />`;!p.isDevelopMode&&!g&&(g=`<style>${await V(W(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const q={bodyHtml:n,linkTags:o.linkTags+c.getStyleTags()+(a?.link.toString()||""),title:j,favicon:k,headScriptTags:L+U+o.headScriptTags+$+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[_,F,...H],postBodyScriptTags:o.postBodyScriptTags+I,preBodyScriptTags:o.preBodyScriptTags||""+N,lang:i,productClass:A,runtimeCss:g||O};return{html:st(q),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:l(r.createElement(C,{error:e})),statusCode:500,error:e}}finally{c.seal(),u.clear()}}function Lt(t){return l(r.createElement(r.Fragment,null,...t))}export{Bt as render,Lt as renderComponents};
1
+ import{pathToFileURL as z}from"url";import{HelmetProvider as G}from"@dr.pogodin/react-helmet";import{renderToString as l}from"react-dom/server";import{StaticRouterProvider as J,createStaticHandler as K,createStaticRouter as Q}from"react-router";import r from"react";import{readFile as V}from"fs/promises";import{join as W}from"path";import{withPathPrefix as m,getLocaleFromPathname as X,withoutPathPrefix as Y,removeTrailingSlash as Z,getSafeClassName as tt}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as et}from"../../utils/path/slash.js";import{reporter as rt}from"../tools/notifiers/reporter.js";import{envConfig as p}from"../config/env-config.js";import{slug as ot}from"../../utils/slugger.js";import{shouldForwardProp as st}from"../../utils/should-forward-prop.js";import{htmlTemplate as nt}from"./template.js";import{detectColorSchemaScript as at,generatePreloadPageData as it,generatePreloadSharedData as ct}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as lt}from"./get-sitemap-link-tag.js";let g="";async function mt(t){return p.isRuntimeMode?await import("../../client/server-entry.js"):await import(z(`${et(t)}/server-entry.js`)+"?"+new Date)}async function Lt(t){if(!p.isRuntimeMode){const e=rt.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:u,App:R,routes:w,ServerStyleSheet:E,StyleSheetManager:C,ErrorDetails:P,initL10n:D}=await mt(t.serverOutDir),{page:h,store:{globalData:S,hasSitemap:y},sharedData:v,ssrHref:b}=t,d=S?.l10n,i=X(Y(h.slug),d?.defaultLocale,d?.locales),f=t.page.request?.url||"http://localhost/";await u.prepare({...h,slug:Z(new URL(f).pathname)},v,S,i),await D(i);const c=new E,{query:M,dataRoutes:x}=K([{Component:R,path:m("*"),children:w}]),s=await M(new Request(f));if(s instanceof Response)throw s;const B=Q(x,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=l(r.createElement(G,{context:e},r.createElement(C,{sheet:c.instance,shouldForwardProp:st},r.createElement(J,{router:B,context:s})))),L=y?lt():"",a=e.helmet,j=a?.title.toString()||"",k=t.store.globalData?.logo?.favicon,o=t.store.config,_=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${m("/app-data.json")}" />`,F=it(t.page.slug),H=ct(t.page.sharedDataIds),U=at(o),A=t.page.product?.name?tt(`product-${ot(t.page.product.name)}`):"",N=t.store.ssr.headTags.join(""),$=t.store.ssr.postBodyTags.join(""),I=t.store.ssr.preBodyTags.join(""),O=`<link rel="stylesheet" href="${m(T)}/browser-entry.css" />`;!p.isDevelopMode&&!g&&(g=`<style>${await V(W(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const q={bodyHtml:n,linkTags:o.linkTags+c.getStyleTags()+(a?.link.toString()||""),title:j,favicon:k,headScriptTags:L+U+o.headScriptTags+N+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[_,F,...H],postBodyScriptTags:o.postBodyScriptTags+$,preBodyScriptTags:o.preBodyScriptTags||""+I,lang:i,productClass:A,runtimeCss:g||O};return{html:nt(q),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:l(r.createElement(P,{error:e})),statusCode:500,error:e}}finally{c.seal(),u.clear()}}function jt(t){return l(r.createElement(r.Fragment,null,...t))}export{Lt as render,jt as renderComponents};
@@ -1 +1 @@
1
- import C from"@markdoc/markdoc";import{getPathnameForLocale as A}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as M}from"./constants/common.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as k}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as D}from"../utils/path/is-local-link.js";import{reporter as S}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as 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 j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as U}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as w}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 v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},E="PLAN_GATES",Z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Oe="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;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:t,serverMode:s=!1,serverOutDir:r}){this.#i=t,this.outdir=e,this.serverMode=s,this.serverOutDir=r,F.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(a=>{this.#n=a})}on(e,t){const s=this.listeners.get(e);s?s.add(t):this.listeners.set(e,new Set([t]))}queueEvent=(e,t,...s)=>{this.#a.set(e+String(t),[e,t,...s])};runListeners=(e,t,...s)=>{for(const r of this.listeners.get(e)||new Set)t?r(t,...s):r(...s)};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=w.instance(),t=await U(this.serverOutDir),s=Object.fromEntries(Object.entries(t.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!0));this.#o={...t,tags:s}})}get markdocOptions(){return{...this.#o,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const t=this.globalData,s={...this.globalData,...e};this.globalData=s,JSON.stringify(s)!==JSON.stringify(t)&&this.queueEvent("global-data-updated",void 0,s)};getGlobalData=()=>this.globalData;getKv=async()=>B.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:t,deps:s,resource:r})=>{const{data:{info:a,ast:o},compoundHash:l}=await j(e,this.markdocOptions,{actions:this,context:t},r);for(const i of a.sharedDataDeps||[]){for(const n of s?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of s?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of a.dynamicMarkdocComponents||[]){for(const n of s?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of s?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(s?.routeSlugs&&a.partials?.length)for(const i of s.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of a.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:a,ast:o,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 t=Object.keys(e);for(const o of t)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:s,unsetEnvVars:r,replacedValues:a}=J(e);for(const o of r)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,a),Object.assign(this.config,s)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,t,s={})=>{if(!w.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(e).toLowerCase();this.config.redirects[o]=t;const{trackOriginalSource:l=!0}=s,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&z(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const t=h(e).toLowerCase(),s=W(t,this.config.redirects,this.config.wildcardRedirectsTree);if(!s)return null;if(D(s.to)){const r=h(s.to).toLowerCase();if(!r.endsWith("*")&&$(r,[t],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:s.to,type:s.type}};createSharedData=async(e,t,s)=>{if(s&&this.#t[e]===s)return e;const r=JSON.stringify(t),a=s??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,t,s)=>{const r=L(e),a=this.routesSharedData.get(r)||{};a[t]=s,this.routesSharedData.set(r,a),u.verbose(`Adding shared data to ${e}, ${t}, ${s}`)};getRouteSharedDataByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.routesSharedData.get(t)||{}:{}};getPartialsForRoute=e=>{const t=this.getGlobalConfig(m)||{},s=this.routesPartials.get(e);if(!s||s.length===0)return{};const r=this.getGlobalConfig(M)||{},a=new Set(s),o=Array.from(s);for(let i=0;i<o.length;i++){const n=o[i],c=r[n]?.partials??[];for(const d of c)a.has(d)||(a.add(d),o.push(d))}const l={};for(const i of a)t[i]&&(l[i]=t[i]);return l};addRoute=e=>{const s={...K(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:s}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,t,s)=>{const r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(a=>({code:a,name:a}));for(const a of r){const o=A(e,g,a.code,r);this.addRouteSharedData(o,t,s)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,t)=>{for(const s of t){const r=this.mcpToolHandlers.get(s.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',s.name,e,r.importPath),this.mcpToolHandlers.set(s.name,{...s,importPath:e}),u.verbose("Created MCP tool %s",s.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const t of e){const s=this.mcpToolHandlers.get(t);s&&this.mcpToolHandlers.set(t,{...s,hasAvailabilityGate:!0})}};addSkills=e=>{for(const t of e)this.skills.set(t.slug,t),u.verbose("Discovered skill %s",t.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const t of e)this.mcpToolHandlers.delete(t)};addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,t)=>{this.config.responseHeaders||(this.config.responseHeaders={});const s=new Set(t.map(o=>o.name.toLowerCase())),a=[...(this.config.responseHeaders[e]??[]).filter(o=>!s.has(o.name.toLowerCase())),...t];this.config.responseHeaders[e]=a};getRouteByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.getRouteBySlug(t):void 0};getRouteBySlug=(e,t={})=>{const{followRedirect:s=!0}=t,r=this.getRedirect(e);return s&&r?this.routesBySlug.get(h(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const t=this.getRedirect(e);if(!t)return!1;if(!D(t.to))return!0;const s=h(t.to);return this.routesBySlug.has(s)};getRoutesByTemplateId=e=>this.newRoutes.filter(t=>t.templateId===e);getAllRoutesForLocale=(e=g)=>{const t=Array.from(this.routesBySlug.values()),s=e.toLowerCase();return t.filter(r=>e===g?!x(r.fsPath):r.slug.startsWith(`/${s}`))};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,t)=>(this.templates.set(e,t),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,t)=>(this.apiRoutesRequestHandlers.set(e,t),e);clearRequestHandlersByPrefix=e=>{for(const t of this.apiRoutesRequestHandlers.keys())t.startsWith(e)&&this.apiRoutesRequestHandlers.delete(t)};registerServerPropsGetter=(e,t)=>(this.serverPropsGetters.set(e,t),e);registerPagePropsGetter=(e,t)=>{this.pagePropsGetters.set(e,t)};async writeRouteStaticData(e,t){const s=await this.resolveRouteStaticData(e,t,!1);s&&q(e.slug,s,this.outdir)}async resolveRouteStaticData(e,t,s){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)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=a?.frontmatter||{};return{...a,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...a.props,dynamicMarkdocComponents:Array.from(o),metadata:{...a?.props?.metadata,...e.metadata},seo:{title:T,...i,...a.props?.seo},compilationErrors:this.compilationErrors},lastModified:s||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,t){if(!e?.length)return;const s=typeof e[0]=="string"?e.join(""):N(e);s&&(t==="head"?this.ssr.headTags.push(s):t==="preBody"?this.ssr.preBodyTags.push(s):this.ssr.postBodyTags.push(s))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[s,r]of Object.entries(v))switch(r){case"map":const a=Array.from(this[s].entries());e.push([s,a]);break;case"object":if(s==="config"){e.push([s,await this.getConfigWithEnvPlaceholders()]);break}e.push([s,this[s]]);break;default:throw new Error("Invalid format")}const t=Object.fromEntries(e);return t[E]=G.PLAN_GATES,t}static fromJson(e,t){const s=new P(t);for(const[a,o]of Object.entries(v))switch(o){case"map":s[a]=new Map(e[a]);break;case"object":if(a==="config"){s.setGlobalConfig(e[a]);break}s[a]=e[a];break;default:throw new Error("Invalid format")}s.config[m]=Q(s.config[m]||{});const r=e[E];return r&&_("PLAN_GATES",r),s}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const t in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[t],r=t.split(":"),a=r.pop(),{error:o,value:l}=y(e,r);if(o||!O(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${t}`);continue}l[a]=s}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(s=>!Z.includes(s));if(e.length===0)return;const t=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await S.panicOnBuildContentError(t)}}function Q(b){return k(b,e=>C.Ast.fromJSON(JSON.stringify(e)))}export{P as Store,Oe as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
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};
@@ -30,7 +30,7 @@ export type SearchParameters = {
30
30
  export type SearchIndex = {
31
31
  add(document: SearchDocument): void;
32
32
  search(params: SearchParameters): Promise<SearchResponse>;
33
- export(handler: ExportHandler<string | SearchDocument>): void;
33
+ export(handler: ExportHandler<string | IndexedSearchDocument>): void;
34
34
  import(searchData: FlexSearchData): void;
35
35
  clearDocuments(): void;
36
36
  };
@@ -40,7 +40,7 @@ export type AddDocumentsParams = {
40
40
  outDir: string;
41
41
  };
42
42
  export type FlexSearchData = {
43
- documents: [number, SearchDocument][];
43
+ documents: [number, IndexedSearchDocument][];
44
44
  index: Record<string, any>;
45
45
  };
46
46
  export type TypesenseSearchData = {
@@ -86,6 +86,11 @@ export type SearchDocument = {
86
86
  rbacTeams?: string[];
87
87
  [SEARCH_DOCUMENT_METADATA_KEY]?: SearchDocumentMetadata;
88
88
  };
89
+ /** Parameter fields kept in the FlexSearch index and its export; the rest never leaves the build. */
90
+ export type IndexedParameter = Pick<OperationParameter, 'name' | 'description' | 'place' | 'path' | 'deepLink'>;
91
+ export type IndexedSearchDocument = Omit<SearchDocument, 'parameters'> & {
92
+ parameters?: IndexedParameter[];
93
+ };
89
94
  export type TypesenseSearchDocument = Omit<SearchDocument, typeof SEARCH_DOCUMENT_METADATA_KEY> & {
90
95
  metadata_curated?: boolean;
91
96
  metadata_keywords_includes?: string[];
@@ -1,5 +1,9 @@
1
1
  import picomatch from 'picomatch';
2
2
  export declare const getDeeperGlobPattern: (a: ReturnType<typeof picomatch.scan>, b: ReturnType<typeof picomatch.scan>) => import("picomatch/lib/scan").State;
3
+ /**
4
+ * Parses every pattern once, so the returned function is cheap to call multiple times.
5
+ */
6
+ export declare function compileGlobMatcher(patterns: string[]): (relativePath: string) => boolean;
3
7
  export declare function pathMatchesGlobPattern(relativePath: string, pattern: string): boolean;
4
8
  export declare function getMostSpecificMatchingGlobKey(relativePath: string, globMap?: Record<string, unknown>): string | undefined;
5
9
  export declare function resolveGlobMapValue<T>(relativePath: string, globMap?: Record<string, T>): T | undefined;
@@ -1 +1 @@
1
- import s from"picomatch";import{minimatch as l}from"minimatch";import u from"is-glob";import c from"path";import{removeTrailingSlash as f}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as m}from"../../utils/url/remove-leading-slash.js";const p=(t,e)=>{const n=t.tokens??[],o=e.tokens??[];if(t.isGlob!==e.isGlob)return t.isGlob?e:t;if(n.length!==o.length)return n.length>o.length?t:e;for(let r=0;r<n.length;r++){if(n[r].isGlob!==o[r].isGlob)return n[r].isGlob?e:t;if(n[r].value!==o[r].value)return n[r].value.length>o[r].value.length?t:e}return t};function h(t,e){if(u(e)){if(l(t,e))return!0}else{const n=f(m(c.posix.normalize(e))),o=t.startsWith(n+"/");if(t===n||o)return!0}return!1}function a(t,e){if(!e)return;const n=[];for(const i of Object.keys(e))h(t,i)&&n.push(i);if(!n.length)return;const o=n.map(i=>s.scan(i,{tokens:!0,parts:!0}));let r=o[0];for(let i=1;i<o.length;i++)r=p(r,o[i]);return r.input}function v(t,e){const n=a(t,e);return n!=null&&e?e[n]:void 0}function y(t){const e=s.makeRe(t);return e||void 0}export{y as convertGlobToRegex,p as getDeeperGlobPattern,a as getMostSpecificMatchingGlobKey,h as pathMatchesGlobPattern,v as resolveGlobMapValue};
1
+ import s from"picomatch";import{minimatch as m,Minimatch as p}from"minimatch";import c from"is-glob";import l from"path";import{removeTrailingSlash as u}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as f}from"../../utils/url/remove-leading-slash.js";const h=(n,t)=>{const e=n.tokens??[],o=t.tokens??[];if(n.isGlob!==t.isGlob)return n.isGlob?t:n;if(e.length!==o.length)return e.length>o.length?n:t;for(let r=0;r<e.length;r++){if(e[r].isGlob!==o[r].isGlob)return e[r].isGlob?t:n;if(e[r].value!==o[r].value)return e[r].value.length>o[r].value.length?n:t}return n};function v(n){const t=n.map(e=>{if(c(e)){const r=new p(e);return i=>r.match(i)}const o=u(f(l.posix.normalize(e)));return r=>r===o||r.startsWith(o+"/")});return e=>t.some(o=>o(e))}function a(n,t){if(c(t)){if(m(n,t))return!0}else{const e=u(f(l.posix.normalize(t))),o=n.startsWith(e+"/");if(n===e||o)return!0}return!1}function d(n,t){if(!t)return;const e=[];for(const i of Object.keys(t))a(n,i)&&e.push(i);if(!e.length)return;const o=e.map(i=>s.scan(i,{tokens:!0,parts:!0}));let r=o[0];for(let i=1;i<o.length;i++)r=h(r,o[i]);return r.input}function P(n,t){const e=d(n,t);return e!=null&&t?t[e]:void 0}function T(n){const t=s.makeRe(n);return t||void 0}export{v as compileGlobMatcher,T as convertGlobToRegex,h as getDeeperGlobPattern,d as getMostSpecificMatchingGlobKey,a as pathMatchesGlobPattern,P as resolveGlobMapValue};
@@ -1 +1 @@
1
- import{HIGHLIGHTED_TEXT_MAX_LENGTH as a}from"../../constants/plugins/search.js";function L(n,g){const p=n.split(/\s+/g),d=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),e=p.reduce((t,h)=>{if(!h||!t?.replace)return t;const u=new RegExp(`(^|\\s)${d(h)}`,"gi");return t.replace(u,(l,H,x,k)=>{const m=k.substring(0,x),T=(m.match(/<mark>/g)??[]).length,$=(m.match(/<\/mark>/g)??[]).length;return T>$?l:`<mark>${l}</mark>`})},g);if(!e)return g||"";if(e.replace(/<mark>/g,"").replace(/<\/mark>/g,"").length<a)return e;const s=e.indexOf("<mark>"),i=e.indexOf("</mark>")+7,r=a/2+n.length/2,o=s<r,c=i+r<e.length,f=e.substring(o?0:s-r,c?i+r:e.length);return`${o?"":"..."}${f}${c?"...":""}`}export{L as highlightTextForSearch};
1
+ import{HIGHLIGHTED_TEXT_MAX_LENGTH as l}from"../../constants/plugins/search.js";const h=i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function m(i,n){if(!n)return"";const o=[...new Set(i.split(/\s+/g).filter(Boolean))].sort((t,e)=>e.length-t.length);if(!o.length)return n;const a=new RegExp(`(^|\\s)(${o.map(h).join("|")})`,"gi");let s=n,g="",c="";if(n.length>l){const t=a.exec(n);a.lastIndex=0;const e=Math.max(0,(t?.index??0)-l/2),r=Math.min(n.length,e+l);s=n.substring(e,r),g=e>0?"...":"",c=r<n.length?"...":""}return g+s.replace(a,(t,e,r)=>`${e}<mark>${r}</mark>`)+c}export{m as highlightTextForSearch};
@@ -1 +1 @@
1
- import{DEFAULT_SEARCH_ENGINE as r}from"@redocly/config";import{logger as e}from"../../tools/notifiers/logger.js";import{SearchEngine as t}from"../../plugins/search/engines/search-engine.js";function E(a){return async(o,i)=>{if(!a.searchEngine&&!a.config?.search?.hide){e.info("Loading search data...");const c=a.config?.search?.engine??r,n=new t(c,a.globalData.l10n);await n.initIndexSchema(a.searchFacets),await n.import(a.outdir),a.setSearchEngine(n),e.info("Search data loaded")}await i()}}export{E as ensureSearchData};
1
+ import{DEFAULT_SEARCH_ENGINE as t}from"@redocly/config";import{logger as c}from"../../tools/notifiers/logger.js";import{SearchEngine as o}from"../../plugins/search/engines/search-engine.js";function f(a){let e;const r=async()=>{c.info("Loading search data...");const i=a.config?.search?.engine??t,n=new o(i,a.globalData.l10n);await n.initIndexSchema(a.searchFacets),await n.import(a.outdir),a.setSearchEngine(n),c.info("Search data loaded")};return async(i,n)=>{!a.searchEngine&&!a.config?.search?.hide&&(e??=r().finally(()=>{e=void 0}),await e),await n()}}export{f as ensureSearchData};
@@ -1 +1 @@
1
- import m from"path";import{REDOCLY_ROUTE_RBAC as v,REDOCLY_TEAMS_RBAC as B}from"@redocly/config";import{combineUrls as F,withoutPathPrefix as Q,withPathPrefix as ee}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as z,CACHE_CONTROL_PUBLIC_HTML as te,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as ne,X_REDOCLY_CACHE_CONTROL_HEADER as oe,X_REDOCLY_CACHE_CONTROL_PUBLIC_HTML as re}from"../../constants/common.js";import{removeTrailingSlash as ie}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as ae}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as se}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as ce}from"../../config/env-config.js";import{sanitizePath as le}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as me}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as ue}from"../../../utils/path/is-path-in-folder.js";import{getLlmsTxtMdPathBySlug as de}from"../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";import{resolveLlmsTxtMd as X}from"../../utils/llmstxt/resolve-llms-txt-md.js";import{removeLeadingSlash as fe}from"../../../utils/url/remove-leading-slash.js";import{processRedirects as ge}from"./helpers/process-redirects.js";import{renderPage as pe,getServerProps as he}from"../../ssr/index.js";import{canAccessAsset as Ce,canAccessResource as Y}from"../../utils/rbac.js";import{handleErrorPageRender as $,handleUnauthorized as k,handleUnauthorizedAsset as N}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as Re,MIME_TYPES as Ae}from"../mime-types.js";import{fileExistsAsync as Ee}from"../../utils/index.js";import{isAiAgentRequest as Le}from"../../utils/ai-agent-detection.js";import{getRedirectRoute as _e}from"../utils/legacy-openapi-redirects.js";import{getContentTypeHeaderValue as G}from"../utils/content-type.js";import{telemetry as we}from"../../../cli/telemetry/index.js";import{telemetry as Te}from"../../telemetry/index.js";function Ke(e,j,V,E){return async n=>{const L=n.get("logger"),r=n.req,a=new URL(r.url),i=Q(le(decodeURIComponent(a.pathname))),_=m.parse(i).ext===".md",w=Le({accept:r.header("accept"),signatureAgent:r.header("signature-agent"),signature:r.header("signature"),signatureInput:r.header("signature-input"),userAgent:r.header("user-agent")}),s=me(i),o=(r.method==="GET"||r.method==="HEAD")&&!_?e.getRouteBySlug(s,{followRedirect:!1})||ae(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(i===t.slug||i.startsWith(t.slug+"/"))):void 0,T=e.getRedirect(s);if(T){const t=ge({redirect:T,reqUrlSearch:a.search});return Te.sendRedirectMessage([{id:s,object:"redirect",uri:`urn:redocly:realm:api:redirect:${s}`,from:s,templateId:t.type.toString()}]),n.newResponse(null,t.type,{Location:t.location})}const g=ce.isProductionEnv?301:302;if(o?.metadata?.type==="openapi"){const t=_e(a.pathname);if(t)return L.info("Legacy OpenAPI docs redirect from "+a.pathname),n.newResponse(null,g,{Location:encodeURI(t)});if(a.pathname.match(/[A-Z]/))return L.warn("Redirect to lowercase route to avoid 404 error"),n.newResponse(null,g,{Location:encodeURI(a.pathname.toLowerCase())})}if(i.endsWith("/")&&i!=="/"){const t=se(new URL(s||"/",n.req.url).pathname);return n.newResponse(null,g,{Location:encodeURI(ee((t==="/"?"/":ie(t))+a.search))})}const{isAuthenticated:u,teams:p,claims:{email:h}}=n.get("auth");if(o&&!Y(o,{isAuthenticated:u,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return u?$(n,e,{slug:o.slug,[B]:o[B],[v]:o[v]},403):k(n,e,o.slug);const d=o&&w?de(o.slug):void 0,P=d?await X(d,e,E):void 0,U=P?.exists??!1;if(o&&(!w||!U)){const t=await j(o),Z=await he(o,n,t,e),{html:x,statusCode:S,error:J}=await pe(o,Z,n,e,we),D=e.config.access?.rbac,H=!e.config.access?.requiresLogin&&(!D||!Object.keys(D).length),q=S>=400||!!J||!!e.compilationErrors?.length,K=H&&!q;let f;return q?f=z:H?f=te:f="private",n.html(x,S,{"Cache-Control":f,...K&&{[oe]:re}})}const C=d&&U?d:i,W=fe(C),c=m.resolve(e.outdir,W);if(!ue(c,e.outdir))return N(n);let l,M;if(_){const t=await X(i,e,E);if(l=t.route,M=t.content,l&&!Y(l,{isAuthenticated:u,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return k(n,e,i)}const b=e.getGlobalConfig("access");if(!Ce(C,b?.rbac||{},b?.requiresLogin||!1,e.getGlobalConfig("directoryPaths"),{isAuthenticated:u,email:h,teams:p}))return N(n);const R=Ae[m.extname(c)]||"text/plain",A=c.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||c.match(/runtime\/chunks\/.*/)?ne:Re[R],y=A?{"Cache-Control":`public, max-age=${A}, immutable`,Expires:new Date(Date.now()+A*1e3).toUTCString()}:{"Cache-Control":z},O=r.query("download")!=null,I=P?.content??M;if(I!==void 0)return n.newResponse(I,200,{"Content-Type":G(R),"Access-Control-Allow-Origin":"*",...y,...l&&{"X-Robots-Tag":"noindex, follow",...e.config.seo?.siteUrl&&{Link:`<${F(e.config.seo.siteUrl,l.slug)}>; rel="canonical"`}},...O&&{"Content-Disposition":`attachment; filename="${m.basename(C)}"`}});if(await Ee(c)){const t=await V(c);return n.newResponse(t,200,{"Content-Type":G(R),"Access-Control-Allow-Origin":"*",...y,...l&&{"X-Robots-Tag":"noindex, follow",...e.config.seo?.siteUrl&&{Link:`<${F(e.config.seo.siteUrl,l.slug)}>; rel="canonical"`}},...O&&{"Content-Disposition":`attachment; filename="${m.basename(c)}"`}})}else return $(n,e,{slug:s},404)}}export{Ke as dynamicRouteHandler};
1
+ import m from"path";import{REDOCLY_ROUTE_RBAC as B,REDOCLY_TEAMS_RBAC as F}from"@redocly/config";import{combineUrls as z,withoutPathPrefix as ee,withPathPrefix as E}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as X,CACHE_CONTROL_PUBLIC_HTML as te,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as ne,X_REDOCLY_CACHE_CONTROL_HEADER as oe,X_REDOCLY_CACHE_CONTROL_PUBLIC_HTML as re}from"../../constants/common.js";import{removeTrailingSlash as ie}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as ae}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as se}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as ce}from"../../config/env-config.js";import{sanitizePath as le}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as me}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as ue}from"../../../utils/path/is-path-in-folder.js";import{getLlmsTxtMdPathBySlug as de}from"../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";import{resolveLlmsTxtMd as Y}from"../../utils/llmstxt/resolve-llms-txt-md.js";import{removeLeadingSlash as fe}from"../../../utils/url/remove-leading-slash.js";import{processRedirects as ge}from"./helpers/process-redirects.js";import{renderPage as pe,getServerProps as he}from"../../ssr/index.js";import{canAccessAsset as Ce,canAccessResource as $}from"../../utils/rbac.js";import{handleErrorPageRender as k,handleUnauthorized as N,handleUnauthorizedAsset as G}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as Re,MIME_TYPES as Ae}from"../mime-types.js";import{fileExistsAsync as Ee}from"../../utils/index.js";import{isAiAgentRequest as Le}from"../../utils/ai-agent-detection.js";import{getRedirectRoute as _e}from"../utils/legacy-openapi-redirects.js";import{getContentTypeHeaderValue as j}from"../utils/content-type.js";import{telemetry as we}from"../../../cli/telemetry/index.js";import{telemetry as Te}from"../../telemetry/index.js";function Ke(e,V,W,L){return async n=>{const _=n.get("logger"),r=n.req,a=new URL(r.url),i=ee(le(decodeURIComponent(a.pathname))),w=m.parse(i).ext===".md",T=Le({accept:r.header("accept"),signatureAgent:r.header("signature-agent"),signature:r.header("signature"),signatureInput:r.header("signature-input"),userAgent:r.header("user-agent")}),s=me(i),o=(r.method==="GET"||r.method==="HEAD")&&!w?e.getRouteBySlug(s,{followRedirect:!1})||ae(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(i===t.slug||i.startsWith(t.slug+"/"))):void 0,P=e.getRedirect(s);if(P){const t=ge({redirect:P,reqUrlSearch:a.search});return Te.sendRedirectMessage([{id:s,object:"redirect",uri:`urn:redocly:realm:api:redirect:${s}`,from:s,templateId:t.type.toString()}]),n.newResponse(null,t.type,{Location:t.location})}const g=ce.isProductionEnv?301:302;if(o?.metadata?.type==="openapi"){const t=_e(a.pathname);if(t)return _.info("Legacy OpenAPI docs redirect from "+a.pathname),n.newResponse(null,g,{Location:encodeURI(t)});if(a.pathname.match(/[A-Z]/))return _.warn("Redirect to lowercase route to avoid 404 error"),n.newResponse(null,g,{Location:encodeURI(a.pathname.toLowerCase())})}if(i.endsWith("/")&&i!=="/"){const t=se(new URL(s||"/",n.req.url).pathname);return n.newResponse(null,g,{Location:encodeURI(E((t==="/"?"/":ie(t))+a.search))})}const{isAuthenticated:u,teams:p,claims:{email:h}}=n.get("auth");if(o&&!$(o,{isAuthenticated:u,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return u?k(n,e,{slug:o.slug,[F]:o[F],[B]:o[B]},403):N(n,e,o.slug);const d=o&&T?de(o.slug):void 0,U=d?await Y(d,e,L):void 0,M=U?.exists??!1;if(o&&(!T||!M)){const t=await V(o),x=await he(o,n,t,e),{html:J,statusCode:D,error:K}=await pe(o,x,n,e,we),H=e.config.access?.rbac,q=!e.config.access?.requiresLogin&&(!H||!Object.keys(H).length),v=D>=400||!!K||!!e.compilationErrors?.length,Q=q&&!v;let f;return v?f=X:q?f=te:f="private",n.html(J,D,{"Cache-Control":f,...Q&&{[oe]:re}})}const C=d&&M?d:i,Z=fe(C),c=m.resolve(e.outdir,Z);if(!ue(c,e.outdir))return G(n);let l,b;if(w){const t=await Y(i,e,L);if(l=t.route,b=t.content,l&&!$(l,{isAuthenticated:u,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return N(n,e,i)}const y=e.getGlobalConfig("access");if(!Ce(C,y?.rbac||{},y?.requiresLogin||!1,e.getGlobalConfig("directoryPaths"),{isAuthenticated:u,email:h,teams:p}))return G(n);const R=Ae[m.extname(c)]||"text/plain",A=c.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||c.match(/runtime\/chunks\/.*/)?ne:Re[R],O=A?{"Cache-Control":`public, max-age=${A}, immutable`,Expires:new Date(Date.now()+A*1e3).toUTCString()}:{"Cache-Control":X},I=r.query("download")!=null,S=U?.content??b;if(S!==void 0)return n.newResponse(S,200,{"Content-Type":j(R),"Access-Control-Allow-Origin":"*",...O,...l&&{"X-Robots-Tag":"noindex, follow",...e.config.seo?.siteUrl&&{Link:`<${z(e.config.seo.siteUrl,E(l.slug))}>; rel="canonical"`}},...I&&{"Content-Disposition":`attachment; filename="${m.basename(C)}"`}});if(await Ee(c)){const t=await W(c);return n.newResponse(t,200,{"Content-Type":j(R),"Access-Control-Allow-Origin":"*",...O,...l&&{"X-Robots-Tag":"noindex, follow",...e.config.seo?.siteUrl&&{Link:`<${z(e.config.seo.siteUrl,E(l.slug))}>; rel="canonical"`}},...I&&{"Content-Disposition":`attachment; filename="${m.basename(c)}"`}})}else return k(n,e,{slug:s},404)}}export{Ke as dynamicRouteHandler};
@@ -1 +1 @@
1
- import{getCookie as A}from"hono/cookie";import{createHash as K,timingSafeEqual as J}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 E}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 b,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 y,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}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 ne}from"../../../utils/crypto/decrypt-aes-gcm.js";import{encryptAesGcm as F}from"../../../utils/crypto/encrypt-aes-gcm.js";import{fetchClientMetadataDocument as oe,isClientMetadataDocumentUrl as H,isRedirectUriRegistered as ie}from"./mcp-client-metadata.js";const s=(r,e,t=200,i)=>r.json(e,t,{"Content-Type":"application/json",...i??{}}),N=new Set(["S256"]),$=["authorization_code","refresh_token"],se="https://claude.ai/oauth/claude-code-client-metadata";function ce(r,e,t){if(!N.has(e||""))return!1;const i=K("sha256").update(t).digest("base64url"),c=Buffer.from(i),o=Buffer.from(r);return c.length!==o.length?!1:J(c,o)}async function de(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 ae(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 Oe(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:[...E],bearer_token_types_supported:["Bearer"]},200,{"Access-Control-Allow-Origin":"*"})}}function Ue(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:[...E],registration_endpoint:`${t}${I(T.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,response_types_supported:["code"],grant_types_supported:[...$],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 De(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:[...$],response_types:["code"],scope:E.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),i=t.find(o=>v(e[o])&&Y(e[o])),c=t.find(o=>v(e[o]));return i||c||t[0]}function qe(r){return async e=>{if(!P(r))return s(e,{error:"not_found"},404);const t=new URL(e.req.url),{searchParams:i}=t,c=i.get("redirect_uri"),o=i.get("client_id"),a=i.get("code_challenge"),n=i.get("code_challenge_method"),l=V();if(a&&!N.has(n||""))return s(e,{error:"invalid_request",error_description:`Unsupported code_challenge_method. Supported: ${[...N].join(", ")}`},400);if(H(o)&&!a)return s(e,{error:"invalid_request",error_description:"code_challenge is required for client_id_metadata_document clients"},400);if(H(o)&&c)try{const d=await oe(o),p=o===se;if(!ie(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([{...y(l),redirect_uri:c||null}]);const f=q(e),_={isMcpFlow:!0,originalRedirectUri:c,mcpClientId:o,mcpState:i.get("state"),mcpSessionId:l,mcpCodeChallenge:a,mcpCodeChallengeMethod:a?n:null,timestamp:Date.now()};try{const d=await de(_),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([{...y(l),error:p,error_details:k}]);const C=new URL(I(`${Z}/oauth2/auth`));return C.search=i.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),i=r.ttlSec??(typeof r.claims.exp=="number"?Math.max(r.claims.exp-e,0):b);return{accessToken:t,expiresIn:i}}async function le(r,e,t){const i=g=>s(r,{error:"invalid_grant",error_description:g},400),c=r.get("logger"),o=t.get("refresh_token"),a=t.get("client_id")||void 0;if(!o)return s(r,{error:"invalid_request",error_description:"refresh_token is required"},400);let n;try{n=await X(o)}catch(g){return c?.warn("MCP refresh token rejected: %s",g instanceof Error?g.message:String(g)),i("Invalid refresh token")}if(a&&a!==n.client_id)return i("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=ne(n.idp_refresh_token_enc,m)}catch{return i("Invalid refresh token")}if(!n.idp_id||!v(l))return i("Unknown identity provider");let u;try{const h=await re(n.idp_id,l);if(!h?.token_endpoint)return i("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"),i("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 i("Invalid token response from identity provider")}}const k=v(l)&&l.tokenExpirationTime||b,C=f??n.claims,w=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:w.accessToken,token_type:"Bearer",expires_in:w.expiresIn,refresh_token:O,scope:E.join(" ")},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}function Le(r){return async e=>{if(e.req.method!=="POST")return s(e,{error:"Method not allowed"},405);try{const t=await e.req.formData(),i=t.get("grant_type"),c=t.get("code"),o=t.get("redirect_uri")||void 0,a=t.get("code_verifier")||void 0;if(!$.includes(i))return s(e,{error:"invalid_request",error_description:"Invalid grant type"},400);if(i==="refresh_token")return await le(e,r,t);if(!c)return s(e,{error:"invalid_request",error_description:"Missing authorization code"},400);try{const n=await Q(c);if(o&&o!==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(!ce(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&&!H(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,w=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:w,scope:E.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 i=t instanceof Error?t.message:String(t);return s(e,{error:"server_error",error_description:"Failed to process token request",error_details:i},500)}}}async function pe(r,e){try{const{payload:t,header:i}=S.decode(r);if(typeof t.idpId=="string"&&t.idpId)return t.idpId;if(i.kid){z.jwks[i.kid]==null&&await te(e||{});const c=z.jwks[i.kid];if(c?.idpId)return c.idpId}}catch{}return G(e)}function He(r){return async e=>{const t=new URL(e.req.url);let i=t.searchParams.get("context");if(!i&&t.pathname.startsWith(I(`${T.MCP_CALLBACK}/`))){const o=t.pathname.split("/");i=o[o.length-1]}if(!i)return M.sendMcpAuthorizationFailedMessage([{...y(null),error:"Missing context parameter",error_details:null}]),e.text("Missing context parameter",400);let c=null;try{const o=await ae(i);if(c=o.mcpSessionId||null,!o.isMcpFlow||!o.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([{...y(c),error:"Authentication required",error_details:null}]),e.text("Authentication required",401);const f=await x({idToken:a,idpId:await pe(a,r.getConfig().ssoDirect),idpAccessTokenEnc:n?L(n,m):void 0,idpRefreshTokenEnc:l?F(l,m):void 0,clientId:o.mcpClientId||"",redirectUri:o.originalRedirectUri,codeChallenge:o.mcpCodeChallenge||void 0,codeChallengeMethod:o.mcpCodeChallengeMethod||void 0,ttlSec:600}),_=new URL(o.originalRedirectUri);return _.searchParams.set("code",f),o.mcpState&&_.searchParams.set("state",o.mcpState),M.sendMcpAuthorizationCompletedMessage([{...y(c),redirect_uri:o.originalRedirectUri||null}]),e.redirect(_.toString())}catch(o){const a=o instanceof Error?o.message:String(o),n=o instanceof Error?o.stack:String(o);return M.sendMcpAuthorizationFailedMessage([{...y(c),error:a,error_details:n}]),e.text(`Invalid MCP callback: ${a}`,400)}}}export{$ as SUPPORTED_MCP_GRANT_TYPES,de as createMcpContextToken,qe as mcpAuthorizationHandler,He as mcpCallbackHandler,De as mcpDynamicClientRegistrationHandler,Ue as mcpOAuthAuthorizationServerHandler,Oe as mcpOAuthProtectedResourceHandler,Le as mcpTokenPortalHandler,G as resolveMcpIdpId,ae as verifyAndParseMcpContextToken,ce 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{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 +1 @@
1
- import{withPathPrefix as A}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as b,MCP_PROTOCOL_VERSION as S}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as T}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as g}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as v,FETCH_TOOL_NAME as M}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as O}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as R}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{normalizeToolDisplayName as L}from"../../../plugins/mcp/utils/tool-registration.js";import{buildCodeModeInstructions as y,buildExecuteDescription as D}from"../../../plugins/mcp/codemode/prompts.js";import{toToolListEntries as I}from"../../../plugins/mcp/codemode/build-tool-list.js";import{composeExecuteAnnotations as P}from"../../../plugins/mcp/codemode/capabilities/index.js";import{ALL_CAPABILITIES as V}from"../../../plugins/mcp/codemode/capabilities/registry.js";import{isGatewayCapabilityEnabled as H}from"../../../plugins/mcp/gateway-mcp/eligibility.js";import{shouldHandleMcpAuth as U}from"../../../utils/rbac/should-handle-mcp-auth.js";import{resolvePublicBaseUrl as x}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as N}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as w}from"./constants.js";const j="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",k="1.0";function se(r){const s=g(),u=new Date().toISOString().slice(0,10);return async a=>await N("com.redocly.mcpServerCard.served",async e=>{e?.setAttribute("id","mcpServerCardId"),e?.setAttribute("object","mcpServerCard"),e?.setAttribute("uri","urn:redocly:realm:api:mcpServerCard:mcpServerCardId");const o=r.getConfig(),m=o.mcp?.docs?.name||b,n=r.getMcpTools().filter(t=>!v.has(t.name)&&!t.hasAvailabilityGate),i=H(o.mcp)?[...V]:[],l=i.some(t=>t.id===M),d=I(n,i),c=(s?[{...O,description:D(l,d),annotations:P(i)},R(n,i)]:n).map(L).map(({name:t,title:E,description:f,schema:h,annotations:_})=>({name:t,title:E,description:f,inputSchema:h,annotations:_})),C=o.skills?.hide===!0?[]:r.getSkills(),p={$schema:j,version:k,protocolVersion:S,serverInfo:{name:m,title:m,version:u},description:o.seo?.description,documentationUrl:x(r,a),transport:{type:"streamable-http",endpoint:A(T.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...C.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:U(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:w}:void 0,instructions:s?y(l,d):void 0,tools:c.length>0?c:["dynamic"]};return e?.setAttribute("mode",s?"code":"tools"),e?.setAttribute("toolsCount",c.length),e?.setAttribute("authRequired",p.authentication!==void 0),a.json(p,200,{"Access-Control-Allow-Origin":"*","Cache-Control":"public, max-age=3600"})})}export{se as mcpServerCardHandler};
1
+ import{combineUrls as b,withPathPrefix as u}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as S,MCP_PROTOCOL_VERSION as T}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as g}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as v}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as M,FETCH_TOOL_NAME as O}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as R}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as L}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{normalizeToolDisplayName as y}from"../../../plugins/mcp/utils/tool-registration.js";import{buildCodeModeInstructions as D,buildExecuteDescription as I}from"../../../plugins/mcp/codemode/prompts.js";import{toToolListEntries as P}from"../../../plugins/mcp/codemode/build-tool-list.js";import{composeExecuteAnnotations as U}from"../../../plugins/mcp/codemode/capabilities/index.js";import{ALL_CAPABILITIES as V}from"../../../plugins/mcp/codemode/capabilities/registry.js";import{isGatewayCapabilityEnabled as H}from"../../../plugins/mcp/gateway-mcp/eligibility.js";import{shouldHandleMcpAuth as x}from"../../../utils/rbac/should-handle-mcp-auth.js";import{resolvePublicBaseUrl as N}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as w}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as j}from"./constants.js";const k="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",q="1.0";function ne(r){const s=v(),C=new Date().toISOString().slice(0,10);return async m=>await w("com.redocly.mcpServerCard.served",async e=>{e?.setAttribute("id","mcpServerCardId"),e?.setAttribute("object","mcpServerCard"),e?.setAttribute("uri","urn:redocly:realm:api:mcpServerCard:mcpServerCardId");const o=r.getConfig(),a=o.mcp?.docs?.name||S,n=r.getMcpTools().filter(t=>!M.has(t.name)&&!t.hasAvailabilityGate),i=H(o.mcp)?[...V]:[],l=i.some(t=>t.id===O),d=P(n,i),c=(s?[{...R,description:I(l,d),annotations:U(i)},L(n,i)]:n).map(y).map(({name:t,title:f,description:h,schema:_,annotations:A})=>({name:t,title:f,description:h,inputSchema:_,annotations:A})),E=o.skills?.hide===!0?[]:r.getSkills(),p={$schema:k,version:q,protocolVersion:T,serverInfo:{name:a,title:a,version:C},description:o.seo?.description,documentationUrl:b(N(r,m),u("/")),transport:{type:"streamable-http",endpoint:u(g.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...E.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:x(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:j}:void 0,instructions:s?D(l,d):void 0,tools:c.length>0?c:["dynamic"]};return e?.setAttribute("mode",s?"code":"tools"),e?.setAttribute("toolsCount",c.length),e?.setAttribute("authRequired",p.authentication!==void 0),m.json(p,200,{"Access-Control-Allow-Origin":"*","Cache-Control":"public, max-age=3600"})})}export{ne as mcpServerCardHandler};
@@ -14,19 +14,4 @@
14
14
  * ```
15
15
  */
16
16
  export declare function compareVersions(versionA: string, versionB: string): number;
17
- /**
18
- * Compares two version strings for sorting purposes in descending order (newest first).
19
- * This is a convenience wrapper around compareVersions for clearer intent.
20
- *
21
- * @param versionA - First version string to compare
22
- * @param versionB - Second version string to compare
23
- * @returns Positive if versionA < versionB, negative if versionA > versionB, zero if equal
24
- *
25
- * @example
26
- * ```typescript
27
- * ['3.1', '3', '10', 'latest', '2.0'].sort(compareVersionsDescending)
28
- * // Returns: ['latest', '10', '3.1', '3', '2.0'] (newest to oldest)
29
- * ```
30
- */
31
- export declare function compareVersionsDescending(versionA: string, versionB: string): number;
32
- //# sourceMappingURL=version-compare.d.ts.map
17
+ //# sourceMappingURL=compare-versions.d.ts.map
@@ -0,0 +1 @@
1
+ function n(e,r){return e.localeCompare(r,void 0,{numeric:!0})}export{n as compareVersions};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/realm",
3
- "version": "0.137.0-next.9",
3
+ "version": "0.137.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,19 +33,20 @@
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.2.0-next.9",
36
+ "@redocly/api-docs": "0.2.0",
37
37
  "@redocly/config": "0.56.0",
38
- "@redocly/openapi-core": "2.51.2",
38
+ "@redocly/openapi-core": "2.53.0",
39
39
  "@redocly/portal-legacy-ui": "0.19.0",
40
- "@redocly/portal-plugin-mock-server": "0.22.0-next.7",
41
- "@redocly/realm-asyncapi-sdk": "0.15.0-next.3",
42
- "@redocly/theme": "0.69.0-next.8",
40
+ "@redocly/portal-plugin-mock-server": "0.22.0",
41
+ "@redocly/realm-asyncapi-sdk": "0.15.0",
42
+ "@redocly/theme": "0.69.0",
43
43
  "@shikijs/transformers": "3.21.0",
44
44
  "@tanstack/react-query": "5.62.3",
45
45
  "@tanstack/react-table": "8.21.3",
46
46
  "@tanstack/react-virtual": "3.13.0",
47
47
  "@wojtekmaj/react-datetimerange-picker": "6.0.0",
48
- "@xmldom/xmldom": "0.9.10",
48
+ "@xmldom/xmldom": "0.9.12",
49
+ "acorn": "8.17.0",
49
50
  "ajv-formats": "^3.0.1",
50
51
  "anser": "^2.3.2",
51
52
  "babel-plugin-styled-components": "2.1.4",
@@ -57,14 +58,14 @@
57
58
  "enquirer": "2.3.6",
58
59
  "esbuild": "0.28.1",
59
60
  "escape-carriage": "^1.3.1",
60
- "fflate": "0.7.4",
61
+ "fflate": "0.7.5",
61
62
  "flexsearch": "0.7.43",
62
63
  "graphql": "16.14.2",
63
- "hono": "4.13.1",
64
+ "hono": "4.13.7",
64
65
  "htmlparser2": "8.0.2",
65
66
  "i18next": "22.4.15",
66
67
  "is-glob": "4.0.3",
67
- "js-yaml": "4.3.1",
68
+ "js-yaml": "4.3.2",
68
69
  "lru-cache": "11.1.0",
69
70
  "minimatch": "10.2.4",
70
71
  "mri": "1.2.0",
@@ -1,9 +0,0 @@
1
- import type { ApiItem, SchemaEntry } from '@redocly/api-docs';
2
- import type { SearchDocument } from '../../../types';
3
- export declare class ApiDocsSearchIndexer {
4
- #private;
5
- constructor(basePath: string, schemaStore?: Record<string, SchemaEntry>, document?: Record<string, unknown>);
6
- addItem(item: ApiItem): void;
7
- getResult(): SearchDocument[];
8
- }
9
- //# sourceMappingURL=search-indexer.d.ts.map
@@ -1 +0,0 @@
1
- import{REDOCLY_TEAMS_RBAC as f}from"@redocly/config";import{extractFullText as w,nodeTypes as h,contentType as A,schemaKind as g}from"@redocly/api-docs";import{toMarkdown as C}from"../../markdown/search/to-markdown.js";const R=10,k=200,I="message payload",P="message headers";function l(u){if(typeof u=="string")return u;const e=Array.isArray(u)?u:[u];return C(e).trim()}function x(u){return u.length>k?`${u.slice(0,k)}\u2026`:u}class L{#a=[];#r;#i;#s;#o;constructor(e,t,n){this.#r=e,this.#i=t,this.#s=n}addItem(e){if(!(!e.link||!e.content))try{switch(e.content.contentType){case A.OVERVIEW:this.#d(e,this.#r);break;case A.GROUP:case A.ITEM:this.#d(e,e.link);break}}catch(t){console.error(`Cannot add item to api-docs search indexer [${e.label}, ${e.link}]:`,t.message)}}#d(e,t){if(!e.content)return;const n=t.startsWith(this.#r+"/")?t.slice(this.#r.length+1):t.split("/").slice(-2).join("/"),r=e.content.children,i=this.#l(r),s=this.#y(r,n),o=e,a={id:t,url:t,title:e.label??"",text:i,path:[],deprecated:e.content.meta?.deprecated,..."httpVerb"in e&&e.httpVerb?{httpMethod:e.httpVerb}:{},..."httpPath"in e&&e.httpPath?{httpPath:e.httpPath}:{},..."badges"in e&&Array.isArray(e.badges)&&e.badges.length?{badges:e.badges}:{},..."isAdditionalOperation"in e&&e.isAdditionalOperation?{isAdditionalOperation:!0}:{},[f]:o[f],...s.length&&{parameters:s}};this.#a.push(a)}#l(e){const t=[],n=r=>{for(const i of r)if(i.nodeType===h.MARKDOC){const s=i;if(this.#h(s.content))continue;const o=w(s.content);o&&t.push(o)}else(i.nodeType===h.CONTAINER||i.nodeType===h.OVERVIEW_SECTION_WRAPPER)&&n(i.children)};return n(e),t.join(" ").trim()}#h(e){let t=!1,n=!1;const r=s=>{s.type==="code"&&s.attributes?.content?t=!0:s.type==="text"&&s.attributes?.content&&(n=!0);for(const o of s.children??[])r(o)},i=Array.isArray(e)?e:[e];for(const s of i)r(s);return t&&!n}#y(e,t){const n={},r=new Set,i=s=>{for(const o of s)if(o.nodeType===h.ITEM){const a=o;if(a[f])continue;this.#m(a,n,t),this.#E(a,n,r,t)}else if(o.nodeType===h.CONTAINER){const a=o;if(a[f])continue;i(a.children)}else o.nodeType===h.OVERVIEW_SECTION_WRAPPER&&i(o.children)};return i(e),Object.values(n)}#m(e,t,n){if(e.parameters?.length)for(const r of e.parameters){if(r[f])continue;const i=this.#A(e.variant),s=this.#O(e.variant),o=r.description?l(r.description):"",a=this.#T(r.schemaId),d={name:r.name,description:o,place:i,mediaType:void 0,type:a,required:r.required??!1,deepLink:this.#c(n,"request",s,void 0,void 0,[r.name]),example:void 0,enum:void 0};t[this.#t(d)]=d}}#t(e){return[...Array.isArray(e.path)?e.path:[],e.name.toString()].join(".")+e.description+e.place}#c(e,t,n,r,i,s){if(!e)return"";const o=s.join("/"),a=[`t=${t}`];return n&&a.push(`in=${n}`),i&&a.push(`c=${i}`),r&&a.push(`ct=${r}`),o&&a.push(`path=${o}`),`/${e}#${e}/${a.join("&")}`.toLowerCase()}#$(e,t){return e?`/${e}#${e}/response&c=${t}`.toLowerCase():""}#S(e,t,n,r){if(!e)return"";let i="messages";t&&(i+=`&m=${t}`),i+=`&t=${n}`;const s=r.join("/");return s&&(i+=`&path=${s}`),`/${e}#${e}/${i}`.toLowerCase()}#O(e){switch(e){case"query":return"query";case"path":return"path";case"headers":return"header";case"cookies":return"cookie";default:return}}#A(e){switch(e){case"query":return"query parameters";case"path":return"path parameters";case"headers":return"header parameters";case"cookies":return"cookie parameters";case"parameters":return"channel parameters";default:return e?`${e} parameters`:"parameters"}}#T(e){const t=this.#i?.[e];if(!t||t.kind!==g.JSON_SCHEMA)return"unknown";const n=t.data,r=this.#u(n);return this.#f(r)}#f(e){return Array.isArray(e.type)?e.type.join(" | "):e.type?e.type:e.properties||e.additionalProperties?"object":e.items?"array":e.enum?"string":"any"}#E(e,t,n,r){const i=this.#P(e);if(e.graphqlSchema&&Array.isArray(e.graphqlSchema)){this.#q(e.graphqlSchema,i,t);return}const s=!!this.#i&&!!this.#s;s&&this.#b(e,i,t,n,r);for(const o of e.responses??[])o[f]||(this.#g(o,t,r),s&&this.#k(o,t,r));if(s)for(const o of e.messages??[])o[f]||this.#I(o,t,r)}#b(e,t,n,r,i){const s=t.startsWith("response");if(e.mediaTypeSchemas){const o=Object.entries(e.mediaTypeSchemas),a=o.find(([,d])=>!d[f]);if(a){const[d,c]=a;c.schemaId&&this.#n(c.schemaId,t,d,o.length>1,s,n,[],r,i)}}else e.schemaId&&this.#n(e.schemaId,t,void 0,!1,s,n,[],r,i)}#g(e,t,n){const r=e.description?l(e.description):"",s=[e.summary?l(e.summary):"",r].filter(Boolean).join(" ").trim();if(!s)return;const o={name:e.code,description:s,place:`response ${e.code}`,mediaType:void 0,type:"unknown",required:!1,deepLink:this.#$(n,e.code),example:void 0,enum:void 0};t[this.#t(o)]=o}#k(e,t,n){const r=`response ${e.code} fields`,i=new Set;if(e.mediaTypeContent){const s=Object.entries(e.mediaTypeContent),o=s.find(([,a])=>!a[f]);if(o){const[a,d]=o;d.schemaId&&this.#n(d.schemaId,r,a,s.length>1,!0,t,[],i,n)}}else e.schemaId&&this.#n(e.schemaId,r,e.mediaType,!1,!0,t,[],i,n)}#I(e,t,n){const r=e.description?l(e.description):"",i=e.summary??"",s={name:e.name,description:(r+i).trim(),place:"message",mediaType:void 0,type:"unknown",required:!1,example:void 0,enum:void 0};t[this.#t(s)]=s,this.#o=e.name;const o=new Set;e.schemaId&&this.#n(e.schemaId,I,e.contentType,!1,!1,t,[],o,n),e.headerSchemaId&&this.#n(e.headerSchemaId,P,void 0,!1,!1,t,[],o,n),this.#o=void 0}#P(e){switch(e.variant){case"body":return"request fields";case"responses":return"response fields";case"graphql-fields":return"fields";case"graphql-args":return"arguments";case"return-type":return"return type fields";default:return e.variant??"fields"}}#q(e,t,n){for(const r of e){const i=r.description?l(r.description):"",s={name:r.name,description:i,place:t,mediaType:void 0,path:[],type:r.type??"unknown",required:!1,example:void 0,enum:void 0};if(n[this.#t(s)]=s,r.args?.length)for(const o of r.args){const a=o.description?l(o.description):"",d={name:o.name,description:a,place:"arguments",mediaType:void 0,path:[r.name],type:o.type??"unknown",required:!1,example:void 0,enum:void 0};n[this.#t(d)]=d}}}#n(e,t,n,r,i,s,o,a,d=""){const c=this.#i?.[e];if(!c||c.kind!==g.JSON_SCHEMA||c[f])return;const p=c.data,y=r?n:void 0;this.#p(p,t,n,y,i,s,o,a,0,d)}#w(e){const t=e.match(/^response (\d+)/);return t?t[1]:void 0}#u(e){if(e.allOf){const t={};for(const n of e.allOf){const r=n.$ref?this.#e(n.$ref):n;if(r){const i=t.properties,s=t.required;Object.assign(t,r),(i||r.properties)&&(t.properties={...i||{},...r.properties||{}}),(s||r.required)&&(t.required=[...s||[],...r.required||[]])}}return delete t.allOf,e.description&&(t.description=e.description),t}if(e.$ref){const t=this.#e(e.$ref);if(t){const n={...t};return e.description&&(n.description=e.description),n}}return e}#e(e){if(!e.startsWith("#/"))return;const t=e.slice(2).split("/");let n=this.#s;for(const r of t){if(n==null||typeof n!="object")return;n=n[r]}return n!=null&&typeof n=="object"?n:void 0}#p(e,t,n,r,i,s,o,a,d,c=""){if(d>R||e[f])return;const p=(y,$,S)=>this.#p(y,t,n,r,i,s,$,a,S,c);if(e.$ref){this.#C(e.$ref,p,o,d,a);return}if(e.allOf){p(this.#R(e,a),o,d);return}if(e.discriminator&&e.properties&&e.oneOf){p({...e,oneOf:void 0,discriminator:void 0},o,d);return}if(e.oneOf||e.anyOf){this.#x(e,p,o,d,a);return}e.properties&&this.#j(e,p,{place:t,mediaType:n,deepLinkContentType:r,isResponse:i,paramsMap:s,path:o,visited:a,depth:d,slug:c}),this.#M(e,p,o,d,a)}#C(e,t,n,r,i){if(i.has(e))return;i.add(e);const s=this.#e(e);s&&t(s,n,r)}#R(e,t){const n={};for(const r of e.allOf??[]){let i=r;if(r.$ref){if(t.has(r.$ref))continue;t.add(r.$ref),i=this.#e(r.$ref)}if(i){const s=n.properties,o=n.required;Object.assign(n,i),(s||i.properties)&&(n.properties={...s||{},...i.properties||{}}),(o||i.required)&&(n.required=[...o||[],...i.required||[]])}}return delete n.allOf,n}#x(e,t,n,r,i){for(const s of e.oneOf||e.anyOf||[]){if(s.$ref){if(i.has(s.$ref))continue;i.add(s.$ref)}const o=s.$ref?this.#e(s.$ref):s;o&&t(o,n,r+1)}}#j(e,t,n){const{isResponse:r,paramsMap:i,path:s,visited:o}=n,a=e.required||[],d=this.#w(n.place),c=r?"response":"request",p=n.place===I?"payload":n.place===P?"headers":void 0,y={requiredList:a,responseCode:d,type:c,asyncSubsection:p,...n};for(const[$,S]of Object.entries(e.properties??{})){if(S[f])continue;const m=this.#D(S,o);if(!m)continue;const q=this.#_(m,o),O=this.#u(m);if(!this.#L(m,O,r))continue;const T=[...s,$],E=this.#V($,m,O,T,y),b=this.#t(E);i[b]==null&&(i[b]=E,q||t(O,T,n.depth+1))}}#D(e,t){if(!e.$ref)return e;if(!t.has(e.$ref))return t.add(e.$ref),this.#e(e.$ref)}#_(e,t){if(!e.allOf)return!1;let n=!1;for(const r of e.allOf)r.$ref?t.has(r.$ref)||(t.add(r.$ref),n=!0):n=!0;return!n}#L(e,t,n){return!(e[f]||t[f]||t.readOnly&&!n||t.writeOnly&&n||e.additionalProperties!==void 0&&!e.properties)}#V(e,t,n,r,i){const s=t.description??n.description,o=s?l(s):"",a=t.example??n.example,d=a!==void 0?x(typeof a=="string"?a:JSON.stringify(a)):void 0,c=Array.isArray(n.enum)&&n.enum.length?n.enum:void 0;return{name:e,description:o,place:i.place,mediaType:i.mediaType,path:i.path,type:this.#f(n),required:i.requiredList.includes(e),deepLink:i.asyncSubsection?this.#S(i.slug,this.#o,i.asyncSubsection,r):this.#c(i.slug,i.type,void 0,i.deepLinkContentType,i.responseCode,r),example:d,enum:c}}#M(e,t,n,r,i){if(!e.items||typeof e.items!="object"||Array.isArray(e.items))return;if(e.items.$ref){if(i.has(e.items.$ref))return;i.add(e.items.$ref)}const s=e.items.$ref?this.#e(e.items.$ref):e.items;s&&t(s,n,r+1)}getResult(){return this.#a}}export{L as ApiDocsSearchIndexer};
@@ -1 +0,0 @@
1
- function r(e,n){return e.localeCompare(n,void 0,{numeric:!0})}function o(e,n){return r(n,e)}export{r as compareVersions,o as compareVersionsDescending};