@redocly/redoc 0.137.0-next.5 → 0.137.0-next.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/api-schemas/otel-traces.d.ts +1359 -0
  3. package/dist/api-schemas/otel-traces.js +1 -0
  4. package/dist/cli/stats/collectors/asyncapi/index.d.ts +3 -0
  5. package/dist/cli/stats/collectors/asyncapi/index.js +1 -0
  6. package/dist/cli/stats/collectors/extension-sampling.d.ts +44 -0
  7. package/dist/cli/stats/collectors/extension-sampling.js +1 -0
  8. package/dist/cli/stats/collectors/openapi/index.js +1 -1
  9. package/dist/cli/stats/collectors/prepare-stats-walk.d.ts +10 -0
  10. package/dist/cli/stats/collectors/prepare-stats-walk.js +1 -0
  11. package/dist/cli/stats/collectors/run-stats-collector.d.ts +24 -0
  12. package/dist/cli/stats/collectors/run-stats-collector.js +1 -0
  13. package/dist/cli/stats/index.js +1 -1
  14. package/dist/client/app/hooks/useMcpData.d.ts +1 -0
  15. package/dist/client/app/hooks/useMcpData.js +1 -1
  16. package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
  17. package/dist/client/providers/hooks.js +1 -1
  18. package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
  19. package/dist/client/templates/api-docs/helpers.d.ts +4 -1
  20. package/dist/client/templates/api-docs/helpers.js +5 -1
  21. package/dist/client/templates/api-docs/template.js +1 -1
  22. package/dist/constants/l10n/langs/ar.js +1 -1
  23. package/dist/constants/l10n/langs/de.js +1 -1
  24. package/dist/constants/l10n/langs/en.js +1 -1
  25. package/dist/constants/l10n/langs/es.js +1 -1
  26. package/dist/constants/l10n/langs/fr.js +1 -1
  27. package/dist/constants/l10n/langs/hi.js +1 -1
  28. package/dist/constants/l10n/langs/it.js +1 -1
  29. package/dist/constants/l10n/langs/ja.js +1 -1
  30. package/dist/constants/l10n/langs/ko.js +1 -1
  31. package/dist/constants/l10n/langs/pl.js +1 -1
  32. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  33. package/dist/constants/l10n/langs/pt.js +1 -1
  34. package/dist/constants/l10n/langs/ru.js +1 -1
  35. package/dist/constants/l10n/langs/uk.js +1 -1
  36. package/dist/constants/l10n/langs/zh.js +1 -1
  37. package/dist/server/config/env-config.d.ts +2 -0
  38. package/dist/server/config/env-schema.d.ts +5 -0
  39. package/dist/server/config/env-schemas/feature-flags.d.ts +4 -0
  40. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  41. package/dist/server/constants/mcp.d.ts +5 -0
  42. package/dist/server/constants/mcp.js +1 -0
  43. package/dist/server/constants/rbac.d.ts +3 -0
  44. package/dist/server/constants/rbac.js +1 -0
  45. package/dist/server/esbuild/esbuild.js +3 -3
  46. package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.js +1 -1
  47. package/dist/server/plugins/api-docs/options.js +1 -1
  48. package/dist/server/plugins/api-docs/search/get-ai-search-documents.js +9 -9
  49. package/dist/server/plugins/api-docs/search/search-indexer.js +1 -1
  50. package/dist/server/plugins/{openapi-docs/is-openapi-doc.d.ts → api-docs/utils/is-api-doc.d.ts} +4 -2
  51. package/dist/server/plugins/api-docs/utils/is-api-doc.js +1 -0
  52. package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.d.ts +1 -1
  53. package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.js +1 -1
  54. package/dist/server/plugins/entitlements/index.js +1 -1
  55. package/dist/server/plugins/l10n/index.js +1 -1
  56. package/dist/server/plugins/lifecycle.js +2 -2
  57. package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
  58. package/dist/server/plugins/markdown/attribute-resolvers/resolve-open-api-ref.js +1 -1
  59. package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +1 -2
  60. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  61. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +4 -4
  62. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +3 -1
  63. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -1
  64. package/dist/server/plugins/mcp/codemode/invoke-tool.js +1 -1
  65. package/dist/server/plugins/mcp/codemode/prompts.js +1 -1
  66. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/fetch-shim.d.ts +1 -1
  67. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/fetch-shim.js +9 -3
  68. package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +1 -1
  69. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +1 -1
  70. package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
  71. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  72. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  73. package/dist/server/plugins/mcp/codemode/types.d.ts +1 -0
  74. package/dist/server/plugins/mcp/constants.d.ts +1 -1
  75. package/dist/server/plugins/mcp/constants.js +1 -1
  76. package/dist/server/plugins/mcp/custom-tools/extract-tool-definition.d.ts +13 -0
  77. package/dist/server/plugins/mcp/custom-tools/extract-tool-definition.js +1 -0
  78. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.d.ts +6 -0
  79. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -0
  80. package/dist/server/plugins/mcp/custom-tools/validate-tool-definition.d.ts +3 -0
  81. package/dist/server/plugins/mcp/custom-tools/validate-tool-definition.js +1 -0
  82. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +2 -0
  83. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  84. package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +2 -2
  85. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoints.js +1 -1
  86. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
  87. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
  88. package/dist/server/plugins/mcp/gateway-mcp/callable-apis.d.ts +10 -0
  89. package/dist/server/plugins/mcp/gateway-mcp/callable-apis.js +1 -0
  90. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +3 -2
  91. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -4
  92. package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -1
  93. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.d.ts +2 -1
  94. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.js +1 -1
  95. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
  96. package/dist/server/plugins/mcp/gateway-mcp/fetch/upstream-detail.d.ts +7 -0
  97. package/dist/server/plugins/mcp/gateway-mcp/fetch/upstream-detail.js +1 -0
  98. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.d.ts +1 -9
  99. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -1
  100. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +6 -0
  101. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.js +1 -1
  102. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  103. package/dist/server/plugins/mcp/handlers/errors.d.ts +6 -1
  104. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  105. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
  106. package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -1
  107. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.d.ts +6 -0
  108. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +50 -42
  109. package/dist/server/plugins/mcp/index.d.ts +0 -2
  110. package/dist/server/plugins/mcp/index.js +1 -1
  111. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  112. package/dist/server/plugins/mcp/servers/mcp-server.js +3 -3
  113. package/dist/server/plugins/mcp/types.d.ts +30 -3
  114. package/dist/server/plugins/mcp/utils/available-sandbox-tools.d.ts +4 -0
  115. package/dist/server/plugins/mcp/utils/available-sandbox-tools.js +1 -0
  116. package/dist/server/plugins/mcp/utils/find-gated-tool-names.d.ts +2 -3
  117. package/dist/server/plugins/mcp/utils/find-gated-tool-names.js +1 -1
  118. package/dist/server/plugins/mcp/utils/mcp-client.d.ts +13 -0
  119. package/dist/server/plugins/mcp/utils/mcp-client.js +1 -0
  120. package/dist/server/plugins/mcp/utils/tool-registration.d.ts +17 -0
  121. package/dist/server/plugins/mcp/utils/tool-registration.js +1 -0
  122. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +6 -1
  123. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  124. package/dist/server/plugins/mcp/workers/import-mcp-tool-handlers.d.ts +5 -0
  125. package/dist/server/plugins/mcp/workers/import-mcp-tool-handlers.js +1 -0
  126. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +6 -11
  127. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  128. package/dist/server/plugins/mcp/workers/tool-file-system.d.ts +6 -0
  129. package/dist/server/plugins/mcp/workers/tool-file-system.js +1 -0
  130. package/dist/server/sandbox/sandbox.js +2 -2
  131. package/dist/server/sandbox/utils/returns-from-top-level.d.ts +4 -0
  132. package/dist/server/sandbox/utils/returns-from-top-level.js +1 -0
  133. package/dist/server/store.d.ts +1 -0
  134. package/dist/server/store.js +1 -1
  135. package/dist/server/types/plugins/common.d.ts +3 -1
  136. package/dist/server/utils/rbac/can-anonymous-access-mcp-feature.d.ts +3 -0
  137. package/dist/server/utils/rbac/can-anonymous-access-mcp-feature.js +1 -0
  138. package/dist/server/utils/rbac/should-handle-mcp-auth.d.ts +2 -0
  139. package/dist/server/utils/rbac/should-handle-mcp-auth.js +1 -0
  140. package/dist/server/utils/rbac.js +1 -1
  141. package/dist/server/web-server/auth.js +3 -3
  142. package/dist/server/web-server/handle-api-route-request.js +1 -1
  143. package/dist/server/web-server/routes/error.js +1 -1
  144. package/dist/server/web-server/routes/helpers/resolve-ui-locales-for-idp-login.js +1 -1
  145. package/dist/server/web-server/routes/index.js +1 -1
  146. package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -1
  147. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  148. package/dist/server/web-server/routes/otel/otel.js +1 -1
  149. package/dist/server/web-server/routes/page-data.js +1 -1
  150. package/dist/server/web-server/routes/resolve-route.js +1 -1
  151. package/dist/server/web-server/utils/get-request-origin.d.ts +2 -0
  152. package/dist/server/web-server/utils/get-request-origin.js +1 -1
  153. package/dist/server/web-server/utils/prepare-list-response.d.ts +0 -4
  154. package/dist/server/web-server/utils/prepare-list-response.js +1 -1
  155. package/dist/server/web-server/utils.d.ts +1 -1
  156. package/dist/server/web-server/utils.js +1 -1
  157. package/dist/server/workers/mcp-tool-worker-pool.d.ts +1 -0
  158. package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
  159. package/dist/server/workers/mcp-tool-worker.js +1 -1
  160. package/dist/server/workers/types.d.ts +9 -2
  161. package/dist/server/workers/worker-pool.d.ts +1 -0
  162. package/dist/server/workers/worker-pool.js +1 -1
  163. package/dist/types/global-data.d.ts +1 -0
  164. package/dist/utils/guards/is-plain-object.d.ts +19 -0
  165. package/dist/utils/guards/is-plain-object.js +1 -0
  166. package/package.json +6 -9
  167. package/dist/client/templates/asyncapi-docs/helpers.d.ts +0 -12
  168. package/dist/client/templates/asyncapi-docs/helpers.js +0 -1
  169. package/dist/client/templates/asyncapi-docs/template.d.ts +0 -15
  170. package/dist/client/templates/asyncapi-docs/template.js +0 -9
  171. package/dist/client/templates/openapi-docs/helpers.d.ts +0 -18
  172. package/dist/client/templates/openapi-docs/helpers.js +0 -5
  173. package/dist/client/templates/openapi-docs/template.d.ts +0 -6
  174. package/dist/client/templates/openapi-docs/template.js +0 -14
  175. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.d.ts +0 -9
  176. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.js +0 -1
  177. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.d.ts +0 -2
  178. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.js +0 -1
  179. package/dist/server/esbuild/plugins/api-docs-module-replacer/index.d.ts +0 -6
  180. package/dist/server/esbuild/plugins/api-docs-module-replacer/index.js +0 -1
  181. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-check.d.ts +0 -8
  182. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-check.js +0 -1
  183. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-overlay.d.ts +0 -2
  184. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-overlay.js +0 -1
  185. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-use-license-key.d.ts +0 -5
  186. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-use-license-key.js +0 -1
  187. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/index.d.ts +0 -6
  188. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/index.js +0 -1
  189. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/loadAndBundleSpec.mock.d.ts +0 -3
  190. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/loadAndBundleSpec.mock.js +0 -1
  191. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.d.ts +0 -18
  192. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.js +0 -5
  193. package/dist/server/plugins/asyncapi-docs/get-server-props.d.ts +0 -4
  194. package/dist/server/plugins/asyncapi-docs/get-server-props.js +0 -1
  195. package/dist/server/plugins/asyncapi-docs/get-template-path.d.ts +0 -2
  196. package/dist/server/plugins/asyncapi-docs/get-template-path.js +0 -1
  197. package/dist/server/plugins/asyncapi-docs/index.d.ts +0 -3
  198. package/dist/server/plugins/asyncapi-docs/index.js +0 -1
  199. package/dist/server/plugins/asyncapi-docs/is-asyncapi-doc.d.ts +0 -3
  200. package/dist/server/plugins/asyncapi-docs/is-asyncapi-doc.js +0 -1
  201. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.d.ts +0 -9
  202. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.js +0 -56
  203. package/dist/server/plugins/asyncapi-docs/search/schema-processor.d.ts +0 -8
  204. package/dist/server/plugins/asyncapi-docs/search/schema-processor.js +0 -1
  205. package/dist/server/plugins/asyncapi-docs/search/search-facets.d.ts +0 -8
  206. package/dist/server/plugins/asyncapi-docs/search/search-facets.js +0 -1
  207. package/dist/server/plugins/asyncapi-docs/search/search-resolver.d.ts +0 -5
  208. package/dist/server/plugins/asyncapi-docs/search/search-resolver.js +0 -1
  209. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.d.ts +0 -4
  210. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.js +0 -1
  211. package/dist/server/plugins/graphql-docs/constants.d.ts +0 -2
  212. package/dist/server/plugins/graphql-docs/constants.js +0 -1
  213. package/dist/server/plugins/graphql-docs/get-template-path.d.ts +0 -2
  214. package/dist/server/plugins/graphql-docs/get-template-path.js +0 -1
  215. package/dist/server/plugins/graphql-docs/graphql-doc-loader.d.ts +0 -17
  216. package/dist/server/plugins/graphql-docs/graphql-doc-loader.js +0 -1
  217. package/dist/server/plugins/graphql-docs/index.d.ts +0 -4
  218. package/dist/server/plugins/graphql-docs/index.js +0 -1
  219. package/dist/server/plugins/graphql-docs/is-graphql-doc.d.ts +0 -2
  220. package/dist/server/plugins/graphql-docs/is-graphql-doc.js +0 -1
  221. package/dist/server/plugins/graphql-docs/search/ai/get-ai-search-document.d.ts +0 -17
  222. package/dist/server/plugins/graphql-docs/search/ai/get-ai-search-document.js +0 -4
  223. package/dist/server/plugins/graphql-docs/search/ai/utils.d.ts +0 -14
  224. package/dist/server/plugins/graphql-docs/search/ai/utils.js +0 -36
  225. package/dist/server/plugins/graphql-docs/search/search-facets.d.ts +0 -8
  226. package/dist/server/plugins/graphql-docs/search/search-facets.js +0 -1
  227. package/dist/server/plugins/graphql-docs/search/search-resolver.d.ts +0 -5
  228. package/dist/server/plugins/graphql-docs/search/search-resolver.js +0 -1
  229. package/dist/server/plugins/graphql-docs/spec-download.api.d.ts +0 -3
  230. package/dist/server/plugins/graphql-docs/spec-download.api.js +0 -1
  231. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.d.ts +0 -5
  232. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +0 -4
  233. package/dist/server/plugins/graphql-docs/types.d.ts +0 -40
  234. package/dist/server/plugins/graphql-docs/types.js +0 -0
  235. package/dist/server/plugins/openapi-docs/ai-search-indexer.d.ts +0 -14
  236. package/dist/server/plugins/openapi-docs/ai-search-indexer.js +0 -1
  237. package/dist/server/plugins/openapi-docs/decorators.d.ts +0 -25
  238. package/dist/server/plugins/openapi-docs/decorators.js +0 -1
  239. package/dist/server/plugins/openapi-docs/format-bundle-error.d.ts +0 -6
  240. package/dist/server/plugins/openapi-docs/format-bundle-error.js +0 -5
  241. package/dist/server/plugins/openapi-docs/get-server-props.d.ts +0 -4
  242. package/dist/server/plugins/openapi-docs/get-server-props.js +0 -1
  243. package/dist/server/plugins/openapi-docs/get-template-path.d.ts +0 -2
  244. package/dist/server/plugins/openapi-docs/get-template-path.js +0 -1
  245. package/dist/server/plugins/openapi-docs/index.d.ts +0 -3
  246. package/dist/server/plugins/openapi-docs/index.js +0 -1
  247. package/dist/server/plugins/openapi-docs/is-openapi-doc.js +0 -1
  248. package/dist/server/plugins/openapi-docs/load-definition.d.ts +0 -31
  249. package/dist/server/plugins/openapi-docs/load-definition.js +0 -3
  250. package/dist/server/plugins/openapi-docs/openapi-search-builder.d.ts +0 -24
  251. package/dist/server/plugins/openapi-docs/openapi-search-builder.js +0 -1
  252. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.d.ts +0 -18
  253. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +0 -94
  254. package/dist/server/plugins/openapi-docs/search/search-facets.d.ts +0 -11
  255. package/dist/server/plugins/openapi-docs/search/search-facets.js +0 -1
  256. package/dist/server/plugins/openapi-docs/search/search-resolver.d.ts +0 -5
  257. package/dist/server/plugins/openapi-docs/search/search-resolver.js +0 -1
  258. package/dist/server/plugins/openapi-docs/search-indexer.d.ts +0 -17
  259. package/dist/server/plugins/openapi-docs/search-indexer.js +0 -1
  260. package/dist/server/plugins/openapi-docs/spec-download.api.d.ts +0 -4
  261. package/dist/server/plugins/openapi-docs/spec-download.api.js +0 -1
  262. package/dist/server/plugins/openapi-docs/store-definition-bundles.d.ts +0 -4
  263. package/dist/server/plugins/openapi-docs/store-definition-bundles.js +0 -1
  264. package/dist/server/plugins/openapi-docs/types.d.ts +0 -17
  265. package/dist/server/plugins/openapi-docs/types.js +0 -0
  266. package/dist/server/plugins/openapi-docs/utils.d.ts +0 -25
  267. package/dist/server/plugins/openapi-docs/utils.js +0 -1
  268. /package/dist/client/templates/{openapi-docs → api-docs}/mock-server-config.d.ts +0 -0
  269. /package/dist/client/templates/{openapi-docs → api-docs}/mock-server-config.js +0 -0
  270. /package/dist/{server/plugins → markdoc}/helpers/parse-partials.d.ts +0 -0
  271. /package/dist/{server/plugins → markdoc}/helpers/parse-partials.js +0 -0
  272. /package/dist/server/plugins/{openapi-docs → api-docs/utils}/ast-utils.d.ts +0 -0
  273. /package/dist/server/plugins/{openapi-docs → api-docs/utils}/ast-utils.js +0 -0
@@ -1,18 +1,13 @@
1
- import type { McpMode, McpServerType } from '../types.js';
1
+ import type { McpErrorClass, McpMode, McpServerType } from '../types.js';
2
2
  type McpToolEvent = {
3
3
  tool: string;
4
4
  mode: McpMode;
5
5
  serverType: McpServerType;
6
6
  durationMs: number;
7
+ client?: string;
8
+ clientVersion?: string;
7
9
  };
8
- /**
9
- * Who an error belongs to. `tool_error` — the caller asked for something that does not exist or
10
- * does not validate. `sandbox_error` — the model's own generated code threw in code mode.
11
- * `server_error` — Redocly code failed. Reported explicitly so consumers never have to infer it
12
- * from whether a stack trace happens to be attached.
13
- */
14
- export type McpErrorClass = 'tool_error' | 'sandbox_error' | 'server_error';
15
- export declare function reportMcpToolCalled({ tool, mode, serverType, durationMs, outputLength, }: McpToolEvent & {
10
+ export declare function reportMcpToolCalled({ tool, mode, serverType, durationMs, outputLength, client, clientVersion, }: McpToolEvent & {
16
11
  outputLength: number;
17
12
  }): void;
18
13
  /**
@@ -21,12 +16,12 @@ export declare function reportMcpToolCalled({ tool, mode, serverType, durationMs
21
16
  * identifies the invocation. The result body itself is never recorded — a tool can return
22
17
  * credentials no pattern will recognise — so only its digest lands here.
23
18
  */
24
- export declare function logMcpToolCallAudit({ tool, mode, serverType, args, result, errorClass, }: Omit<McpToolEvent, 'durationMs'> & {
19
+ export declare function logMcpToolCallAudit({ tool, mode, serverType, args, result, errorClass, client, clientVersion, }: Omit<McpToolEvent, 'durationMs'> & {
25
20
  args: unknown;
26
21
  result?: string;
27
22
  errorClass?: McpErrorClass;
28
23
  }): void;
29
- export declare function reportMcpToolError({ tool, mode, serverType, durationMs, message, stack, errorClass, }: McpToolEvent & {
24
+ export declare function reportMcpToolError({ tool, mode, serverType, durationMs, message, stack, errorClass, client, clientVersion, }: McpToolEvent & {
30
25
  message: string;
31
26
  stack?: string;
32
27
  errorClass: McpErrorClass;
@@ -1 +1 @@
1
- import{telemetry as u}from"../../../telemetry/index.js";import{serverAttributes as l}from"../utils/telemetry-attributes.js";import{EXECUTE_TOOL_NAME as c}from"../codemode/constants.js";import{auditInput as d,auditOutputDigest as p,auditSha256 as f,logAuditRecord as g}from"../audit/audit-log.js";function E({tool:r,mode:e,serverType:o,durationMs:s,outputLength:t}){u.sendMcpToolCalledMessage([{...l(o),tool:r,mode:e,output_length:t,duration_ms:s}])}function T({tool:r,mode:e,serverType:o,args:s,result:t,errorClass:n}){if(r===c)return;const i=m(s),a=t===void 0?void 0:p(t);g("Record MCP tool call",{tool:r,mode:e,server_type:o,error_class:n,args_sha256:f(i),args:d(i),result_sha256:a?.sha256,result_bytes:a?.bytes})}function m(r){try{return JSON.stringify(r)??String(r)}catch{return"\xAB[unserializable]\xBB"}}function A({tool:r,mode:e,serverType:o,durationMs:s,message:t,stack:n="",errorClass:i}){u.sendMcpErrorMessage([{...l(o),tool:r,message:t,stack:n,error_class:i,mode:e,duration_ms:s}])}export{T as logMcpToolCallAudit,E as reportMcpToolCalled,A as reportMcpToolError};
1
+ import{telemetry as c}from"../../../telemetry/index.js";import{serverAttributes as d}from"../utils/telemetry-attributes.js";import{EXECUTE_TOOL_NAME as p}from"../codemode/constants.js";import{auditInput as _,auditOutputDigest as f,auditSha256 as g,logAuditRecord as m}from"../audit/audit-log.js";function A({tool:r,mode:t,serverType:o,durationMs:i,outputLength:e,client:s,clientVersion:n}){c.sendMcpToolCalledMessage([{...d(o),tool:r,mode:t,output_length:e,duration_ms:i,client:s,client_version:n}])}function C({tool:r,mode:t,serverType:o,args:i,result:e,errorClass:s,client:n,clientVersion:a}){if(r===p)return;const l=M(i),u=e===void 0?void 0:f(e);m("Record MCP tool call",{tool:r,mode:t,server_type:o,error_class:s,client:n,client_version:a,args_sha256:g(l),args:_(l),result_sha256:u?.sha256,result_bytes:u?.bytes})}function M(r){try{return JSON.stringify(r)??String(r)}catch{return"\xAB[unserializable]\xBB"}}function b({tool:r,mode:t,serverType:o,durationMs:i,message:e,stack:s="",errorClass:n,client:a,clientVersion:l}){c.sendMcpErrorMessage([{...d(o),tool:r,message:e,stack:s,error_class:n,mode:t,duration_ms:i,client:a,client_version:l}])}export{C as logMcpToolCallAudit,A as reportMcpToolCalled,b as reportMcpToolError};
@@ -0,0 +1,6 @@
1
+ import type { McpToolFileSystem } from '@redocly/config';
2
+ import type { McpToolContext } from '../types.js';
3
+ export declare function attachToolFileSystem(context: McpToolContext): McpToolContext & {
4
+ fs: McpToolFileSystem;
5
+ };
6
+ //# sourceMappingURL=tool-file-system.d.ts.map
@@ -0,0 +1 @@
1
+ import{readFile as s,realpath as i}from"node:fs/promises";import{resolve as l,sep as n}from"node:path";function m(r){return{...r,fs:c(r.outdir)}}function c(r){return{async readFile(o){if(!r)throw new Error("Project files are not available in this environment.");const e=await i(r),t=l(e,o.replace(/^\/+/,"")),a=t.startsWith(e+n)?await i(t):t;if(!a.startsWith(e+n))throw new Error(`Invalid file path "${o}".`);return await s(a,"utf8")}}}export{m as attachToolFileSystem};
@@ -1,3 +1,3 @@
1
- import _ from"@jitl/quickjs-singlefile-mjs-release-sync";import{newQuickJSWASMModuleFromVariant as E,newVariant as S}from"quickjs-emscripten-core";import{createExecutionBudget as A}from"./utils/execution-budget.js";import{DEFAULT_MAX_LIFETIME_MS as p,DEFAULT_TIMEOUT_MS as y,INITIAL_TOTAL_MEMORY_BYTES as g,MAX_ALLOCATION_BYTES as w,MAX_RESULT_BYTES as x,MAX_STACK_SIZE_BYTES as I,MAX_TOTAL_MEMORY_BYTES as L,WASM_PAGE_BYTES as d}from"./constants/sandbox.js";let l;function h(){return l??=E(S(_,{wasmMemory:new WebAssembly.Memory({initial:g/d,maximum:L/d})}))}async function k(t,c={}){const{timeoutMs:m=y,maxLifetimeMs:M=p,setupContext:f}=c,e=(await h()).newContext();let n,s,r;try{e.runtime.setMemoryLimit(w),e.runtime.setMaxStackSize(I),n=A(e,m,M),s=f?.(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 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 () => {
2
2
  ${t}
3
- })()`));const i=e.resolvePromise(r);e.runtime.executePendingJobs();const T=await Promise.race([i,n.aborted]),u=e.unwrapResult(T),o=e.dump(u);if(u.dispose(),o===void 0)return{error:"The code returned undefined. Check that a top-level `return` yields a defined value: return the value directly (not `return;` or `return undefined`), read an existing field (a wrong field name is undefined), and do not wrap the logic in a function or IIFE whose return value is discarded."};const a=JSON.stringify(o??null).length;return a>x?{error:`Result is too large (${a} bytes); return less data`}:{result:o}}catch(i){return{error:b(i)}}finally{n?.dispose(),r?.dispose();try{s?.()}catch{}try{e.dispose()}catch{l=void 0}}}function b(t){return t instanceof Error?t.message:String(t)}export{k as runInSandbox};
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};
@@ -0,0 +1,4 @@
1
+ import type { QuickJSContext } from 'quickjs-emscripten-core';
2
+ /** Whether `code` returns from the guest wrapper itself rather than from a nested function. */
3
+ export declare function returnsFromTopLevel(context: QuickJSContext, code: string): boolean;
4
+ //# sourceMappingURL=returns-from-top-level.d.ts.map
@@ -0,0 +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};
@@ -128,6 +128,7 @@ export declare class Store {
128
128
  markGatedMcpTools: (toolNames: string[]) => void;
129
129
  addSkills: (skills: Skill[]) => void;
130
130
  getSkills: () => Skill[];
131
+ removeMcpTools: (names: string[]) => void;
131
132
  addMiddleware: (middleware: MiddlewareDetails) => void;
132
133
  setResourceResponseHeaders: (resourcePath: string, headers: NonNullable<RedoclyConfig['responseHeaders']>[string]) => void;
133
134
  getRouteByFsPath: (relativePath: string) => PageRouteDetails | undefined;
@@ -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 O}from"./constants/common.js";import{isObject as M}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 K}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as x}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"],Me="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:a}){this.#i=t,this.outdir=e,this.serverMode=s,this.serverOutDir=a,F.register({serverOutDir:a,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(r=>{this.#n=r})}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 a of this.listeners.get(e)||new Set)t?a(t,...s):a(...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(([a])=>R[a]!=null?e.canAccessFeature(R[a]):!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:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(e,this.markdocOptions,{actions:this,context:t},a);for(const i of r.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 r.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&&r.partials?.length)for(const i of s.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async 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:a,replacedValues:r}=J(e);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),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 a=h(s.to).toLowerCase();if(!a.endsWith("*")&&$(a,[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 a=JSON.stringify(t),r=s??H(a);return this.#t[e]===r||(this.#t[e]=r,await I(e,a,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,t,s)=>{const a=L(e),r=this.routesSharedData.get(a)||{};r[t]=s,this.routesSharedData.set(a,r),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 a=this.getGlobalConfig(O)||{},r=new Set(s),o=Array.from(s);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)t[i]&&(l[i]=t[i]);return l};addRoute=e=>{const s={...x(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 a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=A(e,g,r.code,a);this.addRouteSharedData(o,t,s)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,t)=>{for(const s of t)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());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())),r=[...(this.config.responseHeaders[e]??[]).filter(o=>!s.has(o.name.toLowerCase())),...t];this.config.responseHeaders[e]=r};getRouteByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.getRouteBySlug(t):void 0};getRouteBySlug=(e,t={})=>{const{followRedirect:s=!0}=t,a=this.getRedirect(e);return s&&a?this.routesBySlug.get(h(a.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(a=>e===g?!K(a.fsPath):a.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 a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},r=await e.getStaticData?.(e,a)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...e.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified: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,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[s].entries());e.push([s,r]);break;case"object":s==="config"&&e.push([s,await this.getConfigWithEnvPlaceholders()]),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[r,o]of Object.entries(v))switch(o){case"map":s[r]=new Map(e[r]);break;case"object":if(r==="config"){s.setGlobalConfig(e[r]);break}s[r]=e[r];break;default:throw new Error("Invalid format")}s.config[m]=Q(s.config[m]||{});const a=e[E];return a&&_("PLAN_GATES",a),s}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const t in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[t],a=t.split(":"),r=a.pop(),{error:o,value:l}=y(e,a);if(o||!M(l)&&!Array.isArray(l)){await S.panicOnBuild(`Failed to replace env var with env name for ${t}`);continue}l[r]=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,Me as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
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":s==="config"&&e.push([s,await this.getConfigWithEnvPlaceholders()]),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};
@@ -123,14 +123,15 @@ export type ApiRoute = RouteDetails & {
123
123
  };
124
124
  export type McpToolSchema = {
125
125
  name: string;
126
+ title?: string;
126
127
  description: string;
127
128
  schema: Record<string, unknown>;
128
129
  outputSchema?: Record<string, unknown>;
129
130
  annotations?: ToolAnnotations;
131
+ hasAvailabilityGate?: boolean;
130
132
  };
131
133
  export type McpToolRegistration = McpToolSchema & {
132
134
  importPath: string;
133
- hasAvailabilityGate?: boolean;
134
135
  };
135
136
  export type MiddlewareDetails = {
136
137
  id: string;
@@ -163,6 +164,7 @@ export type ProcessContentActions = {
163
164
  addApiRoute: (route: ApiRoute) => void;
164
165
  addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
165
166
  getMcpTools: () => McpToolRegistration[];
167
+ removeMcpTools: (names: string[]) => void;
166
168
  createRequestHandler: (id: string, importPath: string) => void;
167
169
  clearRequestHandlersByPrefix: (prefix: string) => void;
168
170
  addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
@@ -0,0 +1,3 @@
1
+ import type { RbacConfig } from '@redocly/config';
2
+ export declare function canAnonymousAccessMcpFeature(rbacConfig: RbacConfig, requiresLogin: boolean): boolean;
3
+ //# sourceMappingURL=can-anonymous-access-mcp-feature.d.ts.map
@@ -0,0 +1 @@
1
+ import{RbacFeatures as o}from"../../../constants/common.js";import{ANONYMOUS_AUTH_DETAILS as c}from"../../constants/rbac.js";import{canAccessFeature as t}from"../rbac.js";function s(r,e){return t(o.MCP,c,r,e)}export{s as canAnonymousAccessMcpFeature};
@@ -0,0 +1,2 @@
1
+ export declare function shouldHandleMcpAuth(requiresLogin: boolean, rbacConfig?: Record<string, unknown>): boolean;
2
+ //# sourceMappingURL=should-handle-mcp-auth.d.ts.map
@@ -0,0 +1 @@
1
+ import{DEFAULT_ANONYMOUS_VISITOR_TEAM as s,RBAC_ALL_OTHER_TEAMS as u,RbacFeatures as a}from"../../../constants/common.js";function r(e){return!e||typeof e!="object"||Object.keys(e).length===0?!1:!(e[s]&&e[s]!=="none"||e[u]&&e[u]!=="none")}function c(e,t){if(!t||Object.keys(t).length===0)return e;const n=t.content;if(n&&Object.keys(n).length>0&&Object.values(n).some(r))return!0;const o=t.teamFoldersBaseRoles;if(r(o))return!0;const f=t.features;return r(f?.[a.MCP])?!0:e}export{c as shouldHandleMcpAuth};
@@ -1 +1 @@
1
- import y from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as _,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{ServerRoutes as k}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as x,PUBLIC_RBAC_SCOPE_ITEM as R,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as w}from"../constants/common.js";import{removeTrailingSlash as B}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as b}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as M}from"../../utils/path/parse-path-versions.js";import{reporter as U}from"../tools/notifiers/reporter.js";import{bold as W}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as $}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as v}from"../../utils/guards/is-truthy.js";import{canExpandConfig as Y,expandRbacConfig as z,getTeamFolderDefaults as K,parseTeamFoldersTemplate as H,parseTeamNameTemplate as G}from"./rbac-expand.js";import{getUserParamsFromCookies as V}from"../web-server/auth.js";import{getDeeperGlobPattern as J}from"./globs.js";import{EntitlementsProvider as Q}from"../entitlements/entitlements-provider.js";const C=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],X=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Pt(t,e){const r=C.indexOf(t.toUpperCase()),n=C.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return R;const r=t.content,{slug:n,fsPath:s}=e;if(!n&&!s)return R;const o=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const g=`fsPath:${a}`,S=E[g]??P(b(a));return E[g]=S,!!(n&&p(n))||!!(s&&S(s))};if(tt(n||s||"")&&Object.keys(r).filter(p=>o(p)).length===0)return r[L]||R;const f=Object.keys(r).filter(a=>o(a));if(f.length==0)return R;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=J(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,s=[];for(const o of n)t[o]?s.push(t[o]):t[l]&&o!==r&&s.push(t[l]);return s.some(o=>o.toLowerCase()!=="none")}function xt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const s=r.features?.[t];return s?F(s,e.teams):!0}function Dt(t,e){return O(t,{isAuthenticated:!1,teams:[x]},e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(k).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||t.slug==="/mcp"&&Q.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const s=z(r,e.teams||[]),o=t[_]||T(s,t[A]||{});return Object.keys(o||{}).length===0?!1:Object.keys(o).length===1&&o[l]&&o[l].toLowerCase()!=="none"?!0:F(o,e?.teams||[],e?.email)}function gt(t,e,r,n){if(!t.startsWith(I)&&!t.startsWith(j))return!0;const s=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${j}/`),""),c=s==="."?"":s,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function St(t,e,r,n,s){if(!t.startsWith(w))return!0;const o=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!o)return!0;const c=n[o];if(!c)return!0;const{base:i,ext:f}=y.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:y.posix.join(d,`${u}.${h}`)},slug:t};return O(p,s,e,r)}async function _t(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:s,federatedIdToken:o,...c}=await V(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==x):f=[x],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const s=[];for(const o of t){const c=N(o,e,r,n);c!==void 0&&s.push(c)}return s}if(typeof t=="object"){if(!O(t,e,r,n))return;let s=!1;const o={};for(const c in t){if(c===_||c===A)continue;if(X.has(c)){o[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){s=!0;continue}i!==void 0&&(o[c]=i),c==="paths"&&Z(i)&&q(i)}return s?void 0:o}return t}function Lt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function jt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([o,c])=>o===L?[[o,c]]:[[o,c],...t.localeFolders.map(i=>[o.startsWith("/")?`/${i.toLocaleLowerCase()}${o}`:y.posix.join(t.localizationFolder,i,o),c])]),s=Object.fromEntries(n);return{...e,content:s}}async function It(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:s})=>{const{versionFolderPath:o}=M(s)||{},c=y.dirname(s);return o?[o,c]:c}));for(const s of n)r[$(s)]=s;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function Z(t){return m(t)&&Object.keys(t).length>0}function q(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function tt(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const et=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ct=async t=>{if(t){if(Object.keys(t).length===0)return{};if(et(t))return rt(t);await U.panicOnContentError(`You are using an incorrect format of ${W("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},rt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const s=B(n);r[s]=e.content[n]}e.content=r}return e};function Ft(t,e){const r=t.fsPath,n=t.slug,s=[];if(Y(e)&&(r||n)){const o=[r,n].filter(v),c=H(e,o);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];s.push(...i);const f=T({content:{...K(e),...e.content}},t);s.push(...D(f))}else{const i=T(e,t);s.push(...D(i))}}else{const o=T(e,t);s.push(...D(o))}return nt(e,s)}function D(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,s]of Object.entries({...r,...t}))s.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function nt(t,e){return e.map(n=>G(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{C as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,jt as applyL10nToRbacConfig,St as canAccessAsset,xt as canAccessFeature,O as canAccessResource,gt as canDownloadApiDefinition,nt as expandTeamsForRead,D as extractTeamsFromScopeItems,N as filterDataByAccessDeep,_t as getAuthDetailsFromCookies,Pt as getHigherRole,Ft as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,et as isRbacConfigValid,Dt as isResourcePubliclyAccessible,rt as normalizeRbacConfig,Ct as parseRbacConfig,Lt as parseTeamClaimToArray,It as resolveDirectoryHashes};
1
+ import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as g,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as w}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as B}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as S,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as M}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as U}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as b}from"../constants/rbac.js";import{removeTrailingSlash as W}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const I=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Ct(t,e){const r=I.indexOf(t.toUpperCase()),n=I.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const _=`fsPath:${a}`,D=E[_]??P($(a));return E[_]=D,!!(n&&p(n))||!!(o&&D(o))};if(ot(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[L]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function jt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?F(o,e.teams):!0}function It(t,e){return O(t,b,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(B).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||(t.slug===k||t.slug===w||t.slug===U)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[g]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:F(s,e?.teams||[],e?.email)}function Ft(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(C))return!0;const o=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${C}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function Nt(t,e,r,n,o){if(!t.startsWith(M))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function kt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==S):f=[S],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=N(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===g||c===A)continue;if(et.has(c)){s[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&rt(i)&&nt(i)}return o?void 0:s}return t}function wt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Bt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===L?[[s,c]]:[[s,c],...t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c])]),o=Object.fromEntries(n);return{...e,content:o}}async function Mt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function rt(t){return m(t)&&Object.keys(t).length>0}function nt(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function ot(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const st=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ut=async t=>{if(t){if(Object.keys(t).length===0)return{};if(st(t))return ct(t);await Y.panicOnContentError(`You are using an incorrect format of ${z("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},ct=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=W(n);r[o]=e.content[n]}e.content=r}return e};function bt(t,e){const r=t.fsPath,n=t.slug,o=[];if(G(e)&&(r||n)){const s=[r,n].filter(K),c=Q(e,s);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i);const f=T({content:{...J(e),...e.content}},t);o.push(...x(f))}else{const i=T(e,t);o.push(...x(i))}}else{const s=T(e,t);o.push(...x(s))}return it(e,o)}function x(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function it(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{I as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Bt as applyL10nToRbacConfig,Nt as canAccessAsset,jt as canAccessFeature,O as canAccessResource,Ft as canDownloadApiDefinition,it as expandTeamsForRead,x as extractTeamsFromScopeItems,N as filterDataByAccessDeep,kt as getAuthDetailsFromCookies,Ct as getHigherRole,bt as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,st as isRbacConfigValid,It as isResourcePubliclyAccessible,ct as normalizeRbacConfig,Ut as parseRbacConfig,wt as parseTeamClaimToArray,Mt as resolveDirectoryHashes};
@@ -1,12 +1,12 @@
1
- import"../node-crypto-polyfill.js";import{DOMParser as M}from"@xmldom/xmldom";import{SignedXml as Y}from"xml-crypto";import G from"xpath";import{deflateSync as Q,inflateSync as X}from"fflate";import{createHash as Z}from"crypto";import{ulid as ee}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as P}from"@redocly/config";import{AUTH_URL as te,JWT_SECRET_KEY as y}from"../constants/common.js";import{envConfig as ne}from"../config/env-config.js";import{decryptClaimValue as re}from"../utils/crypto/decrypt-claim-value.js";import{getPathPrefix as oe,withPathPrefix as se}from"@redocly/theme/core/utils";import{ServerRoutes as b}from"../../constants/api.js";import{AuthCookieNames as A,DEFAULT_AUTHENTICATED_TEAM as ae,REQUIRED_OIDC_SCOPES as v}from"../../constants/common.js";import{appendQueryParams as ie}from"../../utils/url/append-query-params.js";import{parsePreviewUrl as N}from"../../utils/url/parse-preview-url.js";import{logger as ce}from"../tools/notifiers/logger.js";import{randomString as ue}from"../utils/crypto/random-string.js";import{randomUUID as U}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as h,JwtTokenExpired as de}from"./jwt/types.js";import*as d from"./jwt/jwt.js";import{parseTeamClaimToArray as le}from"../utils/index.js";import{arrayBufferToBase64 as me,decodeBase64 as j,encodeBase64URL as pe,urlSafeBase64 as V}from"./jwt/encode.js";import{formatSamlCertificate as fe}from"./utils/format-saml-certificate.js";function $(e){return e?.type===u.OIDC}function he(e){return e?.type===u.SAML2}async function rt(e,t){if($(t))return ye(e,t);if(he(t))return we(e,t)}async function ye(e,t){const n=await q(e,t),r=new Set((t.scopes||[]).concat(v)),o=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:n.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(r).join(" "),extraParams:o,pkce:t.pkce}}function we(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}function B(e){return Array.from(new Set((e.scopes||[]).concat(v))).join(" ")}async function H(e,t,n){return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:t.clientId,...t.clientSecret?{client_secret:t.clientSecret}:{},...n}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(r=>r.json())}async function ot(e,t,n,r,o={}){return await H(e,r,{scope:B(r),code:t,redirect_uri:F(n),grant_type:"authorization_code",...o})}async function st(e,t,n){return await H(e,n,{scope:B(n),grant_type:"refresh_token",refresh_token:t})}function Se(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:s,idpId:a,pkce:l},p,x,f){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),w=f?.redirectUriOverride??`${e}${se(b.OIDC_CALLBACK)}`,g={state:U(),idpId:a,redirectUri:w,redirectTo:p,branch:f?.branchOverride??_e(e),inviteCode:x,source:f?.sourceOverride??"portal",uiLocales:f?.uiLocales},S={};if(l){const m=V(ue(50)),k=V(Z("sha256").update(m).digest("base64")),I="S256";i.searchParams.append("code_challenge",k),i.searchParams.append("code_challenge_method",I),S.code_verifier={value:m,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:oe()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",F(w)),i.searchParams.append("state",pe(JSON.stringify(g))),f?.uiLocales&&i.searchParams.append("ui_locales",f.uiLocales);for(const m in s)s[m]!==void 0&&i.searchParams.append(m,s[m]);return{loginUrl:i.toString(),cookies:S}}function at(e,t,n,r){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n),o.toString()}async function it(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return d.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpId?{idp_id:e.idpId}:{},...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},y,h.HS256)}async function ct(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!t.client_id||!t.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof t.exp=="number"&&Date.now()>=t.exp*1e3)throw new Error("Authorization code expired");return t}async function ut(e){const t=Math.floor(Date.now()/1e3);return d.sign({type:"mcp_refresh_token",client_id:e.clientId,...e.idpId?{idp_id:e.idpId}:{},claims:e.claims,...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},session_exp:e.sessionExp,iat:t,exp:e.sessionExp},y,h.HS256)}async function dt(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_refresh_token")throw new Error("Invalid refresh token type");if(!t.client_id||typeof t.claims!="object"||t.claims===null)throw new Error("Refresh token missing required claims");if(typeof t.session_exp!="number")throw new Error("Refresh token missing session expiry");return t}function lt(e){const t=e||ee(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function F(e){const t=N(e);if(!t)return e;const n=Ae(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,z(e,t);const r=W(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,z(e,t)):e}function _e(e){const t=N(e);if(t)return W(t.hostname)?.previewBranch}function z(e,t){return e.replace(/^https?:\/\/[^/?#]+/i,`${t.protocol}//${t.host}`)}function W(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const s=n.slice(0,o),a=n.slice(o+2);return!s||!a||a.includes(".")?null:{projectSlug:s,previewBranch:a,after:r}}function Ae(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const s=t===-1?"":e.slice(t);return{previewBranch:o,after:s}}function xe(e){return e.type===u.OIDC}function ge(e){return e.type===u.SAML2}function mt(e,t,n,r,o){return xe(e)?Se(t,e,n,r,{uiLocales:o}):ge(e)?ke(t,e,n,r,o):{}}function ke(e,t,n,r,o){const a=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
1
+ import"../node-crypto-polyfill.js";import{DOMParser as M}from"@xmldom/xmldom";import{SignedXml as Y}from"xml-crypto";import G from"xpath";import{deflateSync as Q,inflateSync as X}from"fflate";import{createHash as Z}from"crypto";import{ulid as ee}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as P}from"@redocly/config";import{AUTH_URL as te,JWT_SECRET_KEY as y}from"../constants/common.js";import{envConfig as ne}from"../config/env-config.js";import{decryptClaimValue as re}from"../utils/crypto/decrypt-claim-value.js";import{getPathPrefix as oe,withPathPrefix as se}from"@redocly/theme/core/utils";import{ServerRoutes as v}from"../../constants/api.js";import{AuthCookieNames as A,DEFAULT_AUTHENTICATED_TEAM as ae,REQUIRED_OIDC_SCOPES as N}from"../../constants/common.js";import{appendQueryParams as ie}from"../../utils/url/append-query-params.js";import{parsePreviewUrl as b}from"../../utils/url/parse-preview-url.js";import{logger as ce}from"../tools/notifiers/logger.js";import{randomString as ue}from"../utils/crypto/random-string.js";import{randomUUID as U}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as h,JwtTokenExpired as de}from"./jwt/types.js";import*as d from"./jwt/jwt.js";import{parseTeamClaimToArray as le}from"../utils/index.js";import{arrayBufferToBase64 as me,decodeBase64 as j,encodeBase64URL as pe,urlSafeBase64 as V}from"./jwt/encode.js";import{formatSamlCertificate as fe}from"./utils/format-saml-certificate.js";function $(e){return e?.type===u.OIDC}function he(e){return e?.type===u.SAML2}async function rt(e,t){if($(t))return ye(e,t);if(he(t))return we(e,t)}async function ye(e,t){const n=await q(e,t),r=new Set((t.scopes||[]).concat(N)),o=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:n.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(r).join(" "),extraParams:o,pkce:t.pkce}}function we(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}function B(e){return Array.from(new Set((e.scopes||[]).concat(N))).join(" ")}async function H(e,t,n){return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:t.clientId,...t.clientSecret?{client_secret:t.clientSecret}:{},...n}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(r=>r.json())}async function ot(e,t,n,r,o={}){return await H(e,r,{scope:B(r),code:t,redirect_uri:F(n),grant_type:"authorization_code",...o})}async function st(e,t,n){return await H(e,n,{scope:B(n),grant_type:"refresh_token",refresh_token:t})}function Se(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:s,idpId:a,pkce:l},p,x,f){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),w=f?.redirectUriOverride??`${e}${se(v.OIDC_CALLBACK)}`,g={state:U(),idpId:a,redirectUri:w,redirectTo:p,branch:f?.branchOverride??_e(e),inviteCode:x,source:f?.sourceOverride??"portal",uiLocales:f?.uiLocales},S={};if(l){const m=V(ue(50)),k=V(Z("sha256").update(m).digest("base64")),I="S256";i.searchParams.append("code_challenge",k),i.searchParams.append("code_challenge_method",I),S.code_verifier={value:m,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:oe()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",F(w)),i.searchParams.append("state",pe(JSON.stringify(g))),f?.uiLocales&&i.searchParams.append("ui_locales",f.uiLocales);for(const m in s)s[m]!==void 0&&i.searchParams.append(m,s[m]);return{loginUrl:i.toString(),cookies:S}}function at(e,t,n,r){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n),o.toString()}async function it(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return d.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpId?{idp_id:e.idpId}:{},...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},y,h.HS256)}async function ct(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!t.client_id||!t.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof t.exp=="number"&&Date.now()>=t.exp*1e3)throw new Error("Authorization code expired");return t}async function ut(e){const t=Math.floor(Date.now()/1e3);return d.sign({type:"mcp_refresh_token",client_id:e.clientId,...e.idpId?{idp_id:e.idpId}:{},claims:e.claims,...e.idpAccessTokenEnc?{idp_access_token_enc:e.idpAccessTokenEnc}:{},...e.idpRefreshTokenEnc?{idp_refresh_token_enc:e.idpRefreshTokenEnc}:{},session_exp:e.sessionExp,iat:t,exp:e.sessionExp},y,h.HS256)}async function dt(e){await d.verify(e,y,h.HS256);const{payload:t}=d.decode(e);if(t.type!=="mcp_refresh_token")throw new Error("Invalid refresh token type");if(!t.client_id||typeof t.claims!="object"||t.claims===null)throw new Error("Refresh token missing required claims");if(typeof t.session_exp!="number")throw new Error("Refresh token missing session expiry");return t}function lt(e){const t=e||ee(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function F(e){const t=b(e);if(!t)return e;const n=Ae(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,z(e,t);const r=W(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,z(e,t)):e}function _e(e){const t=b(e);if(t)return W(t.hostname)?.previewBranch}function z(e,t){return e.replace(/^https?:\/\/[^/?#]+/i,`${t.protocol}//${t.host}`)}function W(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const s=n.slice(0,o),a=n.slice(o+2);return!s||!a||a.includes(".")?null:{projectSlug:s,previewBranch:a,after:r}}function Ae(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const s=t===-1?"":e.slice(t);return{previewBranch:o,after:s}}function xe(e){return e.type===u.OIDC}function ge(e){return e.type===u.SAML2}function mt(e,t,n,r,o){return xe(e)?Se(t,e,n,r,{uiLocales:o}):ge(e)?ke(t,e,n,r,o):{}}function ke(e,t,n,r,o){const a=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
2
2
  xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
3
3
  Version="2.0"
4
4
  ID="_${U()}"
5
5
  IssueInstant="${new Date().toISOString()}"
6
- AssertionConsumerServiceURL="${e}${b.SAML_CALLBACK}"
6
+ AssertionConsumerServiceURL="${e}${v.SAML_CALLBACK}"
7
7
  AttributeConsumingServiceIndex="0">
8
8
  <saml:Issuer>${t.entityId}</saml:Issuer>
9
9
  <samlp:NameIDPolicy
10
10
  AllowCreate="true"
11
11
  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
12
- </samlp:AuthnRequest>`,l=Ie(a);return{loginUrl:ie(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function Ie(e){return me(Q(new TextEncoder().encode(e)).buffer)}function pt(e){const t=j(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=X(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function ft(e){try{return JSON.parse(j(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function ht(e){const t=new M().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,s=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",a=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=a&&a.nodeValue||void 0,p=c(t,"//*[local-name(.)='Audience']/text()")[0],x=p&&p.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",w=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],g=w&&w.nodeValue||"",S=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],m=S&&S.nodeValue||"",k=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],I=Te(k),C={},R=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(R.length)for(const L of R){const O=c(L,"./@Name")[0];if(O.nodeValue){const D=c(L,"./*[local-name(.)='AttributeValue']/text()")[0];D?.nodeValue&&(C[O.nodeValue]=D.nodeValue)}}return{uid:g,success:r,expiresAt:I,issuerId:l,entityId:x,attrs:C,cert:i,nameFormat:m,destination:s}}function Te(e){const t=typeof e?.nodeValue=="string"&&T(Date.parse(e.nodeValue)),n=T(Date.now()),r=T(Date.now()+720*60*1e3);return t?t>n&&t<r?r:t:n}function T(e){return Math.floor(e/1e3)}const E={},_={jwks:{}};async function q(e,t){if(!E[e]){const n=t.configurationUrl?await J(t.configurationUrl):t.configuration;E[e]=Ee()?Re(n):n}return E[e]}function Ee(){const e=ne.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}const Ce=["authorization_endpoint","end_session_endpoint"];function Re(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){if(Ce.includes(String(n)))continue;const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Le(e){for(const t of Object.keys(e)){const n=e[t];if(!$(n))continue;const r=await q(t,n);if(r.jwks_uri){const o=await J(r.jwks_uri);for(const s of o.keys)_.jwks[s.kid]={...s,idpId:t}}}}async function J(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function yt(e){return fetch(`${te}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function wt(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com","cba.au.redocly.com"].some(r=>Oe(t.hostname,r))}function Oe(e,t){return e===t||e.endsWith(`.${t}`)}async function St(e,t){const n=new M().parseFromString(e,"application/xml"),r=c(n,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!r)throw new Error("Cannot find Signature in the SAML response");const o=fe(t),s=new Y({publicCert:o});s.loadSignature(r);try{return s.checkSignature(e)}catch{return!1}}function _t(e,t,n,r){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=n["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const s=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],a=s?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(a?s:void 0),o=o?.toLowerCase(),{sub:e,given_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:n["http://schemas.microsoft.com/identity/claims/displayname"]||s,email:o,email_verified:!0,teams:r?le(n[r]):[]}}function K(e,t={}){return e.map(n=>t[n]||n)}async function At(e,t){if(!t)return{};const n=t[A.AUTHORIZATION];if(!n)return{};try{const r=d.decode(n);if(r.header.alg===h.RS256){_.jwks[r.header.kid]===void 0&&await Le(e);const p=_.jwks[r.header.kid];if(!p)return _.jwks[r.header.kid]=null,{};await d.verify(n,p,h.RS256)}else await d.verify(n,y,h.HS256);const o=r.payload.idpId||_.jwks[r.header.kid]?.idpId,s=e[o]||{},a=Pe(s),l=Me(s);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...K(r.payload.teams||[],l),..."defaultTeams"in s&&s.defaultTeams||[],...K("teamsClaimName"in s&&r.payload[a||""]||[],l),ae])),name:De(r.payload),isAuthenticated:!0,idpAccessToken:re(r.payload.idp_access_token,y)||t[A.IDP_ACCESS_TOKEN],federatedAccessToken:t[A.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[A.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof de||ce.error("Malformed JWT token: %s",r.message)}return{}}function De(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function Me(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Pe(e){switch(e.type){case u.SAML2:return e.teamsAttributeName??P;case u.OIDC:return e.teamsClaimName;default:return P}}function c(e,t){return G.select(t,e)||[]}export{mt as buildLoginUrl,Se as buildOidcLoginUrl,at as buildOidcLogoutUrl,ke as buildSAML2LoginUrl,it as createMcpAuthorizationCode,ut as createMcpRefreshToken,lt as createMcpSessionResource,pt as decodeSamlResponse,Le as discoverJwks,Ie as encodeSAML2,_t as extractUserClaims,rt as getAuthProviderLoginParams,ye as getOidcLoginParams,q as getOidcMetadata,yt as getRedoclyTokenPayload,we as getSaml2LoginParams,At as getUserParamsFromCookies,De as getUsernameFromPayload,$ as isOidcProviderConfig,wt as isRedoclySso,he as isSaml2ProviderConfig,ot as oidcExchangeCodeForToken,_ as oidcJwksCache,E as oidcMetadataCache,st as oidcRefreshTokenGrant,ft as parseOidcState,_e as parsePreviewBranch,ht as parseSamlResponse,F as rewritePreviewAuthRedirectUri,ct as verifyMcpAuthorizationCode,dt as verifyMcpRefreshToken,St as verifySAMLResponse};
12
+ </samlp:AuthnRequest>`,l=Ie(a);return{loginUrl:ie(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function Ie(e){return me(Q(new TextEncoder().encode(e)).buffer)}function pt(e){const t=j(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=X(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function ft(e){try{return JSON.parse(j(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function ht(e){const t=new M().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,s=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",a=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=a&&a.nodeValue||void 0,p=c(t,"//*[local-name(.)='Audience']/text()")[0],x=p&&p.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",w=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],g=w&&w.nodeValue||"",S=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],m=S&&S.nodeValue||"",k=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],I=Te(k),C={},R=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(R.length)for(const L of R){const O=c(L,"./@Name")[0];if(O.nodeValue){const D=c(L,"./*[local-name(.)='AttributeValue']/text()")[0];D?.nodeValue&&(C[O.nodeValue]=D.nodeValue)}}return{uid:g,success:r,expiresAt:I,issuerId:l,entityId:x,attrs:C,cert:i,nameFormat:m,destination:s}}function Te(e){const t=typeof e?.nodeValue=="string"&&T(Date.parse(e.nodeValue)),n=T(Date.now()),r=T(Date.now()+720*60*1e3);return t?t>n&&t<r?r:t:n}function T(e){return Math.floor(e/1e3)}const E={},_={jwks:{}};async function q(e,t){if(!E[e]){const n=t.configurationUrl?await J(t.configurationUrl):t.configuration;E[e]=Ee()?Re(n):n}return E[e]}function Ee(){const e=ne.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}const Ce=["authorization_endpoint","end_session_endpoint"];function Re(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){if(Ce.includes(String(n)))continue;const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Le(e){for(const t of Object.keys(e)){const n=e[t];if(!$(n))continue;const r=await q(t,n);if(r.jwks_uri){const o=await J(r.jwks_uri);for(const s of o.keys)_.jwks[s.kid]={...s,idpId:t}}}}async function J(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function yt(e){return fetch(`${te}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function wt(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com"].some(r=>Oe(t.hostname,r))}function Oe(e,t){return e===t||e.endsWith(`.${t}`)}async function St(e,t){const n=new M().parseFromString(e,"application/xml"),r=c(n,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!r)throw new Error("Cannot find Signature in the SAML response");const o=fe(t),s=new Y({publicCert:o});s.loadSignature(r);try{return s.checkSignature(e)}catch{return!1}}function _t(e,t,n,r){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=n["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const s=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],a=s?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(a?s:void 0),o=o?.toLowerCase(),{sub:e,given_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:n["http://schemas.microsoft.com/identity/claims/displayname"]||s,email:o,email_verified:!0,teams:r?le(n[r]):[]}}function K(e,t={}){return e.map(n=>t[n]||n)}async function At(e,t){if(!t)return{};const n=t[A.AUTHORIZATION];if(!n)return{};try{const r=d.decode(n);if(r.header.alg===h.RS256){_.jwks[r.header.kid]===void 0&&await Le(e);const p=_.jwks[r.header.kid];if(!p)return _.jwks[r.header.kid]=null,{};await d.verify(n,p,h.RS256)}else await d.verify(n,y,h.HS256);const o=r.payload.idpId||_.jwks[r.header.kid]?.idpId,s=e[o]||{},a=Pe(s),l=Me(s);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...K(r.payload.teams||[],l),..."defaultTeams"in s&&s.defaultTeams||[],...K("teamsClaimName"in s&&r.payload[a||""]||[],l),ae])),name:De(r.payload),isAuthenticated:!0,idpAccessToken:re(r.payload.idp_access_token,y)||t[A.IDP_ACCESS_TOKEN],federatedAccessToken:t[A.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[A.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof de||ce.error("Malformed JWT token: %s",r.message)}return{}}function De(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function Me(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Pe(e){switch(e.type){case u.SAML2:return e.teamsAttributeName??P;case u.OIDC:return e.teamsClaimName;default:return P}}function c(e,t){return G.select(t,e)||[]}export{mt as buildLoginUrl,Se as buildOidcLoginUrl,at as buildOidcLogoutUrl,ke as buildSAML2LoginUrl,it as createMcpAuthorizationCode,ut as createMcpRefreshToken,lt as createMcpSessionResource,pt as decodeSamlResponse,Le as discoverJwks,Ie as encodeSAML2,_t as extractUserClaims,rt as getAuthProviderLoginParams,ye as getOidcLoginParams,q as getOidcMetadata,yt as getRedoclyTokenPayload,we as getSaml2LoginParams,At as getUserParamsFromCookies,De as getUsernameFromPayload,$ as isOidcProviderConfig,wt as isRedoclySso,he as isSaml2ProviderConfig,ot as oidcExchangeCodeForToken,_ as oidcJwksCache,E as oidcMetadataCache,st as oidcRefreshTokenGrant,ft as parseOidcState,_e as parsePreviewBranch,ht as parseSamlResponse,F as rewritePreviewAuthRedirectUri,ct as verifyMcpAuthorizationCode,dt as verifyMcpRefreshToken,St as verifySAMLResponse};
@@ -1 +1 @@
1
- import{logger as n}from"../tools/notifiers/logger.js";import{envConfig as o}from"../config/env-config.js";import{runApiRoutesWorker as m}from"../api-routes/run-api-routes-worker.js";import{MCP_CREDENTIALS_HANDLER_ID as i,MCP_DOCS_SERVER_HANDLER_ID as u}from"../plugins/mcp/index.js";import{handleMcpRequest as d}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===u||r.requestHandlerId===i?await d(r,s,a):await m(r,s,a);return n.infoTime(e,`API request handled "${new URL(s.req.url).pathname}" with status "${t.status}" and content type "${t.headers?.get("content-type")}"`),t.headers.set("X-Source","REALM_API_FUNCTION"),t}catch(e){return n.error(`[${r.requestHandlerId}] ${e.stack}`),e.name==="RequestBodySizeLimitError"?s.json({message:e.message},{status:413}):e.name==="ResponseSizeLimitError"?s.json({message:e.message},{status:500}):e.name==="MemoryUsageLimitError"?s.json({message:e.message},{status:502}):e.name==="TimeoutExceededError"?s.json({message:e.message},{status:504}):o.isDevelopMode?s.json({message:e.message},{status:500}):s.json({message:"Internal server error"},{status:500})}}export{l as handleApiRouteRequest};
1
+ import{logger as n}from"../tools/notifiers/logger.js";import{envConfig as o}from"../config/env-config.js";import{runApiRoutesWorker as m}from"../api-routes/run-api-routes-worker.js";import{MCP_CREDENTIALS_HANDLER_ID as i,MCP_DOCS_SERVER_HANDLER_ID as u}from"../constants/mcp.js";import{handleMcpRequest as d}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===u||r.requestHandlerId===i?await d(r,s,a):await m(r,s,a);return n.infoTime(e,`API request handled "${new URL(s.req.url).pathname}" with status "${t.status}" and content type "${t.headers?.get("content-type")}"`),t.headers.set("X-Source","REALM_API_FUNCTION"),t}catch(e){return n.error(`[${r.requestHandlerId}] ${e.stack}`),e.name==="RequestBodySizeLimitError"?s.json({message:e.message},{status:413}):e.name==="ResponseSizeLimitError"?s.json({message:e.message},{status:500}):e.name==="MemoryUsageLimitError"?s.json({message:e.message},{status:502}):e.name==="TimeoutExceededError"?s.json({message:e.message},{status:504}):o.isDevelopMode?s.json({message:e.message},{status:500}):s.json({message:"Internal server error"},{status:500})}}export{l as handleApiRouteRequest};
@@ -1 +1 @@
1
- import{context as s,SpanStatusCode as n,trace as a}from"@opentelemetry/api";import{envConfig as o}from"../../config/env-config.js";const c=t=>{const e=a?.getSpan(s.active());return t instanceof Error&&"name"in t&&t.name==="URIError"?(e&&(e.setStatus({code:n.OK}),e.end()),new Response("Malformed URL",{status:400})):t instanceof SyntaxError?(e&&(e.setStatus({code:n.OK}),e.end()),new Response("Invalid JSON",{status:400})):(e&&(e.setStatus({code:n.ERROR,message:t.message}),e.recordException(t),e.end()),o.isDevelopMode&&t?.name==="PageMissingDefaultExportError"?new Response(t.message,{status:200}):new Response("Internal Server Error",{status:500}))};export{c as errorHandler};
1
+ import{context as s,SpanStatusCode as n,trace as a}from"@opentelemetry/api";import{HTTPException as o}from"hono/http-exception";import{envConfig as i}from"../../config/env-config.js";const u=t=>{const e=a?.getSpan(s.active());return t instanceof Error&&"name"in t&&t.name==="URIError"?(e&&(e.setStatus({code:n.OK}),e.end()),new Response("Malformed URL",{status:400})):t instanceof SyntaxError?(e&&(e.setStatus({code:n.OK}),e.end()),new Response("Invalid JSON",{status:400})):t instanceof o&&t.status<500?(e&&(e.setStatus({code:n.OK}),e.end()),t.getResponse()):(e&&(e.setStatus({code:n.ERROR,message:t.message}),e.recordException(t),e.end()),i.isDevelopMode&&t?.name==="PageMissingDefaultExportError"?new Response(t.message,{status:200}):new Response("Internal Server Error",{status:500}))};export{u as errorHandler};
@@ -1 +1 @@
1
- function i(o,n){if(!o?.trim()||!n?.length)return;const e=o.split("/").filter(Boolean)[0];return e?n.find(t=>t.code.toLowerCase()===e.toLowerCase())?.code:void 0}function a(o){const{localePrefixParam:n,l10n:e}=o;return(e?i(n,e.locales):void 0)??e?.defaultLocale}export{a as resolveUiLocalesForIdpLogin};
1
+ import{DEFAULT_LOCALE_PLACEHOLDER as i}from"../../../../constants/common.js";function c(o,n){if(!o?.trim()||!n?.length)return;const e=o.split("/").filter(Boolean)[0];return e?n.find(r=>r.code.toLowerCase()===e.toLowerCase())?.code:void 0}function l(o){const{localePrefixParam:n,l10n:e}=o,r=(e?c(n,e.locales):void 0)??e?.defaultLocale;return r===i?void 0:r}export{l as resolveUiLocalesForIdpLogin};
@@ -1 +1 @@
1
- import{serveStatic as R}from"hono/serve-static";import{withPathPrefix as i,withoutPathPrefix as H}from"@redocly/theme/core/utils";import{ServerRoutes as l}from"../../../constants/api.js";import{PUBLIC_STATIC_FOLDER as c}from"../../constants/common.js";import{envConfig as L}from"../../config/env-config.js";import{authMiddleware as C}from"../middleware/authMiddleware.js";import{ensureSearchData as I}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as g}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as D}from"../../plugins/dev-onboarding/api/routes/index.js";import{installSkillsRoutes as h}from"./skills/skills-routes.js";import{authorizeHandler as P,oidcCallbackHandler as N,logoutHandler as s,postLogoutHandler as w,idpLoginHandler as M,redoclyLoginCallbackHandler as B,samlCallbackHandler as v,redoclyTokenLoginHandler as F,inviteHandler as G}from"./auth.js";import{appDataHandler as U}from"./app-data.js";import{searchFacetsHandler as Y,searchHandler as y}from"./search.js";import{dynamicRouteHandler as K}from"./dynamic-route.js";import{pageDataHandler as k,sharedPageDataHandler as b}from"./page-data.js";import{pathPrefixRedirectHandler as x}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as T,resolvePathHandler as E,resolvePathsHandler as V,resolveSlugHandler as _}from"./resolve-route.js";import{feedbackHandler as q}from"./feedback.js";import{loggerMiddleware as X}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as $}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as j}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as z}from"./otel/otel.js";import{healthCheckHandler as W}from"./health.js";import{askAiHandler as Z,aiAssistantEscalationsHandler as u,aiAssistantFeedbackHandler as J,AI_ASSISTANT_IDENTITY_STATUS_HEADER as Q}from"./ask-ai.js";import{semanticSearchHandler as aa}from"./semantic-search.js";import{replayOauth2RedirectCallbackHandler as ea}from"./replay-oauth2-redirect.js";import{corsProxyHandler as S}from"./cors-proxy.js";import{corsMiddleware as t}from"../middleware/corsMiddleware.js";import{installApiRoutes as ia}from"./api-routes/api-routes.js";import{cookieMiddleware as la}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ta}from"../routes/static-content.js";import{infoHandler as f}from"./info.js";import{catalogHandler as ma}from"./catalog/catalog.js";import{catalogRelationsHandler as da}from"./catalog/catalog-relations.js";import{bffCatalogHandler as Aa}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as oa}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as na}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as m}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as pa}from"../middleware/telemetry-middleware.js";import{errorHandler as sa}from"./error.js";import{installMcpRoutes as Ta}from"./mcp-routes/mcp-routes.js";import{jsonValidatorMiddleware as O}from"../middleware/jsonValidatorMiddleware.js";import{searchFacetsRequestSchema as Ea}from"../../../api-schemas/search-facets.js";import{searchRequestSchema as _a}from"../../../api-schemas/search.js";function de(a,e,d){const{resolveRouteData:o,readStaticAsset:n}=d;a.use("*",j()),a.use("*",la()),a.use("*",g(e)),a.use("*",C(e)),a.use("*",X()),a.use("*",$(e)),a.use("*",pa()),a.use(i("*"),R({root:`./${c}`,getContent:(A,r)=>ta(A,r,e,n),rewriteRequestPath:A=>H(A)})),a.use(i(l.FEEDBACK),t({allowMethods:["POST"]})),a.use(i(l.ASK_AI),t({allowMethods:["POST"],exposeHeaders:[Q]})),a.use(i(l.AI_ASSISTANT_ESCALATIONS),t({allowMethods:["POST"]})),a.use(i(l.AI_ASSISTANT_FEEDBACK),t({allowMethods:["POST"]})),a.use(i(l.SEMANTIC_SEARCH),t({allowMethods:["POST"]})),a.use("*",Sa(e));const p=I(e);a.use(i(l.INFO),f()),L.NEW_CATALOG_ENABLED&&(a.use(i(l.CATALOG_ENTITIES),m({serverOutDir:e.serverOutDir}),ma(e)),a.use(i(l.CATALOG_ENTITIES_RELATIONS),m({serverOutDir:e.serverOutDir}),da(e)),a.get(i(l.BFF_CATALOG_ENTITIES),m({serverOutDir:e.serverOutDir,protectReadMethods:!1}),Aa(e)),a.get(i(l.BFF_CATALOG_RELATED_ENTITIES),m({serverOutDir:e.serverOutDir,protectReadMethods:!1}),na(e)),a.get(i(l.BFF_CATALOG_REVISIONS),m({serverOutDir:e.serverOutDir,protectReadMethods:!1}),oa(e))),a.get(i(l.SHARED_PAGE_DATA),b(e)),a.get(i(l.PAGE_DATA),k(e,o)),a.get(i(l.APP_DATA),U(e)),a.post(i(l.SEARCH),p,O(_a),y(e)),a.post(i(l.SEARCH_FACETS),p,O(Ea),Y(e)),a.post(i(l.AUTHORIZATION),P),a.post(i(l.LOGOUT),s(e)),a.get(i(l.LOGOUT),s(e)),a.get(i(l.POST_LOGOUT),w(e)),a.get(i(l.OIDC_CALLBACK),N(e)),a.get(i(l.REDOCLY_TOKEN_LOGIN),F(e)),a.get(i(l.REDOCLY_LOGIN_CALLBACK),B()),a.get(i(l.IDP_LOGIN),M(e)),a.post(i(l.SAML_CALLBACK),v(e)),a.get(i(l.INVITE),G(e)),a.get(i(l.HEALTH),W),Ta(a,e),D(a,e),h(a,e),a.all(i(l.CORS_PROXY),S(e)),a.all(i(`${l.CORS_PROXY}/*`),S(e)),ia(a,e),a.post(i(l.FEEDBACK),q(e)),a.post(i(l.RESOLVE_ROUTE_BY_PATH),E(e)),a.post(i(l.RESOLVE_ROUTES_BY_PATHS),V(e)),a.post(i(l.RESOLVE_ROUTE_BY_SLUG),_(e)),a.post(i(l.ASK_AI),Z(e)),a.post(i(l.AI_ASSISTANT_ESCALATIONS),u(e)),a.post(i(l.AI_ASSISTANT_FEEDBACK),J(e)),a.post(i(l.SEMANTIC_SEARCH),aa(e)),a.get(i(l.GET_ROUTES_BY_LINE),T(e)),a.post(i(l.OTEL_TRACES),z),a.get(i(l.REPLAY_OAUTH2_CALLBACK),ea),a.all(i("/*"),K(e,o,n)),a.get("*",x),a.onError(sa)}function Sa(a){return async(e,d)=>{await a.waitForPluginsLifecycle(),await d()}}function Ae(a,e){a.get(i(l.INFO),f()),a.post(i(l.RESOLVE_ROUTE_BY_PATH),E(e)),a.post(i(l.RESOLVE_ROUTE_BY_SLUG),_(e)),a.get(i(l.GET_ROUTES_BY_LINE),T(e))}export{Ae as installDevRoutes,de as installProdRoutes,Sa as waitForPluginsLifecycle};
1
+ import{serveStatic as R}from"hono/serve-static";import{withPathPrefix as i,withoutPathPrefix as c}from"@redocly/theme/core/utils";import{ServerRoutes as l}from"../../../constants/api.js";import{PUBLIC_STATIC_FOLDER as H}from"../../constants/common.js";import{envConfig as L}from"../../config/env-config.js";import{authMiddleware as C}from"../middleware/authMiddleware.js";import{ensureSearchData as I}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as g}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as h}from"../../plugins/dev-onboarding/api/routes/index.js";import{installSkillsRoutes as D}from"./skills/skills-routes.js";import{authorizeHandler as P,oidcCallbackHandler as N,logoutHandler as T,postLogoutHandler as w,idpLoginHandler as M,redoclyLoginCallbackHandler as B,samlCallbackHandler as v,redoclyTokenLoginHandler as F,inviteHandler as G}from"./auth.js";import{appDataHandler as U}from"./app-data.js";import{searchFacetsHandler as Y,searchHandler as y}from"./search.js";import{dynamicRouteHandler as K}from"./dynamic-route.js";import{pageDataHandler as k,sharedPageDataHandler as b}from"./page-data.js";import{pathPrefixRedirectHandler as x}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as E,resolvePathHandler as S,resolvePathsHandler as V,resolveSlugHandler as _}from"./resolve-route.js";import{feedbackHandler as q}from"./feedback.js";import{loggerMiddleware as X}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as $}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as j}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as u}from"./otel/otel.js";import{healthCheckHandler as z}from"./health.js";import{askAiHandler as W,aiAssistantEscalationsHandler as Z,aiAssistantFeedbackHandler as J,AI_ASSISTANT_IDENTITY_STATUS_HEADER as Q}from"./ask-ai.js";import{semanticSearchHandler as aa}from"./semantic-search.js";import{replayOauth2RedirectCallbackHandler as ea}from"./replay-oauth2-redirect.js";import{corsProxyHandler as f}from"./cors-proxy.js";import{corsMiddleware as t}from"../middleware/corsMiddleware.js";import{installApiRoutes as ia}from"./api-routes/api-routes.js";import{cookieMiddleware as la}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ta}from"../routes/static-content.js";import{infoHandler as r}from"./info.js";import{catalogHandler as ma}from"./catalog/catalog.js";import{catalogRelationsHandler as oa}from"./catalog/catalog-relations.js";import{bffCatalogHandler as da}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as Aa}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as na}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as m}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as sa}from"../middleware/telemetry-middleware.js";import{errorHandler as pa}from"./error.js";import{installMcpRoutes as Ta}from"./mcp-routes/mcp-routes.js";import{jsonValidatorMiddleware as A}from"../middleware/jsonValidatorMiddleware.js";import{otelTracesRequestSchema as Ea}from"../../../api-schemas/otel-traces.js";import{searchFacetsRequestSchema as Sa}from"../../../api-schemas/search-facets.js";import{searchRequestSchema as _a}from"../../../api-schemas/search.js";function Ae(a,e,o){const{resolveRouteData:n,readStaticAsset:s}=o;a.use("*",j()),a.use("*",la()),a.use("*",g(e)),a.use("*",C(e)),a.use("*",X()),a.use("*",$(e)),a.use("*",sa()),a.use(i("*"),R({root:`./${H}`,getContent:(d,O)=>ta(d,O,e,s),rewriteRequestPath:d=>c(d)})),a.use(i(l.FEEDBACK),t({allowMethods:["POST"]})),a.use(i(l.ASK_AI),t({allowMethods:["POST"],exposeHeaders:[Q]})),a.use(i(l.AI_ASSISTANT_ESCALATIONS),t({allowMethods:["POST"]})),a.use(i(l.AI_ASSISTANT_FEEDBACK),t({allowMethods:["POST"]})),a.use(i(l.SEMANTIC_SEARCH),t({allowMethods:["POST"]})),a.use("*",fa(e));const p=I(e);a.use(i(l.INFO),r()),L.NEW_CATALOG_ENABLED&&(a.use(i(l.CATALOG_ENTITIES),m({serverOutDir:e.serverOutDir}),ma(e)),a.use(i(l.CATALOG_ENTITIES_RELATIONS),m({serverOutDir:e.serverOutDir}),oa(e)),a.get(i(l.BFF_CATALOG_ENTITIES),m({serverOutDir:e.serverOutDir,protectReadMethods:!1}),da(e)),a.get(i(l.BFF_CATALOG_RELATED_ENTITIES),m({serverOutDir:e.serverOutDir,protectReadMethods:!1}),na(e)),a.get(i(l.BFF_CATALOG_REVISIONS),m({serverOutDir:e.serverOutDir,protectReadMethods:!1}),Aa(e))),a.get(i(l.SHARED_PAGE_DATA),b(e)),a.get(i(l.PAGE_DATA),k(e,n)),a.get(i(l.APP_DATA),U(e)),a.post(i(l.SEARCH),p,A(_a),y(e)),a.post(i(l.SEARCH_FACETS),p,A(Sa),Y(e)),a.post(i(l.AUTHORIZATION),P),a.post(i(l.LOGOUT),T(e)),a.get(i(l.LOGOUT),T(e)),a.get(i(l.POST_LOGOUT),w(e)),a.get(i(l.OIDC_CALLBACK),N(e)),a.get(i(l.REDOCLY_TOKEN_LOGIN),F(e)),a.get(i(l.REDOCLY_LOGIN_CALLBACK),B()),a.get(i(l.IDP_LOGIN),M(e)),a.post(i(l.SAML_CALLBACK),v(e)),a.get(i(l.INVITE),G(e)),a.get(i(l.HEALTH),z),Ta(a,e),h(a,e),D(a,e),a.all(i(l.CORS_PROXY),f(e)),a.all(i(`${l.CORS_PROXY}/*`),f(e)),ia(a,e),a.post(i(l.FEEDBACK),q(e)),a.post(i(l.RESOLVE_ROUTE_BY_PATH),S(e)),a.post(i(l.RESOLVE_ROUTES_BY_PATHS),V(e)),a.post(i(l.RESOLVE_ROUTE_BY_SLUG),_(e)),a.post(i(l.ASK_AI),W(e)),a.post(i(l.AI_ASSISTANT_ESCALATIONS),Z(e)),a.post(i(l.AI_ASSISTANT_FEEDBACK),J(e)),a.post(i(l.SEMANTIC_SEARCH),aa(e)),a.get(i(l.GET_ROUTES_BY_LINE),E(e)),a.post(i(l.OTEL_TRACES),A(Ea),u),a.get(i(l.REPLAY_OAUTH2_CALLBACK),ea),a.all(i("/*"),K(e,n,s)),a.get("*",x),a.onError(pa)}function fa(a){return async(e,o)=>{await a.waitForPluginsLifecycle(),await o()}}function ne(a,e){a.get(i(l.INFO),r()),a.post(i(l.RESOLVE_ROUTE_BY_PATH),S(e)),a.post(i(l.RESOLVE_ROUTE_BY_SLUG),_(e)),a.get(i(l.GET_ROUTES_BY_LINE),E(e))}export{ne as installDevRoutes,Ae as installProdRoutes,fa as waitForPluginsLifecycle};
@@ -1 +1 @@
1
- import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as c}from"../../../constants/common.js";import{telemetryTraceStep as d}from"../../../telemetry/helpers/trace-step.js";import{getAccessibleSkills as g}from"../../../utils/skills/get-accessible-skills.js";import{resolvePublicBaseUrl as m}from"../../../web-server/utils/resolve-public-base-url.js";import{shouldHandleMcpAuth as A}from"../../../plugins/mcp/auth/auth-handlers.js";import{buildAgentCard as C}from"./utils/build-agent-card.js";function y(e){return async r=>await d("com.redocly.agentCard.served",async t=>{if(t?.setAttribute("id","agentCardId"),t?.setAttribute("object","agentCard"),t?.setAttribute("uri","urn:redocly:realm:api:agentCard:agentCardId"),e.config.skills?.hide===!0)return r.newResponse(null,404);const{isAuthenticated:l,teams:a,claims:{email:u}}=r.get("auth"),i=e.config.access?.rbac||{},n=!!e.config.access?.requiresLogin,s=g(e.getSkills(),{isAuthenticated:l,teams:a,email:u},i,n),o=A(n,i);return t?.setAttribute("skillsCount",s.length),t?.setAttribute("mcpAuthRequired",o),r.json(C({seo:e.getGlobalConfig("seo"),baseUrl:m(e,r),skills:s,mcpAuthRequired:o}),200,{"Cache-Control":c,"Access-Control-Allow-Origin":"*"})})}export{y as agentCardHandler};
1
+ import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as c}from"../../../constants/common.js";import{telemetryTraceStep as d}from"../../../telemetry/helpers/trace-step.js";import{getAccessibleSkills as g}from"../../../utils/skills/get-accessible-skills.js";import{resolvePublicBaseUrl as m}from"../../../web-server/utils/resolve-public-base-url.js";import{shouldHandleMcpAuth as A}from"../../../utils/rbac/should-handle-mcp-auth.js";import{buildAgentCard as C}from"./utils/build-agent-card.js";function y(e){return async r=>await d("com.redocly.agentCard.served",async t=>{if(t?.setAttribute("id","agentCardId"),t?.setAttribute("object","agentCard"),t?.setAttribute("uri","urn:redocly:realm:api:agentCard:agentCardId"),e.config.skills?.hide===!0)return r.newResponse(null,404);const{isAuthenticated:l,teams:a,claims:{email:u}}=r.get("auth"),i=e.config.access?.rbac||{},n=!!e.config.access?.requiresLogin,s=g(e.getSkills(),{isAuthenticated:l,teams:a,email:u},i,n),o=A(n,i);return t?.setAttribute("skillsCount",s.length),t?.setAttribute("mcpAuthRequired",o),r.json(C({seo:e.getGlobalConfig("seo"),baseUrl:m(e,r),skills:s,mcpAuthRequired:o}),200,{"Cache-Control":c,"Access-Control-Allow-Origin":"*"})})}export{y as agentCardHandler};
@@ -1 +1 @@
1
- import{withPathPrefix as S}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as f,MCP_PROTOCOL_VERSION as A}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as O}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as T}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as b,DESCRIBE_TOOLS_TOOL_NAME as M,FETCH_TOOL_NAME as R}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as g}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as v}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{buildCodeModeInstructions as L,buildExecuteDescription as I,DESCRIBE_TOOLS_DESCRIPTION as D}from"../../../plugins/mcp/codemode/prompts.js";import{toToolListEntries as P}from"../../../plugins/mcp/codemode/build-tool-list.js";import{composeExecuteAnnotations as y}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 N}from"../../../plugins/mcp/auth/auth-handlers.js";import{resolvePublicBaseUrl as U}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as x}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as w}from"./constants.js";const B="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",j="1.0";function ie(r){const s=T(),E=new Date().toISOString().slice(0,10);return async m=>await x("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||f,n=r.getMcpTools().filter(t=>!b.has(t.name)&&!t.hasAvailabilityGate),i=H(o.mcp)?[...V]:[],l=i.some(t=>t.id===R),d=P(n,i),c=(s?[{...g,description:I(l,d),annotations:y(i)},{name:M,description:D,schema:v(n,i)}]:n).map(({name:t,description:_,schema:h,annotations:u})=>({name:t,description:_,inputSchema:h,...u?{annotations:u}:{}})),C=o.skills?.hide===!0?[]:r.getSkills(),p={$schema:B,version:j,protocolVersion:A,serverInfo:{name:a,title:a,version:E},description:o.seo?.description,documentationUrl:U(r,m),transport:{type:"streamable-http",endpoint:S(O.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...C.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:N(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:w}:void 0,instructions:s?L(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{ie as mcpServerCardHandler};
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 +1 @@
1
- import{AsyncApiRealmAPI as y}from"@redocly/realm-asyncapi-sdk";import{envConfig as o}from"../../../config/env-config.js";import{getClientIp as R}from"../../utils/get-client-ip.js";import{getAttributesStringValue as I,mergeAttributes as h,toAttribute as O}from"./otlp.js";const C=o.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",A="cloudevents.event_session_id";class w extends y.OtelClient{initTracer(){}}let d=null;function E(){return d||(d=new w,d.init({collectorTraceUrl:void 0,serviceName:"realm-ui",serviceVersion:"1.0",isProd:o.isProductionEnv,version:"1.0",tracerName:"attribute-processor"})),d}async function $(e){const t=await e.req.json();return t.resourceSpans?.length&&(N(t,j(e)),await fetch(C,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),e.newResponse(null,200)}function N(e,t){for(const s of e.resourceSpans){const r=s.resource.attributes.find(u=>u.key==="session_id");if(!r)continue;const i=I(r);if(!i)continue;const l=L(t.userId,i),_=new Date,v={organizationId:o.ORGANIZATION_ID||"",organizationSlug:o.ORGANIZATION_SLUG||"",projectId:o.PROJECT_ID||"",projectSlug:o.PROJECT_SLUG||"",env:o.REDOCLY_ENV||"",source:"urn:redocly:realm:ui",actor:{id:l.id,object:l.object,uri:l.uri},clientIp:t.clientIp,userAgent:t.userAgent},c=(u,n)=>{const a=u.attributes.find(f=>f.key===n);return a?I(a):""};for(const u of s.scopeSpans)for(const n of u.spans){if(!n.name.startsWith("event.")||n.name==="event.undefined")continue;const a=c(n,"cloudevents.event_spec_version"),f=c(n,"cloudevents.event_object"),g=c(n,"cloudevents.event_data_content_type"),b=c(n,"cloudevents.event_origin"),p=c(n,"cloudevents.event_time"),m=p?new Date(p):_,S={...v,id:c(n,"cloudevents.event_id"),specversion:a,type:n.name.slice(6),object:f,datacontenttype:g,time:m,origin:b},T=E().processAttributes(S,m);h(n,T,{overwrite:!0}),P(n,t.sessionId)}}}function P(e,t){const s=e.attributes.findIndex(i=>i.key===A),r=O(A,t);r?s===-1?e.attributes.push(r):e.attributes[s]=r:s!==-1&&e.attributes.splice(s,1)}function j(e){const t=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,s=e.get("auth")?.claims?.sessionId,r=R(e.req.raw)||e.req.raw.context?.remoteAddr?.hostname,i=e.req.raw.headers.get("user-agent");return{userId:t,sessionId:s||void 0,clientIp:r??void 0,userAgent:i??void 0}}function L(e,t){if(e)return{id:e,object:"user",uri:`${o.MAIN_API_URL}/users/${e}`};const s=t.replace("ses_","ann_");return{id:s,object:"anonymous",uri:`${o.MAIN_API_URL}/anonymous/${s}`}}export{$ as otelTracesHandler,L as toActor};
1
+ import{AsyncApiRealmAPI as N}from"@redocly/realm-asyncapi-sdk";import{envConfig as o}from"../../../config/env-config.js";import{getClientIp as R}from"../../utils/get-client-ip.js";import{getAttributesStringValue as _,mergeAttributes as h,toAttribute as O}from"./otlp.js";const C=o.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",v="cloudevents.event_session_id";class w extends N.OtelClient{initTracer(){}}let d=null;function E(){return d||(d=new w,d.init({collectorTraceUrl:void 0,serviceName:"realm-ui",serviceVersion:"1.0",isProd:o.isProductionEnv,version:"1.0",tracerName:"attribute-processor"})),d}async function k(e){const t=await e.req.json();return t.resourceSpans?.length&&(P(t,L(e)),await fetch(C,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})),e.newResponse(null,200)}function P(e,t){for(const s of e.resourceSpans){const r=s.resource.attributes.find(u=>u.key==="session_id");if(!r)continue;const i=_(r);if(!i)continue;const l=U(t.userId,i),p=new Date,g={organizationId:o.ORGANIZATION_ID||"",organizationSlug:o.ORGANIZATION_SLUG||"",projectId:o.PROJECT_ID||"",projectSlug:o.PROJECT_SLUG||"",env:o.REDOCLY_ENV||"",source:"urn:redocly:realm:ui",actor:{id:l.id,object:l.object,uri:l.uri},clientIp:t.clientIp,userAgent:t.userAgent},c=(u,n)=>{const a=u.attributes.find(f=>f.key===n);return a?_(a):""};for(const u of s.scopeSpans)for(const n of u.spans){if(!n.name.startsWith("event.")||n.name==="event.undefined")continue;const a=c(n,"cloudevents.event_spec_version"),f=c(n,"cloudevents.event_object"),b=c(n,"cloudevents.event_data_content_type"),S=c(n,"cloudevents.event_origin"),m=c(n,"cloudevents.event_time"),I=m?new Date(m):p,A=Number.isNaN(I.getTime())?p:I,T={...g,id:c(n,"cloudevents.event_id"),specversion:a,type:n.name.slice(6),object:f,datacontenttype:b,time:A,origin:S},y=E().processAttributes(T,A);h(n,y,{overwrite:!0}),j(n,t.sessionId)}}}function j(e,t){const s=e.attributes.findIndex(i=>i.key===v),r=O(v,t);r?s===-1?e.attributes.push(r):e.attributes[s]=r:s!==-1&&e.attributes.splice(s,1)}function L(e){const t=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,s=e.get("auth")?.claims?.sessionId,r=R(e.req.raw)||e.req.raw.context?.remoteAddr?.hostname,i=e.req.raw.headers.get("user-agent");return{userId:t,sessionId:s||void 0,clientIp:r??void 0,userAgent:i??void 0}}function U(e,t){if(e)return{id:e,object:"user",uri:`${o.MAIN_API_URL}/users/${e}`};const s=t.replace("ses_","ann_");return{id:s,object:"anonymous",uri:`${o.MAIN_API_URL}/anonymous/${s}`}}export{k as otelTracesHandler,U as toActor};
@@ -1 +1 @@
1
- import{ServerRoutes as $}from"../../../constants/api.js";import{DEV_LOGIN_SLUG as w}from"../../../constants/common.js";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as a,DEFAULT_TITLE as U}from"../../constants/common.js";import{findInIterable as F}from"../../../utils/collection/find-in-iterable.js";import{removeTrailingSlash as N}from"../../../utils/url/remove-trailing-slash.js";import{envConfig as b}from"../../config/env-config.js";import{canAccessResource as q,filterDataByAccessDeep as T,isResourcePubliclyAccessible as B}from"../../utils/rbac.js";import{getServerProps as H}from"../../ssr/index.js";import{readSharedData as M}from"../../utils/index.js";import{getRedirectLoginUrl as G}from"../utils/get-redirect-login-url.js";import{processRedirects as V}from"./helpers/process-redirects.js";import{removeErrorDetails as W}from"../utils/remove-error-details.js";import{telemetry as k}from"../../telemetry/index.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as K}from"../../plugins/mcp/constants.js";function ie(e,n){return async(t,g)=>{const m=t.get("logger"),{req:p}=t,{pathname:d}=new URL(p.url),{seo:f,ssoDirect:h}=e.getConfig(),i=f?.title||U;if(e?.compilationErrors?.length&&b.isDevelopMode)return t.json({templateId:"compilation-error",props:{compilationErrors:e?.compilationErrors},sharedDataIds:{}},500,{"Cache-Control":a});const u=d.match(/page-data(.*)data.json$/);if(!u)return g();const c=decodeURI(u[1]),r=c==="/index/"?"/":N(c),o=e.getRouteBySlug(r,{followRedirect:!1})||F(e.routesBySlug.values(),s=>s.hasClientRoutes&&c.startsWith(s.slug+"/"));if(c===$.OIDC_CALLBACK+"/")return t.json({templateId:"403OIDC",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}}},200,{"Cache-Control":a});const{isAuthenticated:C,teams:D,claims:{name:j,picture:A,email:I}}=t.get("auth"),R={isAuthenticated:C,email:I,teams:D},l={isAuthenticated:C,name:j,picture:A,email:I,teams:D};if(r==="/mcp"&&e.globalData.mcpData?.docs?.enabled)return t.json({templateId:K,sharedDataIds:{},props:{},userData:l},405,{"Cache-Control":a});const L=e.getRedirect(r);if(L){const s=V({redirect:L}).location;return k.sendRedirectMessage([{id:r,object:"redirect",uri:`urn:redocly:realm:api:redirect:${r}`,from:r,templateId:"404"}]),t.json({templateId:"404",redirectTo:s,sharedDataIds:{},props:{}},301,{"Cache-Control":a})}if(!o){const s=e.getRouteBySlug(r,{followRedirect:!0});return m.error(`Page not found: ${d}`),t.json({templateId:"404",redirectTo:s?.slug,sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l},404,{"Cache-Control":a})}if(m.verbose(`Page viewed: ${o.slug}`),!q(o,R,e.config.access?.rbac,e.config.access?.requiresLogin)&&o.slug!==w){if(C)return t.json({templateId:"403",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}},userData:l},403,{"Cache-Control":a});const s=Object.keys(h||{}).length>0;return t.json({templateId:"404",sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l,...s?{redirectTo:G(e,o.slug)}:{}},s?401:404,{"Cache-Control":a})}const S=T(o.versions,R,e.config.access?.rbac,e.config.access?.requiresLogin),_=e.routesSharedData.get(o.slug)||{},v=await n(o),P=await H(o,t,v,e),{sharedDataIds:y,...E}=P,O={templateId:o.templateId,versions:S,sharedDataIds:{..._,...y||{}},props:b.isProductionEnv?W(E):E,slug:o.slug,userData:l,isPublic:B(o,e.config)};return t.json(O,200,{"Cache-Control":a})}}function ce(e){return async(n,t)=>{const g=n.get("logger"),{req:m}=n,{pathname:p}=new URL(m.url),d=p.match(/\/page-data\/shared\/(.*)\.json/);if(!d)return t();const f=decodeURIComponent(d[1]),h=await M(f,e.outdir),{isAuthenticated:i,teams:u,claims:{email:c}}=n.get("auth"),r=T(h,{isAuthenticated:i,email:c,teams:u},e.config.access?.rbac,e.config.access?.requiresLogin);return r?n.json(r,200,{"Cache-Control":a}):(g.error(`Shared data not found: ${p}`),n.text("Not Found",404,{"Cache-Control":a}))}}export{ie as pageDataHandler,ce as sharedPageDataHandler};
1
+ import{MCP_ROUTE as y,PUBLIC_MCP_ROUTE as $}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as w}from"../../../constants/api.js";import{DEV_LOGIN_SLUG as M}from"../../../constants/common.js";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as a,DEFAULT_TITLE as F}from"../../constants/common.js";import{findInIterable as N}from"../../../utils/collection/find-in-iterable.js";import{removeTrailingSlash as B}from"../../../utils/url/remove-trailing-slash.js";import{envConfig as b}from"../../config/env-config.js";import{canAccessResource as q,filterDataByAccessDeep as T,isResourcePubliclyAccessible as H}from"../../utils/rbac.js";import{getServerProps as G}from"../../ssr/index.js";import{readSharedData as V}from"../../utils/index.js";import{getRedirectLoginUrl as W}from"../utils/get-redirect-login-url.js";import{processRedirects as k}from"./helpers/process-redirects.js";import{removeErrorDetails as K}from"../utils/remove-error-details.js";import{telemetry as z}from"../../telemetry/index.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as J}from"../../constants/mcp.js";function pe(e,n){return async(t,g)=>{const p=t.get("logger"),{req:m}=t,{pathname:d}=new URL(m.url),{seo:f,ssoDirect:h}=e.getConfig(),i=f?.title||F;if(e?.compilationErrors?.length&&b.isDevelopMode)return t.json({templateId:"compilation-error",props:{compilationErrors:e?.compilationErrors},sharedDataIds:{}},500,{"Cache-Control":a});const u=d.match(/page-data(.*)data.json$/);if(!u)return g();const c=decodeURI(u[1]),r=c==="/index/"?"/":B(c),o=e.getRouteBySlug(r,{followRedirect:!1})||N(e.routesBySlug.values(),s=>s.hasClientRoutes&&c.startsWith(s.slug+"/"));if(c===w.OIDC_CALLBACK+"/")return t.json({templateId:"403OIDC",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}}},200,{"Cache-Control":a});const{isAuthenticated:C,teams:D,claims:{name:_,picture:P,email:I}}=t.get("auth"),R={isAuthenticated:C,email:I,teams:D},l={isAuthenticated:C,name:_,picture:P,email:I,teams:D};if((r===y||r===$&&!!e.globalData.mcpData?.docs?.publicEndpoint)&&e.globalData.mcpData?.docs?.enabled)return t.json({templateId:J,sharedDataIds:{},props:{},userData:l},405,{"Cache-Control":a});const E=e.getRedirect(r);if(E){const s=k({redirect:E}).location;return z.sendRedirectMessage([{id:r,object:"redirect",uri:`urn:redocly:realm:api:redirect:${r}`,from:r,templateId:"404"}]),t.json({templateId:"404",redirectTo:s,sharedDataIds:{},props:{}},301,{"Cache-Control":a})}if(!o){const s=e.getRouteBySlug(r,{followRedirect:!0});return p.error(`Page not found: ${d}`),t.json({templateId:"404",redirectTo:s?.slug,sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l},404,{"Cache-Control":a})}if(p.verbose(`Page viewed: ${o.slug}`),!q(o,R,e.config.access?.rbac,e.config.access?.requiresLogin)&&o.slug!==M){if(C)return t.json({templateId:"403",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}},userData:l},403,{"Cache-Control":a});const s=Object.keys(h||{}).length>0;return t.json({templateId:"404",sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l,...s?{redirectTo:W(e,o.slug)}:{}},s?401:404,{"Cache-Control":a})}const j=T(o.versions,R,e.config.access?.rbac,e.config.access?.requiresLogin),A=e.routesSharedData.get(o.slug)||{},S=await n(o),v=await G(o,t,S,e),{sharedDataIds:O,...L}=v,U={templateId:o.templateId,versions:j,sharedDataIds:{...A,...O||{}},props:b.isProductionEnv?K(L):L,slug:o.slug,userData:l,isPublic:H(o,e.config)};return t.json(U,200,{"Cache-Control":a})}}function me(e){return async(n,t)=>{const g=n.get("logger"),{req:p}=n,{pathname:m}=new URL(p.url),d=m.match(/\/page-data\/shared\/(.*)\.json/);if(!d)return t();const f=decodeURIComponent(d[1]),h=await V(f,e.outdir),{isAuthenticated:i,teams:u,claims:{email:c}}=n.get("auth"),r=T(h,{isAuthenticated:i,email:c,teams:u},e.config.access?.rbac,e.config.access?.requiresLogin);return r?n.json(r,200,{"Cache-Control":a}):(g.error(`Shared data not found: ${m}`),n.text("Not Found",404,{"Cache-Control":a}))}}export{pe as pageDataHandler,me as sharedPageDataHandler};
@@ -1 +1 @@
1
- import{Source as P}from"@redocly/openapi-core";import y from"node:fs/promises";import S from"node:path";import{withPathPrefix as j,getPathPrefix as h,combineUrls as w}from"@redocly/theme/core/utils";import{API_DOCS_SHARED_DATA_PREFIX as d}from"../../constants/plugins/api-docs.js";import{CATALOG_BASE_SLUG as b,CATALOG_SLUGS as $}from"../../../constants/catalog-entities.js";import{CATALOG_ENTITIES_FILES_REGEX as I}from"../../constants/plugins/catalog-entities.js";import{removeTrailingSlash as E}from"../../../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as N}from"../../../utils/path/normalize-route-slug.js";import{promiseMapLimit as T}from"../../utils/async/promise-map-limit.js";import{getRoutesByLines as L,getPointerPosition as U}from"../../plugins/openapi-docs/ast-utils.js";import{readSharedData as m}from"../../utils/index.js";const q=new Set(["openapi","asyncapi"]);function K(n){return async t=>{const i=await t.req.json(),r=decodeURI(E(i.split("?")[0])),[o]=r.split("#"),g=h(),f=N(o.slice(g.length)),u=f.startsWith(b)?b:f,e=n.getRouteBySlug(u);if(e){const p=n.getRouteByFsPath(e.fsPath);if(p?.metadata?.type&&q.has(p.metadata.type)){const a=await m(`${d}${e.fsPath}`,n.outdir);if(!a?.routesMapping)return t.json({route:e},200);const s=Object.keys(a.routesMapping).find(c=>w(e.baseSlug,a.routesMapping[c])===r);if(!a.sourcePath)return t.json({route:e},200);let l;if(s){const c=S.join(n.contentDir,e.fsPath),R=await y.readFile(c,"utf-8"),_=new P(c,R);l=U(s,_)}return t.json({route:{fsPath:e.fsPath,pointer:s,position:l}},200)}if(p?.metadata?.type==="graphql"){const a=await m(`${d}${e.fsPath}`,n.outdir);if(!a?.graphqlPositions)return t.json({route:e},200);const s=Object.keys(a.graphqlPositions).find(c=>w(e.baseSlug,c)===r),l=s?a.graphqlPositions[s].position:void 0;return t.json({route:{fsPath:e.fsPath,position:l}},200)}}return t.json({route:e},200)}}function X(n){return async t=>{const i=await t.req.json(),r=await T(i,5,async o=>A(o,n));return t.json({routes:r},200)}}function Y(n){return async t=>{const i=await t.req.json(),r=await A(i,n);return t.json(r,200)}}function J(n){return async t=>{const i=(t.req.query("lines")||"").split(",").map(f=>parseInt(f)),r=t.req.query("file");if(!r)return t.json("No data",400);const o=await m(`${d}${r}`,n.outdir),g=S.join(n.contentDir,r);try{const f=await y.readFile(g,"utf-8");if(!o)return t.json("No data",400);const u=new P(g,f),e=L(i,u,o.routesMapping,o.baseSlug);return t.json(e,200)}catch{return t.json("No data",400)}}}async function A(n,t){const[i,r]=n.split(":");if(I.test(i))return{route:{slug:`${b}/${$.ALL}`}};let o=t.getRouteByFsPath(i);if(o?.metadata?.type&&q.has(o.metadata.type)){const u=await m(`${d}${i}`,t.outdir);if(u?.sourcePath){const e=S.join(t.contentDir,o.fsPath),p=await y.readFile(e,"utf-8"),a=new P(e,p),s=L([parseInt(r,10)],a,u.routesMapping,o.baseSlug);if(s.length)return{route:{slug:h()?j(s[0]):s[0],filePath:n}}}}if(o?.metadata?.type==="graphql"){const u=await m(`${d}${i}`,t.outdir),e=parseInt(r,10);if(u?.sourcePath&&u.graphqlPositions&&!Number.isNaN(e)){let p,a=1/0;for(const[s,{startLine:l,endLine:c}]of Object.entries(u.graphqlPositions))l<=e&&e<=c&&c-l<a&&(a=c-l,p=s);if(p){const s=w(o.baseSlug,p);return{route:{slug:h()?j(s):s,filePath:n}}}}}const g=o?.slug?h()?j(o?.slug):o?.slug:"";return{route:{...o,pageName:o?await o?.getNavText?.():"",slug:g,filePath:n}}}export{J as getRoutesByLineHandler,Y as resolvePathHandler,X as resolvePathsHandler,K as resolveSlugHandler};
1
+ import{Source as P}from"@redocly/openapi-core";import y from"node:fs/promises";import S from"node:path";import{withPathPrefix as j,getPathPrefix as h,combineUrls as w}from"@redocly/theme/core/utils";import{API_DOCS_SHARED_DATA_PREFIX as d}from"../../constants/plugins/api-docs.js";import{CATALOG_BASE_SLUG as b,CATALOG_SLUGS as $}from"../../../constants/catalog-entities.js";import{CATALOG_ENTITIES_FILES_REGEX as I}from"../../constants/plugins/catalog-entities.js";import{removeTrailingSlash as E}from"../../../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as N}from"../../../utils/path/normalize-route-slug.js";import{promiseMapLimit as T}from"../../utils/async/promise-map-limit.js";import{getRoutesByLines as L,getPointerPosition as U}from"../../plugins/api-docs/utils/ast-utils.js";import{readSharedData as m}from"../../utils/index.js";const q=new Set(["openapi","asyncapi"]);function K(n){return async t=>{const i=await t.req.json(),r=decodeURI(E(i.split("?")[0])),[o]=r.split("#"),g=h(),f=N(o.slice(g.length)),u=f.startsWith(b)?b:f,e=n.getRouteBySlug(u);if(e){const p=n.getRouteByFsPath(e.fsPath);if(p?.metadata?.type&&q.has(p.metadata.type)){const a=await m(`${d}${e.fsPath}`,n.outdir);if(!a?.routesMapping)return t.json({route:e},200);const s=Object.keys(a.routesMapping).find(c=>w(e.baseSlug,a.routesMapping[c])===r);if(!a.sourcePath)return t.json({route:e},200);let l;if(s){const c=S.join(n.contentDir,e.fsPath),R=await y.readFile(c,"utf-8"),_=new P(c,R);l=U(s,_)}return t.json({route:{fsPath:e.fsPath,pointer:s,position:l}},200)}if(p?.metadata?.type==="graphql"){const a=await m(`${d}${e.fsPath}`,n.outdir);if(!a?.graphqlPositions)return t.json({route:e},200);const s=Object.keys(a.graphqlPositions).find(c=>w(e.baseSlug,c)===r),l=s?a.graphqlPositions[s].position:void 0;return t.json({route:{fsPath:e.fsPath,position:l}},200)}}return t.json({route:e},200)}}function X(n){return async t=>{const i=await t.req.json(),r=await T(i,5,async o=>A(o,n));return t.json({routes:r},200)}}function Y(n){return async t=>{const i=await t.req.json(),r=await A(i,n);return t.json(r,200)}}function J(n){return async t=>{const i=(t.req.query("lines")||"").split(",").map(f=>parseInt(f)),r=t.req.query("file");if(!r)return t.json("No data",400);const o=await m(`${d}${r}`,n.outdir),g=S.join(n.contentDir,r);try{const f=await y.readFile(g,"utf-8");if(!o)return t.json("No data",400);const u=new P(g,f),e=L(i,u,o.routesMapping,o.baseSlug);return t.json(e,200)}catch{return t.json("No data",400)}}}async function A(n,t){const[i,r]=n.split(":");if(I.test(i))return{route:{slug:`${b}/${$.ALL}`}};let o=t.getRouteByFsPath(i);if(o?.metadata?.type&&q.has(o.metadata.type)){const u=await m(`${d}${i}`,t.outdir);if(u?.sourcePath){const e=S.join(t.contentDir,o.fsPath),p=await y.readFile(e,"utf-8"),a=new P(e,p),s=L([parseInt(r,10)],a,u.routesMapping,o.baseSlug);if(s.length)return{route:{slug:h()?j(s[0]):s[0],filePath:n}}}}if(o?.metadata?.type==="graphql"){const u=await m(`${d}${i}`,t.outdir),e=parseInt(r,10);if(u?.sourcePath&&u.graphqlPositions&&!Number.isNaN(e)){let p,a=1/0;for(const[s,{startLine:l,endLine:c}]of Object.entries(u.graphqlPositions))l<=e&&e<=c&&c-l<a&&(a=c-l,p=s);if(p){const s=w(o.baseSlug,p);return{route:{slug:h()?j(s):s,filePath:n}}}}}const g=o?.slug?h()?j(o?.slug):o?.slug:"";return{route:{...o,pageName:o?await o?.getNavText?.():"",slug:g,filePath:n}}}export{J as getRoutesByLineHandler,Y as resolvePathHandler,X as resolvePathsHandler,K as resolveSlugHandler};
@@ -1,4 +1,6 @@
1
1
  import type { Context } from 'hono';
2
2
  export declare function getRequestOrigin(ctx: Context): string;
3
+ /** Request-based counterpart of `getRequestOrigin`; the same trust caveat applies. */
3
4
  export declare function getForwardedOrigin(request: Request): string;
5
+ export declare function getInternalOrigin(request: Request): string | undefined;
4
6
  //# sourceMappingURL=get-request-origin.d.ts.map
@@ -1 +1 @@
1
- const s=["localhost","127.0.0.1","::1","[::1]"];function n(o){return o?.split(",")[0].trim()||void 0}function d(o){const t=o.replace(/:\d+$/,"");return s.includes(t)||t.endsWith(".localhost")}function a(o){const t=new URL(o.req.url),r=o.req.header("x-forwarded-proto")||t.protocol.slice(0,-1)||"https",e=o.req.header("x-forwarded-host")||t.host;return`${r}://${e}`}function c(o){const t=new URL(o.url),r=n(o.headers.get("x-forwarded-host"))||t.host;return`${n(o.headers.get("x-forwarded-proto"))||(d(r)?"http":"https")}://${r}`}export{c as getForwardedOrigin,a as getRequestOrigin};
1
+ import{envConfig as i}from"../../config/env-config.js";const c=["localhost","127.0.0.1","::1","[::1]"];function n(o){return o?.split(",")[0].trim()||void 0}const a=/^(?:[A-Za-z0-9._-]+|\[[0-9A-Fa-f:.]+\])(?::\d{1,5})?$/;function s(o){const t=n(o);return t&&a.test(t)?t:void 0}function d(o){const t=n(o)?.toLowerCase();return t==="http"||t==="https"?t:void 0}function p(o){const t=o.replace(/:\d+$/,"");return c.includes(t)||t.endsWith(".localhost")}function h(o){const t=new URL(o.req.url),r=d(o.req.header("x-forwarded-proto"))||t.protocol.slice(0,-1)||"https",e=s(o.req.header("x-forwarded-host"))||t.host;return`${r}://${e}`}function u(o){const t=new URL(o.url),r=s(o.headers.get("x-forwarded-host"))||t.host;return`${d(o.headers.get("x-forwarded-proto"))||(p(r)?"http":"https")}://${r}`}function l(o){const t=o.context?.remoteAddr?.port??i.PORT;return t?`http://127.0.0.1:${t}`:void 0}export{u as getForwardedOrigin,l as getInternalOrigin,h as getRequestOrigin};
@@ -7,10 +7,6 @@ export type ListResponseResult<T extends {
7
7
  page: {
8
8
  total: number;
9
9
  limit: number;
10
- hasNextPage: boolean;
11
- hasPrevPage: boolean;
12
- startCursor: string | null;
13
- endCursor: string | null;
14
10
  nextPage: string | null;
15
11
  previousPage: string | null;
16
12
  };
@@ -1 +1 @@
1
- import{createCursor as c}from"../../providers/database/pagination/utils/create-cursor.js";import{DEFAULT_LIMIT as o}from"../../providers/database/pagination/limit.js";function h(e){return!!(e.after||e.before)}function b(e,i,n){const r=h(i),t=i.limit??o;if(r){if(i.before)return!0;if(i.after)return e.length===t}return n!==void 0&&i.skip!==void 0?i.skip+t<n:n!==void 0?t<n:e.length===t}function d(e){return!!(e.after||e.before||e.skip!==void 0&&e.skip>0)}function x({data:e,params:i,totalCount:n,nameTransformationsFromDatabase:r={},hasMore:t}){if(!e.length)return{object:"list",items:[],page:{total:0,limit:i.limit??o,hasNextPage:!1,hasPrevPage:!1,startCursor:null,endCursor:null,nextPage:null,previousPage:null}};const l=i.sort?.length?i.sort:[{field:"id",order:"ASC"}],u=t??b(e,i,n),g=d(i),P=!!(i.after||i.before&&t||i.skip!==void 0&&i.skip>0),f=c(e[0],l,r),s=c(e[e.length-1],l,r);return{object:"list",items:e,page:{total:n??0,limit:i.limit??o,hasNextPage:u,hasPrevPage:g,startCursor:f,endCursor:s,nextPage:u?s:null,previousPage:P?f:null}}}export{x as prepareListResponse};
1
+ import{createCursor as u}from"../../providers/database/pagination/utils/create-cursor.js";import{DEFAULT_LIMIT as l}from"../../providers/database/pagination/limit.js";function P(i){return!!(i.after||i.before)}function b(i,e,t){const r=P(e),n=e.limit??l;if(r){if(e.before)return!0;if(e.after)return i.length===n}return t!==void 0&&e.skip!==void 0?e.skip+n<t:t!==void 0?n<t:i.length===n}function v({data:i,params:e,totalCount:t,nameTransformationsFromDatabase:r={},hasMore:n}){if(!i.length)return{object:"list",items:[],page:{total:0,limit:e.limit??l,nextPage:null,previousPage:null}};const o=e.sort?.length?e.sort:[{field:"id",order:"ASC"}],f=n??b(i,e,t),s=!!(e.after||e.before&&n||e.skip!==void 0&&e.skip>0),c=u(i[0],o,r),g=u(i[i.length-1],o,r);return{object:"list",items:i,page:{total:t??0,limit:e.limit??l,nextPage:f?g:null,previousPage:s?c:null}}}export{v as prepareListResponse};
@@ -12,7 +12,7 @@ export declare function handleErrorPageRender(ctx: Context, store: Store, option
12
12
  };
13
13
  }, statusCode: ClientErrorStatusCode, templateId?: string): Promise<Response>;
14
14
  export declare function getLoginUrlWithRedirect(redirectTo: string): string;
15
- export declare function handleUnauthorizedAsset(ctx: Context): Promise<Response & import("hono").TypedResponse<"Forbidden", -1 | 100 | 102 | 103 | 200 | 201 | 202 | 203 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511, "text">>;
15
+ export declare function handleUnauthorizedAsset(ctx: Context): Promise<Response & import("hono").TypedResponse<string, -1 | 100 | 102 | 103 | 200 | 201 | 202 | 203 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511, "text">>;
16
16
  export declare function handleUnauthorizedApiRequest(ctx: Context): Response & import("hono").TypedResponse<{
17
17
  message: string;
18
18
  }, -1 | 100 | 102 | 103 | 200 | 201 | 202 | 203 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511, "json">;