@redocly/reef 0.131.0-next.0 → 0.131.0-next.10

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 (465) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/dist/bin.d.ts +1 -0
  3. package/dist/bin.js +1 -1
  4. package/dist/cli/build/copy-env-files.js +1 -0
  5. package/dist/cli/{prepare → build}/index.d.ts +2 -2
  6. package/dist/cli/build/index.js +1 -0
  7. package/dist/cli/develop.js +1 -1
  8. package/dist/cli/eject/resolveTheme.d.ts +1 -1
  9. package/dist/cli/eject/resolveTheme.js +1 -1
  10. package/dist/cli/stats/collectors/{openapi.d.ts → openapi/index.d.ts} +2 -2
  11. package/dist/cli/stats/collectors/openapi/index.js +1 -0
  12. package/dist/cli/stats/collectors/openapi/oas32.d.ts +15 -0
  13. package/dist/cli/stats/collectors/openapi/oas32.js +1 -0
  14. package/dist/cli/stats/index.js +1 -1
  15. package/dist/cli/telemetry/index.js +1 -1
  16. package/dist/cli/utils/listen-stdin.d.ts +10 -0
  17. package/dist/cli/utils/listen-stdin.js +2 -0
  18. package/dist/client/App.js +1 -1
  19. package/dist/client/ErrorBoundary.js +1 -1
  20. package/dist/client/TestProvider.js +1 -1
  21. package/dist/client/app/DevModeFloatingBar/index.d.ts +3 -0
  22. package/dist/client/app/DevModeFloatingBar/index.js +43 -0
  23. package/dist/client/app/Feedback/useSubmitFeedback.js +1 -1
  24. package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
  25. package/dist/client/app/hooks/index.d.ts +1 -0
  26. package/dist/client/app/hooks/index.js +1 -1
  27. package/dist/client/app/hooks/useAnchorPositioning.d.ts +6 -0
  28. package/dist/client/app/hooks/useAnchorPositioning.js +1 -0
  29. package/dist/client/app/hooks/useAutoScroll.js +1 -1
  30. package/dist/client/app/hooks/useRouteChangeTracker.js +1 -1
  31. package/dist/client/app/hooks/utils/pathname-matches-active-section.d.ts +6 -0
  32. package/dist/client/app/hooks/utils/pathname-matches-active-section.js +1 -0
  33. package/dist/client/app/markdoc/custom-components/html-script.js +1 -0
  34. package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.js +1 -0
  35. package/dist/client/app/markdoc/custom-components/openapi/openapi-response-sample.js +1 -0
  36. package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -0
  37. package/dist/client/app/markdoc/hooks/use-store.js +1 -0
  38. package/dist/client/app/search/useAiSearch.js +1 -1
  39. package/dist/client/app/search/useSearch.js +1 -1
  40. package/dist/client/browser-entry.js +5 -5
  41. package/dist/client/constants/common.d.ts +2 -0
  42. package/dist/client/constants/common.js +1 -0
  43. package/dist/client/providers/hooks.js +1 -1
  44. package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
  45. package/dist/client/runtime/loader.js +1 -1
  46. package/dist/client/runtime/useSocketMessages.js +1 -1
  47. package/dist/{server/plugins/asyncapi-docs/template → client/templates/asyncapi-docs}/helpers.d.ts +3 -3
  48. package/dist/client/templates/asyncapi-docs/helpers.js +1 -0
  49. package/dist/{server/plugins/asyncapi-docs/template/AsyncApiDocs.d.ts → client/templates/asyncapi-docs/template.d.ts} +1 -1
  50. package/dist/client/templates/asyncapi-docs/template.js +11 -0
  51. package/dist/client/templates/openapi-docs/helpers.js +5 -0
  52. package/dist/{server/plugins/openapi-docs/template/OpenAPIDocs.d.ts → client/templates/openapi-docs/template.d.ts} +1 -1
  53. package/dist/{server/plugins/openapi-docs/template/OpenAPIDocs.js → client/templates/openapi-docs/template.js} +1 -1
  54. package/dist/client/utils/catalog/inject-catalog-items.d.ts +1 -1
  55. package/dist/client/utils/catalog/inject-catalog-items.js +1 -1
  56. package/dist/constants/catalog-entities.d.ts +12 -0
  57. package/dist/constants/catalog-entities.js +1 -0
  58. package/dist/constants/common.d.ts +2 -2
  59. package/dist/constants/common.js +1 -1
  60. package/dist/constants/l10n/langs/ar.js +1 -1
  61. package/dist/constants/l10n/langs/de.js +1 -1
  62. package/dist/constants/l10n/langs/en.js +1 -1
  63. package/dist/constants/l10n/langs/es.js +1 -1
  64. package/dist/constants/l10n/langs/fr.js +1 -1
  65. package/dist/constants/l10n/langs/hi.js +1 -1
  66. package/dist/constants/l10n/langs/it.js +1 -1
  67. package/dist/constants/l10n/langs/ja.js +1 -1
  68. package/dist/constants/l10n/langs/ko.js +1 -1
  69. package/dist/constants/l10n/langs/pl.js +1 -1
  70. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  71. package/dist/constants/l10n/langs/pt.js +1 -1
  72. package/dist/constants/l10n/langs/ru.js +1 -1
  73. package/dist/constants/l10n/langs/uk.js +1 -1
  74. package/dist/constants/l10n/langs/zh.js +1 -1
  75. package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/get-inner-text.d.ts +1 -1
  76. package/dist/markdoc/helpers/get-inner-text.js +2 -0
  77. package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/get-variable.d.ts +2 -2
  78. package/dist/markdoc/helpers/get-variable.js +1 -0
  79. package/dist/markdoc/nodes/fence/index.js +1 -0
  80. package/dist/markdoc/nodes/heading.js +1 -0
  81. package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/index.d.ts +6 -6
  82. package/dist/markdoc/tags/json-example.d.ts +3 -0
  83. package/dist/markdoc/tags/json-schema.d.ts +3 -0
  84. package/dist/markdoc/tags/openapi-code-sample.d.ts +3 -0
  85. package/dist/markdoc/tags/openapi-example.d.ts +3 -0
  86. package/dist/markdoc/tags/openapi-response-sample.d.ts +3 -0
  87. package/dist/markdoc/tags/replay-openapi.d.ts +3 -0
  88. package/dist/markdoc/types.d.ts +8 -0
  89. package/dist/markdoc/types.js +0 -0
  90. package/dist/server/api-routes/import-api-routes-handlers.js +1 -1
  91. package/dist/server/api-routes/run-api-routes-worker.js +1 -1
  92. package/dist/server/config/env-config.js +1 -0
  93. package/dist/{config → server/config}/env-schema.d.ts +9 -6
  94. package/dist/{config → server/config}/env-schemas/database.d.ts +1 -1
  95. package/dist/server/config/env-schemas/database.js +1 -0
  96. package/dist/{config → server/config}/env-schemas/environment-detection.d.ts +2 -2
  97. package/dist/{config → server/config}/env-schemas/organization-project.d.ts +3 -0
  98. package/dist/{config → server/config}/env-schemas/organization-project.js +1 -1
  99. package/dist/{config → server/config}/env-schemas/search.d.ts +2 -2
  100. package/dist/server/config/env-schemas/search.js +1 -0
  101. package/dist/server/constants/common.d.ts +3 -0
  102. package/dist/server/constants/common.js +1 -1
  103. package/dist/server/constants/feedback.d.ts +6 -0
  104. package/dist/server/constants/feedback.js +1 -0
  105. package/dist/server/constants/plugins/catalog-entities.d.ts +0 -11
  106. package/dist/server/constants/plugins/catalog-entities.js +1 -1
  107. package/dist/server/constants/plugins/search.d.ts +0 -4
  108. package/dist/server/constants/plugins/search.js +1 -1
  109. package/dist/server/entitlements/entitlements-provider.js +1 -1
  110. package/dist/server/esbuild/esbuild-logger.js +1 -1
  111. package/dist/server/esbuild/esbuild.js +1 -1
  112. package/dist/server/esbuild/plugins/assets-resolver.js +1 -1
  113. package/dist/server/esbuild/plugins/esbuild-compile-resolver.js +1 -1
  114. package/dist/server/esbuild/plugins/styled-components-ssr.js +1 -1
  115. package/dist/server/esbuild/plugins/themes-resolver.js +2 -2
  116. package/dist/server/{config/external-plugins.d.ts → external-plugins/resolve-external-plugins.d.ts} +2 -2
  117. package/dist/server/{config/external-plugins.js → external-plugins/resolve-external-plugins.js} +1 -1
  118. package/dist/server/fs/cache.js +1 -1
  119. package/dist/server/fs/last-modified-tracker.js +1 -1
  120. package/dist/server/fs/utils/is-loader-cache-enabled.js +1 -1
  121. package/dist/server/node-bundle-entry.js +1 -1
  122. package/dist/server/plugins/analytics/adobe/index.js +1 -1
  123. package/dist/server/plugins/analytics/amplitude/index.js +1 -1
  124. package/dist/server/plugins/analytics/fullstory/index.js +1 -1
  125. package/dist/server/plugins/analytics/ga/index.js +1 -1
  126. package/dist/server/plugins/analytics/gtm/browser-hooks.js +1 -1
  127. package/dist/server/plugins/analytics/gtm/index.js +1 -1
  128. package/dist/server/plugins/analytics/heap/index.js +1 -1
  129. package/dist/server/plugins/analytics/rudderstack/index.js +1 -1
  130. package/dist/server/plugins/analytics/segment/browser-hooks.js +1 -1
  131. package/dist/server/plugins/analytics/segment/build-script.js +5 -2
  132. package/dist/server/plugins/analytics/segment/index.js +1 -1
  133. package/dist/server/plugins/asyncapi-docs/index.js +1 -1
  134. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.js +37 -37
  135. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
  136. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +2 -2
  137. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
  138. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
  139. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
  140. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
  141. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +1 -1
  142. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
  143. package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
  144. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  145. package/dist/server/plugins/config-parser/loaders/redocly-config-loader.js +1 -1
  146. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
  147. package/dist/server/plugins/default-theme/index.js +1 -1
  148. package/dist/server/plugins/entitlements/index.js +1 -1
  149. package/dist/server/plugins/lifecycle.js +2 -2
  150. package/dist/server/plugins/markdown/attribute-resolvers/code-walkthrough/filesets-resolver.js +1 -1
  151. package/dist/server/plugins/markdown/attribute-resolvers/resolve-code-snippet-from-file.js +1 -1
  152. package/dist/server/plugins/markdown/attribute-resolvers/resolve-html-href.js +1 -1
  153. package/dist/server/plugins/markdown/attribute-resolvers/resolve-html-source-attribute.js +1 -1
  154. package/dist/server/plugins/markdown/attribute-resolvers/resolve-image-src-set.js +1 -1
  155. package/dist/server/plugins/markdown/attribute-resolvers/resolve-image-src.js +1 -1
  156. package/dist/server/plugins/markdown/attribute-resolvers/resolve-json-example-ref.js +1 -1
  157. package/dist/server/plugins/markdown/attribute-resolvers/resolve-json-schema-ref.js +1 -1
  158. package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
  159. package/dist/server/plugins/markdown/attribute-resolvers/resolve-native-md-link.js +1 -1
  160. package/dist/server/plugins/markdown/attribute-resolvers/resolve-nav-links.js +1 -1
  161. package/dist/server/plugins/markdown/attribute-resolvers/resolve-open-api-ref.js +1 -1
  162. package/dist/server/plugins/markdown/attribute-resolvers/resolve-parsed-yaml.js +1 -1
  163. package/dist/server/plugins/markdown/attribute-resolvers/resolve-raw-content.js +1 -1
  164. package/dist/server/plugins/markdown/attribute-resolvers/resolve-relative-or-cdn-icon.js +1 -1
  165. package/dist/server/plugins/markdown/attribute-resolvers/resolve-relative-path.js +1 -1
  166. package/dist/server/plugins/markdown/attribute-resolvers/resolve-sample-from-json-schema.js +1 -1
  167. package/dist/server/plugins/markdown/attribute-resolvers/resolve-svg-content.js +1 -1
  168. package/dist/server/plugins/markdown/markdoc/import-user-tags.js +1 -1
  169. package/dist/server/plugins/markdown/markdoc/markdoc-options.js +1 -1
  170. package/dist/server/plugins/markdown/markdoc/partials.js +1 -1
  171. package/dist/server/plugins/markdown/markdoc/plugins/headings.js +1 -1
  172. package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.js +1 -1
  173. package/dist/server/plugins/markdown/markdoc/plugins/utils.js +1 -1
  174. package/dist/server/plugins/markdown/runtime-transform.js +1 -1
  175. package/dist/server/plugins/markdown/search/get-ai-search-documents.js +1 -1
  176. package/dist/server/plugins/markdown/search/get-search-documents.js +2 -2
  177. package/dist/server/plugins/markdown/search/nodes/section-node.js +1 -1
  178. package/dist/server/plugins/markdown/search/search-resolver.js +1 -1
  179. package/dist/server/plugins/markdown/search/to-markdown.js +17 -13
  180. package/dist/server/plugins/markdown/search/walk-sections.js +1 -1
  181. package/dist/server/plugins/markdown/utils/stringify-tag-children-objects.js +1 -1
  182. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +1 -0
  183. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +1 -1
  184. package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +3 -2
  185. package/dist/server/plugins/mcp/docs-mcp/tools/search.js +6 -1
  186. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  187. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
  188. package/dist/server/plugins/mcp/servers/docs-server.d.ts +3 -1
  189. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  190. package/dist/server/plugins/mcp/types.d.ts +7 -0
  191. package/dist/server/plugins/openapi-docs/index.js +1 -1
  192. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +29 -29
  193. package/dist/server/plugins/openapi-docs/search-indexer.js +1 -1
  194. package/dist/server/plugins/scorecard-classic/get-scorecard-config.d.ts +1 -1
  195. package/dist/server/plugins/scorecard-classic/index.js +1 -1
  196. package/dist/server/plugins/scorecard-classic/lint.js +1 -1
  197. package/dist/server/plugins/scorecards/database/scorecards-config-service.js +1 -1
  198. package/dist/server/plugins/scorecards/plugin.js +1 -1
  199. package/dist/server/plugins/scorecards/workers/run-scorecards-worker.js +1 -1
  200. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.d.ts +11 -0
  201. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +1 -0
  202. package/dist/server/plugins/search/documents/search-documents.js +1 -1
  203. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  204. package/dist/server/plugins/search/engines/typesense/index.js +1 -1
  205. package/dist/server/plugins/search/index.js +1 -1
  206. package/dist/server/plugins/search/llmstxt/index.js +1 -1
  207. package/dist/server/plugins/search/utils.d.ts +2 -0
  208. package/dist/server/plugins/search/utils.js +2 -2
  209. package/dist/server/plugins/sidebars/index.js +2 -2
  210. package/dist/server/plugins/sso/index.js +1 -1
  211. package/dist/server/providers/database/base-repository.js +1 -1
  212. package/dist/server/providers/database/database-connection-factory.js +1 -1
  213. package/dist/server/providers/database/database-preconnect-service.js +1 -1
  214. package/dist/server/providers/database/databases/sqld-sqlite/drizzle.config.js +1 -1
  215. package/dist/server/ssr/render.js +1 -1
  216. package/dist/server/ssr/server-side-props/get-server-props-from-user-handler.js +1 -1
  217. package/dist/server/ssr/utils.js +1 -1
  218. package/dist/server/store.d.ts +1 -1
  219. package/dist/server/store.js +1 -1
  220. package/dist/server/telemetry/index.js +1 -1
  221. package/dist/server/tools/notifiers/formatter.js +1 -1
  222. package/dist/server/tools/notifiers/helpers/colors.js +1 -1
  223. package/dist/server/tools/notifiers/logger.js +1 -1
  224. package/dist/server/tools/notifiers/reporter.d.ts +0 -1
  225. package/dist/server/tools/notifiers/reporter.js +6 -7
  226. package/dist/server/tools/notifiers/terminal-manager.js +5 -4
  227. package/dist/server/types/plugins/markdown.d.ts +0 -7
  228. package/dist/server/utils/ai-agent-detection.d.ts +16 -0
  229. package/dist/server/utils/ai-agent-detection.js +1 -0
  230. package/dist/server/utils/envs/load-env-variables.js +1 -1
  231. package/dist/server/utils/fs.js +1 -1
  232. package/dist/server/utils/index.d.ts +2 -2
  233. package/dist/server/utils/index.js +1 -1
  234. package/dist/server/utils/is-catalog-entities-enabled.js +1 -1
  235. package/dist/server/utils/is-scorecards-enabled.js +1 -1
  236. package/dist/server/utils/lifecycle-hooks.d.ts +2 -2
  237. package/dist/server/utils/lifecycle-hooks.js +1 -1
  238. package/dist/server/utils/rbac.js +1 -1
  239. package/dist/server/utils/report-all-errors.js +1 -1
  240. package/dist/server/utils/set-execution-mode.d.ts +5 -0
  241. package/dist/server/utils/set-execution-mode.js +1 -0
  242. package/dist/server/version.js +1 -1
  243. package/dist/server/web-server/auth.d.ts +2 -0
  244. package/dist/server/web-server/auth.js +4 -4
  245. package/dist/server/web-server/handle-api-route-request.js +1 -1
  246. package/dist/server/web-server/http.js +2 -2
  247. package/dist/server/web-server/middleware/apiKeyMiddleware.js +1 -1
  248. package/dist/server/web-server/middleware/catalogAuthMiddleware.js +1 -1
  249. package/dist/server/web-server/middleware/corsMiddleware.js +1 -1
  250. package/dist/server/web-server/middleware/dynamic-middleware/dynamic-middleware.js +1 -1
  251. package/dist/server/web-server/middleware/idleTimeoutMiddleware.js +1 -1
  252. package/dist/server/web-server/middleware/responseHeadersMiddleware.js +1 -1
  253. package/dist/server/web-server/mime-types.js +1 -1
  254. package/dist/server/web-server/routes/auth.js +1 -1
  255. package/dist/server/web-server/routes/cors-proxy.d.ts +5 -0
  256. package/dist/server/web-server/routes/cors-proxy.js +2 -0
  257. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  258. package/dist/server/web-server/routes/error.js +1 -1
  259. package/dist/server/web-server/routes/feedback.js +1 -1
  260. package/dist/server/web-server/routes/helpers/get-md-asset-pathname.d.ts +2 -0
  261. package/dist/server/web-server/routes/helpers/get-md-asset-pathname.js +1 -0
  262. package/dist/server/web-server/routes/index.js +1 -1
  263. package/dist/server/web-server/routes/info.js +1 -1
  264. package/dist/server/web-server/routes/mcp-oauth.js +1 -1
  265. package/dist/server/web-server/routes/otel/otel.js +1 -1
  266. package/dist/server/web-server/routes/page-data.js +1 -1
  267. package/dist/server/web-server/routes/path-prefix-redirect.js +1 -1
  268. package/dist/server/web-server/routes/resolve-route.js +1 -1
  269. package/dist/server/web-server/routes/semantic-search.d.ts +4 -0
  270. package/dist/server/web-server/routes/semantic-search.js +1 -0
  271. package/dist/server/workers/worker-pool.js +1 -1
  272. package/dist/{server/utils → utils}/slugger.d.ts +13 -0
  273. package/package.json +13 -13
  274. package/dist/cli/prepare/copy-env-files.js +0 -1
  275. package/dist/cli/prepare/index.js +0 -1
  276. package/dist/cli/stats/collectors/openapi.js +0 -1
  277. package/dist/client/app/ErrorBubble/index.d.ts +0 -3
  278. package/dist/client/app/ErrorBubble/index.js +0 -59
  279. package/dist/client/app/PageCounter/index.d.ts +0 -3
  280. package/dist/client/app/PageCounter/index.js +0 -64
  281. package/dist/config/env-config.js +0 -1
  282. package/dist/config/env-schemas/database.js +0 -1
  283. package/dist/config/env-schemas/search.js +0 -1
  284. package/dist/server/plugins/asyncapi-docs/template/AsyncApiDocs.js +0 -11
  285. package/dist/server/plugins/asyncapi-docs/template/helpers.js +0 -1
  286. package/dist/server/plugins/markdown/markdoc/custom-components/html-script.js +0 -1
  287. package/dist/server/plugins/markdown/markdoc/custom-components/openapi/openapi-code-sample.js +0 -1
  288. package/dist/server/plugins/markdown/markdoc/custom-components/openapi/openapi-response-sample.js +0 -1
  289. package/dist/server/plugins/markdown/markdoc/custom-components/openapi/replay-openapi.js +0 -1
  290. package/dist/server/plugins/markdown/markdoc/helpers/get-inner-text.js +0 -2
  291. package/dist/server/plugins/markdown/markdoc/helpers/get-variable.js +0 -1
  292. package/dist/server/plugins/markdown/markdoc/hooks/use-store.js +0 -1
  293. package/dist/server/plugins/markdown/markdoc/nodes/fence/index.js +0 -1
  294. package/dist/server/plugins/markdown/markdoc/nodes/heading.js +0 -1
  295. package/dist/server/plugins/markdown/markdoc/tags/json-example.d.ts +0 -3
  296. package/dist/server/plugins/markdown/markdoc/tags/json-schema.d.ts +0 -3
  297. package/dist/server/plugins/markdown/markdoc/tags/openapi-code-sample.d.ts +0 -3
  298. package/dist/server/plugins/markdown/markdoc/tags/openapi-example.d.ts +0 -3
  299. package/dist/server/plugins/markdown/markdoc/tags/openapi-response-sample.d.ts +0 -3
  300. package/dist/server/plugins/markdown/markdoc/tags/replay-openapi.d.ts +0 -3
  301. package/dist/server/plugins/openapi-docs/template/helpers.js +0 -5
  302. package/dist/server/plugins/search/ai-indexer/prepare-ai-search-documents.d.ts +0 -6
  303. package/dist/server/plugins/search/ai-indexer/prepare-ai-search-documents.js +0 -1
  304. /package/dist/cli/{prepare → build}/analytics/collect-analytics.d.ts +0 -0
  305. /package/dist/cli/{prepare → build}/analytics/collect-analytics.js +0 -0
  306. /package/dist/cli/{prepare → build}/analytics/collectors/get-api-functions-usage.d.ts +0 -0
  307. /package/dist/cli/{prepare → build}/analytics/collectors/get-api-functions-usage.js +0 -0
  308. /package/dist/cli/{prepare → build}/analytics/collectors/get-async-api-usage.d.ts +0 -0
  309. /package/dist/cli/{prepare → build}/analytics/collectors/get-async-api-usage.js +0 -0
  310. /package/dist/cli/{prepare → build}/analytics/collectors/get-config-stats-usage.d.ts +0 -0
  311. /package/dist/cli/{prepare → build}/analytics/collectors/get-config-stats-usage.js +0 -0
  312. /package/dist/cli/{prepare → build}/analytics/collectors/get-file-extensions-usage.d.ts +0 -0
  313. /package/dist/cli/{prepare → build}/analytics/collectors/get-file-extensions-usage.js +0 -0
  314. /package/dist/cli/{prepare → build}/analytics/collectors/get-frontmatter-usage.d.ts +0 -0
  315. /package/dist/cli/{prepare → build}/analytics/collectors/get-frontmatter-usage.js +0 -0
  316. /package/dist/cli/{prepare → build}/analytics/collectors/get-markdoc-usage.d.ts +0 -0
  317. /package/dist/cli/{prepare → build}/analytics/collectors/get-markdoc-usage.js +0 -0
  318. /package/dist/cli/{prepare → build}/analytics/collectors/get-nested-configs-usage.d.ts +0 -0
  319. /package/dist/cli/{prepare → build}/analytics/collectors/get-nested-configs-usage.js +0 -0
  320. /package/dist/cli/{prepare → build}/analytics/collectors/get-processed-config-stats-usage.d.ts +0 -0
  321. /package/dist/cli/{prepare → build}/analytics/collectors/get-processed-config-stats-usage.js +0 -0
  322. /package/dist/cli/{prepare → build}/analytics/collectors/get-refs-usage.d.ts +0 -0
  323. /package/dist/cli/{prepare → build}/analytics/collectors/get-refs-usage.js +0 -0
  324. /package/dist/cli/{prepare → build}/analytics/collectors/get-theme-folder-usage.d.ts +0 -0
  325. /package/dist/cli/{prepare → build}/analytics/collectors/get-theme-folder-usage.js +0 -0
  326. /package/dist/cli/{prepare → build}/copy-env-files.d.ts +0 -0
  327. /package/dist/cli/{prepare → build}/libsql/copy-prebuilt-binary.d.ts +0 -0
  328. /package/dist/cli/{prepare → build}/libsql/copy-prebuilt-binary.js +0 -0
  329. /package/dist/cli/{prepare → build}/libsql/get-current-platform.d.ts +0 -0
  330. /package/dist/cli/{prepare → build}/libsql/get-current-platform.js +0 -0
  331. /package/dist/client/app/{ErrorBubble → DevModeFloatingBar}/DetailedErrors.d.ts +0 -0
  332. /package/dist/client/app/{ErrorBubble → DevModeFloatingBar}/DetailedErrors.js +0 -0
  333. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/html-script.d.ts +0 -0
  334. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/index.d.ts +0 -0
  335. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/index.js +0 -0
  336. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/explain-step.d.ts +0 -0
  337. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/explain-step.js +0 -0
  338. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/get-operation-info-by-id.d.ts +0 -0
  339. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/get-operation-info-by-id.js +0 -0
  340. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/get-operation-info-by-pointer.d.ts +0 -0
  341. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/get-operation-info-by-pointer.js +0 -0
  342. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/get-operation.d.ts +0 -0
  343. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/get-operation.js +0 -0
  344. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/index.d.ts +0 -0
  345. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/index.js +0 -0
  346. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/index.d.ts +0 -0
  347. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/index.js +0 -0
  348. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/operation-identifier.d.ts +0 -0
  349. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/operation-identifier.js +0 -0
  350. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/operation-info.d.ts +0 -0
  351. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/operation-info.js +0 -0
  352. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/operation-parameters.d.ts +0 -0
  353. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/get-operation/types/operation-parameters.js +0 -0
  354. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/index.d.ts +0 -0
  355. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/index.js +0 -0
  356. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/json-example.d.ts +0 -0
  357. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/json-example.js +0 -0
  358. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/json-schema.d.ts +0 -0
  359. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/json-schema.js +0 -0
  360. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/openapi-code-sample.d.ts +0 -0
  361. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/openapi-example.d.ts +0 -0
  362. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/openapi-example.js +0 -0
  363. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/openapi-response-sample.d.ts +0 -0
  364. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/replay-openapi.d.ts +0 -0
  365. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/step-by-step-wrapper.d.ts +0 -0
  366. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/openapi/step-by-step-wrapper.js +0 -0
  367. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/styled.elements.d.ts +0 -0
  368. /package/dist/{server/plugins/markdown → client/app}/markdoc/custom-components/styled.elements.js +0 -0
  369. /package/dist/{server/plugins/markdown → client/app}/markdoc/hooks/use-store.d.ts +0 -0
  370. /package/dist/{server/plugins/openapi-docs/template → client/templates/openapi-docs}/helpers.d.ts +0 -0
  371. /package/dist/{server/plugins/openapi-docs/template → client/templates/openapi-docs}/mock-server-config.d.ts +0 -0
  372. /package/dist/{server/plugins/openapi-docs/template → client/templates/openapi-docs}/mock-server-config.js +0 -0
  373. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/definition-path.d.ts +0 -0
  374. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/definition-path.js +0 -0
  375. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/index.d.ts +0 -0
  376. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/index.js +0 -0
  377. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/json-example-ref.d.ts +0 -0
  378. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/json-example-ref.js +0 -0
  379. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/json-schema-ref.d.ts +0 -0
  380. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/json-schema-ref.js +0 -0
  381. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/parsed-yaml.d.ts +0 -0
  382. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/parsed-yaml.js +0 -0
  383. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/raw-content.d.ts +0 -0
  384. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/raw-content.js +0 -0
  385. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/sample-from-json-schema.d.ts +0 -0
  386. /package/dist/{server/plugins/markdown/markdoc → markdoc}/attributes/sample-from-json-schema.js +0 -0
  387. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/extract-rbac-from-condition-node.d.ts +0 -0
  388. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/extract-rbac-from-condition-node.js +0 -0
  389. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/get-node-attribute.d.ts +0 -0
  390. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/get-node-attribute.js +0 -0
  391. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-code-node.d.ts +0 -0
  392. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-code-node.js +0 -0
  393. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-conditional-node.d.ts +0 -0
  394. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-conditional-node.js +0 -0
  395. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-content-node.d.ts +0 -0
  396. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-content-node.js +0 -0
  397. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-example-node.d.ts +0 -0
  398. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-example-node.js +0 -0
  399. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-fence-node.d.ts +0 -0
  400. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-fence-node.js +0 -0
  401. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-function.d.ts +0 -0
  402. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-function.js +0 -0
  403. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-list-node.d.ts +0 -0
  404. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-list-node.js +0 -0
  405. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-node.d.ts +0 -0
  406. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-node.js +0 -0
  407. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-string-node.d.ts +0 -0
  408. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-string-node.js +0 -0
  409. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-tag.d.ts +0 -0
  410. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-tag.js +0 -0
  411. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-text-node.d.ts +0 -0
  412. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-text-node.js +0 -0
  413. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-variable.d.ts +0 -0
  414. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/guards/is-variable.js +0 -0
  415. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/remove-markdoc-tags.d.ts +0 -0
  416. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/remove-markdoc-tags.js +0 -0
  417. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/set-node-attribute-value.d.ts +0 -0
  418. /package/dist/{server/plugins/markdown/markdoc → markdoc}/helpers/set-node-attribute-value.js +0 -0
  419. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/fence/escape-html.d.ts +0 -0
  420. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/fence/escape-html.js +0 -0
  421. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/fence/index.d.ts +0 -0
  422. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/gfm-list-item.d.ts +0 -0
  423. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/gfm-list-item.js +0 -0
  424. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/heading.d.ts +0 -0
  425. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/index.d.ts +0 -0
  426. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/index.js +0 -0
  427. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/table.d.ts +0 -0
  428. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/table.js +0 -0
  429. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/text.d.ts +0 -0
  430. /package/dist/{server/plugins/markdown/markdoc → markdoc}/nodes/text.js +0 -0
  431. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/index.js +0 -0
  432. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/json-example.js +0 -0
  433. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/json-schema.js +0 -0
  434. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/openapi-code-sample.js +0 -0
  435. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/openapi-example.js +0 -0
  436. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/openapi-response-sample.js +0 -0
  437. /package/dist/{server/plugins/markdown/markdoc → markdoc}/tags/replay-openapi.js +0 -0
  438. /package/dist/{config → server/config}/env-config.d.ts +0 -0
  439. /package/dist/{config → server/config}/env-schema.js +0 -0
  440. /package/dist/{config → server/config}/env-schemas/api-urls.d.ts +0 -0
  441. /package/dist/{config → server/config}/env-schemas/api-urls.js +0 -0
  442. /package/dist/{config → server/config}/env-schemas/auth.d.ts +0 -0
  443. /package/dist/{config → server/config}/env-schemas/auth.js +0 -0
  444. /package/dist/{config → server/config}/env-schemas/catalog.d.ts +0 -0
  445. /package/dist/{config → server/config}/env-schemas/catalog.js +0 -0
  446. /package/dist/{config → server/config}/env-schemas/environment-detection.js +0 -0
  447. /package/dist/{config → server/config}/env-schemas/feature-flags.d.ts +0 -0
  448. /package/dist/{config → server/config}/env-schemas/feature-flags.js +0 -0
  449. /package/dist/{config → server/config}/env-schemas/scorecards.d.ts +0 -0
  450. /package/dist/{config → server/config}/env-schemas/scorecards.js +0 -0
  451. /package/dist/{config → server/config}/env-schemas/server-config.d.ts +0 -0
  452. /package/dist/{config → server/config}/env-schemas/server-config.js +0 -0
  453. /package/dist/{config → server/config}/env-schemas/site.d.ts +0 -0
  454. /package/dist/{config → server/config}/env-schemas/site.js +0 -0
  455. /package/dist/{config → server/config}/env-schemas/ssr.d.ts +0 -0
  456. /package/dist/{config → server/config}/env-schemas/ssr.js +0 -0
  457. /package/dist/{config → server/config}/env-schemas/telemetry.d.ts +0 -0
  458. /package/dist/{config → server/config}/env-schemas/telemetry.js +0 -0
  459. /package/dist/{config → server/config}/env-schemas/test.d.ts +0 -0
  460. /package/dist/{config → server/config}/env-schemas/test.js +0 -0
  461. /package/dist/server/{config → external-plugins}/resolve-module.d.ts +0 -0
  462. /package/dist/server/{config → external-plugins}/resolve-module.js +0 -0
  463. /package/dist/{server/utils → utils}/conflict-resolvers.d.ts +0 -0
  464. /package/dist/{server/utils → utils}/conflict-resolvers.js +0 -0
  465. /package/dist/{server/utils → utils}/slugger.js +0 -0
@@ -1 +1 @@
1
- import h from"path";import O from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as D,REDOCLY_ROUTE_RBAC as R}from"@redocly/config";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as P,ServerRoutes as j,PUBLIC_RBAC_SCOPE_ITEM as A,RBAC_ALL_OTHER_TEAMS as u,DEFAULT_RBAC_SCOPE as _}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as L,PUBLIC_API_DEFINITIONS_FOLDER as g,PUBLIC_ASSETS_FOLDER as F}from"../constants/common.js";import{removeTrailingSlash as w}from"../../utils/url/remove-trailing-slash.js";import{parsePathVersions as N}from"../../utils/path/parse-path-versions.js";import{reporter as B}from"../tools/notifiers/reporter.js";import{bold as k}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as W}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as U}from"../../utils/guards/is-truthy.js";import{canExpandConfig as b,expandRbacConfig as M,getTeamFolderDefaults as $,parseTeamFoldersTemplate as v,parseTeamNameTemplate as Y}from"./rbac-expand.js";import{getUserParamsFromCookies as z}from"../web-server/auth.js";import{getDeeperGlobPattern as H}from"./globs.js";import{EntitlementsProvider as G}from"../entitlements/entitlements-provider.js";const S=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],K=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function dt(t,e){const n=S.indexOf(t.toUpperCase()),r=S.indexOf(e.toUpperCase());return n>r?t:e}const I={};function y(t,e){if(!t?.content)return A;const n=t.content,{slug:r,fsPath:o}=e;if(!r&&!o)return A;const s=f=>{const m=I[f]||O(f);return I[f]=m,!!(r&&m(r))||!!(o&&m(o))};if(V(r||o||"")&&Object.keys(n).filter(T=>s(T)).length===0)return n[_]||A;const c=Object.keys(n).filter(f=>s(f));if(c.length==0)return A;const l=c.map(f=>O.scan(f,{tokens:!0,parts:!0}));let p=l[0];for(let f=1;f<l.length;f++)p=H(p,l[f]);return n[p.input]}function ht(t,e,n={},r=!1){if(r&&Object.keys(n).length===0)return e.isAuthenticated;const o=n.features?.[t];return o?e.teams.some(s=>o[s]&&o[s].toLowerCase()!=="none"):!0}function Rt(t,e){return E(t,{isAuthenticated:!1,teams:[P]},e.rbac||{},e.requiresLogin||!1)}function E(t,e={},n={},r=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(j).some(c=>{const l=c.split(":")[0].replace(/\/$/,"");return t.slug===l||t.slug?.startsWith(c)})||typeof t.slug=="string"&&t.slug?.endsWith("/mcp")&&G.instance().canAccessFeature("mcp"))return!0;if(r&&Object.keys(n).length===0)return!!e.isAuthenticated;const o=M(n,e.teams||[]),s=t[D]||y(o,t[R]||{});if(Object.keys(s||{}).length===0)return!1;if(Object.keys(s).length===1&&s[u]&&s[u].toLowerCase()!=="none")return!0;const i=(e?.email?[...e?.teams||[],e?.email]:e?.teams)||[],a=[];for(const c of i??[])s[c]?a.push(s[c]):s[u]&&c!==e?.email&&a.push(s[u]);return a.length?a.some(c=>c.toLowerCase()!=="none"):!1}function At(t,e,n,r){if(!t.startsWith(g)&&!t.startsWith(L))return!0;const o=t.replace(new RegExp(`^${g}/`),"").replace(new RegExp(`^${L}/`),""),i=o==="."?"":o,a={[R]:{slug:t,fsPath:i},slug:t};return E(a,r,e,n)}function yt(t,e,n,r,o){if(!t.startsWith(F))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!s)return!0;const i=r[s];if(!i)return!0;const{base:a,ext:c}=h.parse(t),l=a.split(".")[0],p=c.split(".").join(""),m=i==="."?"":i,T={[R]:{slug:t,fsPath:h.posix.join(m,`${l}.${p}`)},slug:t};return E(T,o,e,n)}async function Et(t,e){const{isAuthenticated:n=!1,idpAccessToken:r,federatedAccessToken:o,federatedIdToken:s,...i}=await z(t,e),{teams:a=[]}=i;let c;return n?c=a.filter(l=>l!==P):c=[P],{isAuthenticated:n,idpAccessToken:r,teams:c,claims:i}}function C(t,e,n={},r=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const i=C(s,e,n,r);i!==void 0&&o.push(i)}return o}if(typeof t=="object"){if(!E(t,e,n,r))return;let o=!1;const s={};for(const i in t){if(i===D||i===R)continue;if(K.has(i)){s[i]=t[i];continue}const a=C(t[i],e,n,r);if(i==="items"&&Array.isArray(a)&&a.length===0&&t[i].length!==0){o=!0;continue}a!==void 0&&(s[i]=a)}return o?void 0:s}return t}function Tt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Pt(t,e){if(!e)return;const n=e.content;if(!n)return e;const r=Object.entries(n).flatMap(([s,i])=>s===_?[[s,i]]:[[s,i],...t.localeFolders.map(a=>[s.startsWith("/")?`/${a.toLocaleLowerCase()}${s}`:h.posix.join(t.localizationFolder,a,s),i])]),o=Object.fromEntries(r);return{...e,content:o}}async function xt(t,e){if(!e)return{};const n={},r=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=N(o)||{},i=h.dirname(o);return s?[s,i]:i}));for(const o of r)n[W(o)]=o;return n}const d=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function V(t){return t?t.split("/").filter(Boolean).some(n=>n.startsWith(".")):!1}const J=t=>{if(t&&d(t)&&("content"in t&&d(t.content)||"reunite"in t&&d(t.reunite)||"features"in t&&d(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(d))return e.every(n=>Object.values(n).every(r=>typeof r=="string"))}return!1},Ot=async t=>{if(t){if(Object.keys(t).length===0)return{};if(J(t))return Q(t);await B.panicOnContentError(`You are using an incorrect format of ${k("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},Q=t=>{const e={...t};if(e.content){const n={};for(const r in e.content)if(e.content[r]!==void 0){const o=w(r);n[o]=e.content[r]}e.content=n}return e};function Dt(t,e){const n=t.fsPath,r=t.slug,o=[];if(b(e)&&(n||r)){const s=[n,r].filter(U),i=v(e,s);if(i){const a=e?.teamNamePatterns?.map(l=>l.replace("{teamPathSegment}",i.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...a);const c=y({content:{...$(e),...e.content}},t);o.push(...x(c))}else{const a=y(e,t);o.push(...x(a))}}else{const s=y(e,t);o.push(...x(s))}return X(e,o)}function x(t){if(!t)return[];const e=[],n=u in t?{authenticated:t[u],anonymous:t[u]}:{};for(const[r,o]of Object.entries({...n,...t}))o.toLowerCase()!=="none"&&r!==u&&e.push(r);return e}function X(t,e){return e.map(r=>Y(t,r)??{teamName:r}).map(r=>r.projectRole&&r.projectRole!=="READ"?r.teamName?.toLowerCase().replace(r.projectRole?.toLowerCase?.()??"","read")??"":r.teamName?.toLowerCase()??"")}export{S as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Pt as applyL10nToRbacConfig,yt as canAccessAsset,ht as canAccessFeature,E as canAccessResource,At as canDownloadApiDefinition,X as expandTeamsForRead,x as extractTeamsFromScopeItems,C as filterDataByAccessDeep,Et as getAuthDetailsFromCookies,dt as getHigherRole,Dt as getRbacTeamsListForResource,y as getScopeItemsForResource,J as isRbacConfigValid,Rt as isResourcePubliclyAccessible,Q as normalizeRbacConfig,Ot as parseRbacConfig,Tt as parseTeamClaimToArray,xt as resolveDirectoryHashes};
1
+ import R from"path";import x from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as _,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as O,ServerRoutes as w,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as u,DEFAULT_RBAC_SCOPE as S}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_ASSETS_FOLDER as N}from"../constants/common.js";import{removeTrailingSlash as B}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as k}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as M}from"../../utils/path/parse-path-versions.js";import{reporter as W}from"../tools/notifiers/reporter.js";import{bold as U}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as $}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as b}from"../../utils/guards/is-truthy.js";import{canExpandConfig as v,expandRbacConfig as Y,getTeamFolderDefaults as z,parseTeamFoldersTemplate as H,parseTeamNameTemplate as K}from"./rbac-expand.js";import{getUserParamsFromCookies as G}from"../web-server/auth.js";import{getDeeperGlobPattern as V}from"./globs.js";import{EntitlementsProvider as J}from"../entitlements/entitlements-provider.js";const j=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],Q=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function yt(t,e){const n=j.indexOf(t.toUpperCase()),r=j.indexOf(e.toUpperCase());return n>r?t:e}const E={};function P(t,e){if(!t?.content)return y;const n=t.content,{slug:r,fsPath:s}=e;if(!r&&!s)return y;const o=f=>{const h=`slug:${f}`,m=E[h]??x(f);E[h]=m;const g=`fsPath:${f}`,L=E[g]??x(k(f));return E[g]=L,!!(r&&m(r))||!!(s&&L(s))};if(X(r||s||"")&&Object.keys(n).filter(m=>o(m)).length===0)return n[S]||y;const c=Object.keys(n).filter(f=>o(f));if(c.length==0)return y;const l=c.map(f=>x.scan(f,{tokens:!0,parts:!0}));let p=l[0];for(let f=1;f<l.length;f++)p=V(p,l[f]);return n[p.input]}function Et(t,e,n={},r=!1){if(r&&Object.keys(n).length===0)return e.isAuthenticated;const s=n.features?.[t];return s?e.teams.some(o=>s[o]&&s[o].toLowerCase()!=="none"):!0}function Pt(t,e){return T(t,{isAuthenticated:!1,teams:[O]},e.rbac||{},e.requiresLogin||!1)}function T(t,e={},n={},r=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(w).some(c=>{const l=c.split(":")[0].replace(/\/$/,"");return t.slug===l||t.slug?.startsWith(c)})||typeof t.slug=="string"&&t.slug?.endsWith("/mcp")&&J.instance().canAccessFeature("mcp"))return!0;if(r&&Object.keys(n).length===0)return!!e.isAuthenticated;const s=Y(n,e.teams||[]),o=t[_]||P(s,t[A]||{});if(Object.keys(o||{}).length===0)return!1;if(Object.keys(o).length===1&&o[u]&&o[u].toLowerCase()!=="none")return!0;const a=(e?.email?[...e?.teams||[],e?.email]:e?.teams)||[],i=[];for(const c of a??[])o[c]?i.push(o[c]):o[u]&&c!==e?.email&&i.push(o[u]);return i.length?i.some(c=>c.toLowerCase()!=="none"):!1}function Tt(t,e,n,r){if(!t.startsWith(C)&&!t.startsWith(I))return!0;const s=t.replace(new RegExp(`^${C}/`),"").replace(new RegExp(`^${I}/`),""),a=s==="."?"":s,i={[A]:{slug:t,fsPath:a},slug:t};return T(i,r,e,n)}function xt(t,e,n,r,s){if(!t.startsWith(N))return!0;const o=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!o)return!0;const a=r[o];if(!a)return!0;const{base:i,ext:c}=R.parse(t),l=i.split(".")[0],p=c.split(".").join(""),h=a==="."?"":a,m={[A]:{slug:t,fsPath:R.posix.join(h,`${l}.${p}`)},slug:t};return T(m,s,e,n)}async function Ot(t,e){const{isAuthenticated:n=!1,idpAccessToken:r,federatedAccessToken:s,federatedIdToken:o,...a}=await G(t,e),{teams:i=[]}=a;let c;return n?c=i.filter(l=>l!==O):c=[O],{isAuthenticated:n,idpAccessToken:r,teams:c,claims:a}}function F(t,e,n={},r=!1){if(!t)return t;if(Array.isArray(t)){const s=[];for(const o of t){const a=F(o,e,n,r);a!==void 0&&s.push(a)}return s}if(typeof t=="object"){if(!T(t,e,n,r))return;let s=!1;const o={};for(const a in t){if(a===_||a===A)continue;if(Q.has(a)){o[a]=t[a];continue}const i=F(t[a],e,n,r);if(a==="items"&&Array.isArray(i)&&i.length===0&&t[a].length!==0){s=!0;continue}i!==void 0&&(o[a]=i)}return s?void 0:o}return t}function Dt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function gt(t,e){if(!e)return;const n=e.content;if(!n)return e;const r=Object.entries(n).flatMap(([o,a])=>o===S?[[o,a]]:[[o,a],...t.localeFolders.map(i=>[o.startsWith("/")?`/${i.toLocaleLowerCase()}${o}`:R.posix.join(t.localizationFolder,i,o),a])]),s=Object.fromEntries(r);return{...e,content:s}}async function Lt(t,e){if(!e)return{};const n={},r=new Set((await t.scan()).flatMap(({relativePath:s})=>{const{versionFolderPath:o}=M(s)||{},a=R.dirname(s);return o?[o,a]:a}));for(const s of r)n[$(s)]=s;return n}const d=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function X(t){return t?t.split("/").filter(Boolean).some(n=>n.startsWith(".")):!1}const Z=t=>{if(t&&d(t)&&("content"in t&&d(t.content)||"reunite"in t&&d(t.reunite)||"features"in t&&d(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(d))return e.every(n=>Object.values(n).every(r=>typeof r=="string"))}return!1},_t=async t=>{if(t){if(Object.keys(t).length===0)return{};if(Z(t))return q(t);await W.panicOnContentError(`You are using an incorrect format of ${U("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},q=t=>{const e={...t};if(e.content){const n={};for(const r in e.content)if(e.content[r]!==void 0){const s=B(r);n[s]=e.content[r]}e.content=n}return e};function St(t,e){const n=t.fsPath,r=t.slug,s=[];if(v(e)&&(n||r)){const o=[n,r].filter(b),a=H(e,o);if(a){const i=e?.teamNamePatterns?.map(l=>l.replace("{teamPathSegment}",a.teamPathSegment).replace("{projectRole}","read"))??[];s.push(...i);const c=P({content:{...z(e),...e.content}},t);s.push(...D(c))}else{const i=P(e,t);s.push(...D(i))}}else{const o=P(e,t);s.push(...D(o))}return tt(e,s)}function D(t){if(!t)return[];const e=[],n=u in t?{authenticated:t[u],anonymous:t[u]}:{};for(const[r,s]of Object.entries({...n,...t}))s.toLowerCase()!=="none"&&r!==u&&e.push(r);return e}function tt(t,e){return e.map(r=>K(t,r)??{teamName:r}).map(r=>r.projectRole&&r.projectRole!=="READ"?r.teamName?.toLowerCase().replace(r.projectRole?.toLowerCase?.()??"","read")??"":r.teamName?.toLowerCase()??"")}export{j as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,gt as applyL10nToRbacConfig,xt as canAccessAsset,Et as canAccessFeature,T as canAccessResource,Tt as canDownloadApiDefinition,tt as expandTeamsForRead,D as extractTeamsFromScopeItems,F as filterDataByAccessDeep,Ot as getAuthDetailsFromCookies,yt as getHigherRole,St as getRbacTeamsListForResource,P as getScopeItemsForResource,Z as isRbacConfigValid,Pt as isResourcePubliclyAccessible,q as normalizeRbacConfig,_t as parseRbacConfig,Dt as parseTeamClaimToArray,Lt as resolveDirectoryHashes};
@@ -1 +1 @@
1
- import{envConfig as p}from"../../config/env-config.js";import{reporter as r}from"../tools/notifiers/reporter.js";import{isMarkdocError as d}from"../plugins/markdown/errors.js";import{telemetryTraceStep as m}from"../../cli/telemetry/helpers/trace-step.js";async function k(i){await m("build.validation_errors",async n=>{let e=0;for(const[a,c]of i.cache.errors.entries()){const f=a.split(":")[1];for(const o of c)d(o)?(r.reportMarkdocProblem(o),o.type!=="BROKEN_LINK"&&e++):await r.panicOnBuild(o.message,f)}const s=await i.getConfig();if(!p.isBuildMode)return;const t=r.getPageRenderProblems().length;n?.setAttribute("markdocErrors",e.toString()),n?.setAttribute("pageRenderErrors",t.toString()),e>0&&!s?.reunite?.ignoreMarkdocErrors?(r.printErrors(),await r.panic(`Need to fix ${e} Markdoc issue(s) or set the \`ignoreMarkdocErrors\` option to \`true\` in the \`reunite\` section of your \`redocly.yaml\``)):t>0&&(r.printErrors(),await r.panic(`Need to fix ${t} runtime error(s) in React pages`))})}export{k as reportAllErrors};
1
+ import{envConfig as p}from"../config/env-config.js";import{reporter as r}from"../tools/notifiers/reporter.js";import{isMarkdocError as d}from"../plugins/markdown/errors.js";import{telemetryTraceStep as m}from"../../cli/telemetry/helpers/trace-step.js";async function k(i){await m("build.validation_errors",async n=>{let e=0;for(const[a,c]of i.cache.errors.entries()){const f=a.split(":")[1];for(const o of c)d(o)?(r.reportMarkdocProblem(o),o.type!=="BROKEN_LINK"&&e++):await r.panicOnBuild(o.message,f)}const s=await i.getConfig();if(!p.isBuildMode)return;const t=r.getPageRenderProblems().length;n?.setAttribute("markdocErrors",e.toString()),n?.setAttribute("pageRenderErrors",t.toString()),e>0&&!s?.reunite?.ignoreMarkdocErrors?(r.printErrors(),await r.panic(`Need to fix ${e} Markdoc issue(s) or set the \`ignoreMarkdocErrors\` option to \`true\` in the \`reunite\` section of your \`redocly.yaml\``)):t>0&&(r.printErrors(),await r.panic(`Need to fix ${t} runtime error(s) in React pages`))})}export{k as reportAllErrors};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Must run before any module that reads envConfig.
3
+ */
4
+ declare const command: string;
5
+ //# sourceMappingURL=set-execution-mode.d.ts.map
@@ -0,0 +1 @@
1
+ const e=process.argv[2];e==="prepare"||e==="build"?process.env.REDOCLY_EXECUTION_MODE="build":e==="develop"&&(process.env.REDOCLY_EXECUTION_MODE="develop");
@@ -1 +1 @@
1
- import{createRequire as o}from"module";import{envConfig as e}from"../config/env-config.js";const t=e.isDevelopMode?"local":o(import.meta.url)("../../package.json").version;export{t as PORTAL_VERSION};
1
+ import{createRequire as o}from"module";import{envConfig as r}from"./config/env-config.js";const i=r.REDOCLY_INTERNAL_DEV==="true"?"local":o(import.meta.url)("../../package.json").version;export{i as PORTAL_VERSION};
@@ -57,11 +57,13 @@ type McpAuthorizationCodePayload = {
57
57
  client_id: string;
58
58
  redirect_uri: string;
59
59
  id_token: string;
60
+ idp_access_token?: string;
60
61
  iat: number;
61
62
  exp: number;
62
63
  };
63
64
  export declare function createMcpAuthorizationCode(params: {
64
65
  idToken: string;
66
+ idpAccessToken?: string;
65
67
  clientId: string;
66
68
  redirectUri: string;
67
69
  ttlSec?: number;
@@ -1,12 +1,12 @@
1
- import"../node-crypto-polyfill.js";import{DOMParser as D}from"@xmldom/xmldom";import{SignedXml as B}from"xml-crypto";import F from"xpath";import{deflateSync as H,inflateSync as J}from"fflate";import{createHash as q}from"crypto";import{ulid as W}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as K}from"@redocly/config";import{AUTH_URL as Q,JWT_SECRET_KEY as I}from"../constants/common.js";import{getPathPrefix as X,withPathPrefix as Y}from"@redocly/theme/core/utils";import{DEFAULT_AUTHENTICATED_TEAM as G,REQUIRED_OIDC_SCOPES as N,ServerRoutes as P}from"../../constants/common.js";import{appendQueryParams as Z}from"../../utils/url/append-query-params.js";import{logger as ee}from"../tools/notifiers/logger.js";import{randomString as te}from"../utils/crypto/random-string.js";import{randomUUID as k}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as y,JwtTokenExpired as ne}from"./jwt/types.js";import*as p from"./jwt/jwt.js";import{parseTeamClaimToArray as re}from"../utils/index.js";import{arrayBufferToBase64 as ae,decodeBase64 as R,encodeBase64URL as oe,urlSafeBase64 as v}from"./jwt/encode.js";import{formatSamlCertificate as se}from"./utils/format-saml-certificate.js";function j(e){return e?.type===u.OIDC}function ie(e){return e?.type===u.SAML2}async function ze(e,t){if(j(t))return ce(e,t);if(ie(t))return ue(e,t)}async function ce(e,t){const r=await V(e,t),n=new Set((t.scopes||[]).concat(N)),a=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:r.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(n).join(" "),extraParams:a,pkce:t.pkce}}function ue(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function Be(e,t,r,n,a={}){const o=new Set((n.scopes||[]).concat(N));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:n.clientId,scope:Array.from(o).join(" "),code:t,redirect_uri:E(r),grant_type:"authorization_code",...n.clientSecret?{client_secret:n.clientSecret}:{},...a}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function de(e,{authorizationEndpoint:t,clientId:r,responseType:n,scope:a,extraParams:o,idpId:s,pkce:l},m,A,S){if(!t||!r||!n||!a)return{loginUrl:void 0};const c=new URL(t),f=S?.redirectUriOverride??`${e}${Y(P.OIDC_CALLBACK)}`,x={state:k(),idpId:s,redirectUri:f,redirectTo:m,branch:S?.branchOverride??me(e),inviteCode:A,source:S?.sourceOverride??"portal"},h={};if(l){const d=v(te(50)),_=v(q("sha256").update(d).digest("base64")),g="S256";c.searchParams.append("code_challenge",_),c.searchParams.append("code_challenge_method",g),h.code_verifier={value:d,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:X()||"/"}}}c.searchParams.append("client_id",r),c.searchParams.append("scope",a),c.searchParams.append("response_type",n),c.searchParams.append("redirect_uri",E(f)),c.searchParams.append("state",oe(JSON.stringify(x)));for(const d in o)o[d]!==void 0&&c.searchParams.append(d,o[d]);return{loginUrl:c.toString(),cookies:h}}function Fe(e,t,r,n){const a=new URL(e);return a.searchParams.append("post_logout_redirect_uri",t),n&&a.searchParams.append("state",n),a.searchParams.append("id_token_hint",r),a.toString()}async function He(e){const t=Math.floor(Date.now()/1e3),r=t+(e.ttlSec??600);return p.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,iat:t,exp:r},I,y.HS256)}async function Je(e){await p.verify(e,I,y.HS256);const{payload:t}=p.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}function qe(e){const t=e||W(),r=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:r,object:"mcp_session",uri:`urn:redocly:realm:mcp:session:${r}`}}function E(e){return e.match(/^https:\/\/preview-[^\.]+--/)?"https://previewauth--"+e.split("--")[1]:e.match(/^(https:\/\/[^\.]+)--[^\.]+\.preview\./)?e.replace(/^(https:\/\/[^\.]+?)--[^\.]+\.preview\./,"$1.previewauth."):e}function me(e){return e.match(/^(https:\/\/[^\.]+)--([^\.]+)\.preview\./)?.[2]||void 0}function le(e){return e.type===u.OIDC}function pe(e){return e.type===u.SAML2}function We(e,t,r,n){return le(e)?de(t,e,r,n):pe(e)?fe(t,e,r,n):{}}function fe(e,t,r,n){const o=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
1
+ import"../node-crypto-polyfill.js";import{DOMParser as b}from"@xmldom/xmldom";import{SignedXml as B}from"xml-crypto";import F from"xpath";import{deflateSync as H,inflateSync as J}from"fflate";import{createHash as q}from"crypto";import{ulid as W}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as K}from"@redocly/config";import{AUTH_URL as Q,JWT_SECRET_KEY as I}from"../constants/common.js";import{getPathPrefix as X,withPathPrefix as Y}from"@redocly/theme/core/utils";import{DEFAULT_AUTHENTICATED_TEAM as G,REQUIRED_OIDC_SCOPES as D,ServerRoutes as N}from"../../constants/common.js";import{appendQueryParams as Z}from"../../utils/url/append-query-params.js";import{logger as ee}from"../tools/notifiers/logger.js";import{randomString as te}from"../utils/crypto/random-string.js";import{randomUUID as P}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as y,JwtTokenExpired as ne}from"./jwt/types.js";import*as p from"./jwt/jwt.js";import{parseTeamClaimToArray as re}from"../utils/index.js";import{arrayBufferToBase64 as ae,decodeBase64 as R,encodeBase64URL as oe,urlSafeBase64 as v}from"./jwt/encode.js";import{formatSamlCertificate as se}from"./utils/format-saml-certificate.js";function j(e){return e?.type===u.OIDC}function ie(e){return e?.type===u.SAML2}async function ze(e,t){if(j(t))return ce(e,t);if(ie(t))return ue(e,t)}async function ce(e,t){const r=await V(e,t),n=new Set((t.scopes||[]).concat(D)),a=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:r.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(n).join(" "),extraParams:a,pkce:t.pkce}}function ue(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function Be(e,t,r,n,a={}){const o=new Set((n.scopes||[]).concat(D));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:n.clientId,scope:Array.from(o).join(" "),code:t,redirect_uri:E(r),grant_type:"authorization_code",...n.clientSecret?{client_secret:n.clientSecret}:{},...a}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function de(e,{authorizationEndpoint:t,clientId:r,responseType:n,scope:a,extraParams:o,idpId:s,pkce:l},m,A,S){if(!t||!r||!n||!a)return{loginUrl:void 0};const c=new URL(t),f=S?.redirectUriOverride??`${e}${Y(N.OIDC_CALLBACK)}`,_={state:P(),idpId:s,redirectUri:f,redirectTo:m,branch:S?.branchOverride??me(e),inviteCode:A,source:S?.sourceOverride??"portal"},h={};if(l){const d=v(te(50)),x=v(q("sha256").update(d).digest("base64")),g="S256";c.searchParams.append("code_challenge",x),c.searchParams.append("code_challenge_method",g),h.code_verifier={value:d,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:X()||"/"}}}c.searchParams.append("client_id",r),c.searchParams.append("scope",a),c.searchParams.append("response_type",n),c.searchParams.append("redirect_uri",E(f)),c.searchParams.append("state",oe(JSON.stringify(_)));for(const d in o)o[d]!==void 0&&c.searchParams.append(d,o[d]);return{loginUrl:c.toString(),cookies:h}}function Fe(e,t,r,n){const a=new URL(e);return a.searchParams.append("post_logout_redirect_uri",t),n&&a.searchParams.append("state",n),a.searchParams.append("id_token_hint",r),a.toString()}async function He(e){const t=Math.floor(Date.now()/1e3),r=t+(e.ttlSec??600);return p.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpAccessToken?{idp_access_token:e.idpAccessToken}:{},iat:t,exp:r},I,y.HS256)}async function Je(e){await p.verify(e,I,y.HS256);const{payload:t}=p.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}function qe(e){const t=e||W(),r=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:r,object:"mcp_session",uri:`urn:redocly:realm:mcp:session:${r}`}}function E(e){return e.match(/^https:\/\/preview-[^\.]+--/)?"https://previewauth--"+e.split("--")[1]:e.match(/^(https:\/\/[^\.]+)--[^\.]+\.preview\./)?e.replace(/^(https:\/\/[^\.]+?)--[^\.]+\.preview\./,"$1.previewauth."):e}function me(e){return e.match(/^(https:\/\/[^\.]+)--([^\.]+)\.preview\./)?.[2]||void 0}function le(e){return e.type===u.OIDC}function pe(e){return e.type===u.SAML2}function We(e,t,r,n){return le(e)?de(t,e,r,n):pe(e)?fe(t,e,r,n):{}}function fe(e,t,r,n){const o=`<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
- ID="_${k()}"
4
+ ID="_${P()}"
5
5
  IssueInstant="${new Date().toISOString()}"
6
- AssertionConsumerServiceURL="${e}${P.SAML_CALLBACK}"
6
+ AssertionConsumerServiceURL="${e}${N.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>`,s=he(o);return{loginUrl:Z(t.ssoUrl,{SAMLRequest:s,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:r,inviteCode:n,source:"portal"})})}}function he(e){return ae(H(new TextEncoder().encode(e)).buffer)}function Ke(e){const t=R(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const r=J(new Uint8Array(atob(e).split("").map(n=>n.charCodeAt(0))));return new TextDecoder().decode(r)}function Qe(e){try{return JSON.parse(R(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function Xe(e){const t=new D().parseFromString(e,"application/xml"),n=i(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,o=i(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,m=i(t,"//*[local-name(.)='Audience']/text()")[0],A=m&&m.nodeValue||void 0,c=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",f=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],x=f&&f.nodeValue||"",h=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],d=h&&h.nodeValue||"",_=i(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],g=ye(_),T={},C=i(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(C.length)for(const O of C){const U=i(O,"./@Name")[0];if(U.nodeValue){const b=i(O,"./*[local-name(.)='AttributeValue']/text()")[0];b?.nodeValue&&(T[U.nodeValue]=b.nodeValue)}}return{uid:x,success:n,expiresAt:g,issuerId:l,entityId:A,attrs:T,cert:c,nameFormat:d,destination:o}}function ye(e){const t=typeof e?.nodeValue=="string"&&L(Date.parse(e.nodeValue)),r=L(Date.now()),n=L(Date.now()+720*60*1e3);return t?t>r&&t<n?n:t:r}function L(e){return Math.floor(e/1e3)}const M={},w={jwks:{}};async function V(e,t){return M[e]||(M[e]=t.configurationUrl?await $(t.configurationUrl):t.configuration),M[e]}async function we(e){for(const t of Object.keys(e)){const r=e[t];if(!j(r))continue;const n=await V(t,r);if(n.jwks_uri){const a=await $(n.jwks_uri);for(const o of a.keys)w.jwks[o.kid]={...o,idpId:t}}}}async function $(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function Ye(e){return fetch(`${Q}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function Ge(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(n=>Se(t.hostname,n))}function Se(e,t){return e===t||e.endsWith(`.${t}`)}async function Ze(e,t){const r=new D().parseFromString(e),n=i(r,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!n)throw new Error("Cannot find Signature in the SAML response");const a=se(t),o=new B({publicCert:a});o.loadSignature(n);try{return o.checkSignature(e)}catch{return!1}}function et(e,t,r,n){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=r["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let a;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(a=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(a=e);const o=r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=o?.match(/.+@.+/);return a=a||r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?o:void 0),a=a?.toLowerCase(),{sub:e,given_name:r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:r["http://schemas.microsoft.com/identity/claims/displayname"]||o,email:a,email_verified:!0,teams:n?re(r[n]):[]}}function z(e,t={}){return e.map(r=>t[r]||r)}async function tt(e,t){if(!t)return{};const r=t.authorization;if(!r)return{};try{const n=p.decode(r);if(n.header.alg===y.RS256){w.jwks[n.header.kid]===void 0&&await we(e);const m=w.jwks[n.header.kid];if(!m)return w.jwks[n.header.kid]=null,{};await p.verify(r,m,y.RS256)}else await p.verify(r,I,y.HS256);const a=n.payload.idpId||w.jwks[n.header.kid]?.idpId,o=e[a]||{},s=_e(o),l=xe(o);return{...n.payload,email:n.payload.email?.toLowerCase(),idpId:a,teams:Array.from(new Set([...z(n.payload.teams||[],l),..."defaultTeams"in o&&o.defaultTeams||[],...z("teamsClaimName"in o&&n.payload[s||""]||[],l),G])),name:Ae(n.payload),isAuthenticated:!0,idpAccessToken:t.idp_access_token,federatedAccessToken:t.federated_access_token,federatedIdToken:t.federated_id_token,authCookie:r}}catch(n){n instanceof ne||ee.error("Malformed JWT token: %s",n.message)}return{}}function Ae(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function xe(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function _e(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return K}}function i(e,t){return F.select(t,e)||[]}export{We as buildLoginUrl,de as buildOidcLoginUrl,Fe as buildOidcLogoutUrl,fe as buildSAML2LoginUrl,He as createMcpAuthorizationCode,qe as createMcpSessionResource,Ke as decodeSamlResponse,he as encodeSAML2,et as extractUserClaims,ze as getAuthProviderLoginParams,ce as getOidcLoginParams,V as getOidcMetadata,Ye as getRedoclyTokenPayload,ue as getSaml2LoginParams,tt as getUserParamsFromCookies,Ae as getUsernameFromPayload,j as isOidcProviderConfig,Ge as isRedoclySso,ie as isSaml2ProviderConfig,Be as oidcExchangeCodeForToken,Qe as parseOidcState,me as parsePreviewBranch,Xe as parseSamlResponse,E as rewritePreviewAuthRedirectUri,Je as verifyMcpAuthorizationCode,Ze as verifySAMLResponse};
12
+ </samlp:AuthnRequest>`,s=he(o);return{loginUrl:Z(t.ssoUrl,{SAMLRequest:s,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:r,inviteCode:n,source:"portal"})})}}function he(e){return ae(H(new TextEncoder().encode(e)).buffer)}function Ke(e){const t=R(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const r=J(new Uint8Array(atob(e).split("").map(n=>n.charCodeAt(0))));return new TextDecoder().decode(r)}function Qe(e){try{return JSON.parse(R(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function Xe(e){const t=new b().parseFromString(e,"application/xml"),n=i(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,o=i(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,m=i(t,"//*[local-name(.)='Audience']/text()")[0],A=m&&m.nodeValue||void 0,c=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",f=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],_=f&&f.nodeValue||"",h=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],d=h&&h.nodeValue||"",x=i(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],g=ye(x),T={},k=i(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(k.length)for(const C of k){const O=i(C,"./@Name")[0];if(O.nodeValue){const U=i(C,"./*[local-name(.)='AttributeValue']/text()")[0];U?.nodeValue&&(T[O.nodeValue]=U.nodeValue)}}return{uid:_,success:n,expiresAt:g,issuerId:l,entityId:A,attrs:T,cert:c,nameFormat:d,destination:o}}function ye(e){const t=typeof e?.nodeValue=="string"&&L(Date.parse(e.nodeValue)),r=L(Date.now()),n=L(Date.now()+720*60*1e3);return t?t>r&&t<n?n:t:r}function L(e){return Math.floor(e/1e3)}const M={},w={jwks:{}};async function V(e,t){return M[e]||(M[e]=t.configurationUrl?await $(t.configurationUrl):t.configuration),M[e]}async function we(e){for(const t of Object.keys(e)){const r=e[t];if(!j(r))continue;const n=await V(t,r);if(n.jwks_uri){const a=await $(n.jwks_uri);for(const o of a.keys)w.jwks[o.kid]={...o,idpId:t}}}}async function $(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function Ye(e){return fetch(`${Q}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function Ge(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(n=>Se(t.hostname,n))}function Se(e,t){return e===t||e.endsWith(`.${t}`)}async function Ze(e,t){const r=new b().parseFromString(e),n=i(r,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!n)throw new Error("Cannot find Signature in the SAML response");const a=se(t),o=new B({publicCert:a});o.loadSignature(n);try{return o.checkSignature(e)}catch{return!1}}function et(e,t,r,n){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=r["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let a;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(a=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(a=e);const o=r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=o?.match(/.+@.+/);return a=a||r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?o:void 0),a=a?.toLowerCase(),{sub:e,given_name:r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:r["http://schemas.microsoft.com/identity/claims/displayname"]||o,email:a,email_verified:!0,teams:n?re(r[n]):[]}}function z(e,t={}){return e.map(r=>t[r]||r)}async function tt(e,t){if(!t)return{};const r=t.authorization;if(!r)return{};try{const n=p.decode(r);if(n.header.alg===y.RS256){w.jwks[n.header.kid]===void 0&&await we(e);const m=w.jwks[n.header.kid];if(!m)return w.jwks[n.header.kid]=null,{};await p.verify(r,m,y.RS256)}else await p.verify(r,I,y.HS256);const a=n.payload.idpId||w.jwks[n.header.kid]?.idpId,o=e[a]||{},s=xe(o),l=_e(o);return{...n.payload,email:n.payload.email?.toLowerCase(),idpId:a,teams:Array.from(new Set([...z(n.payload.teams||[],l),..."defaultTeams"in o&&o.defaultTeams||[],...z("teamsClaimName"in o&&n.payload[s||""]||[],l),G])),name:Ae(n.payload),isAuthenticated:!0,idpAccessToken:n.payload.idp_access_token||t.idp_access_token,federatedAccessToken:t.federated_access_token,federatedIdToken:t.federated_id_token,authCookie:r}}catch(n){n instanceof ne||ee.error("Malformed JWT token: %s",n.message)}return{}}function Ae(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function _e(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function xe(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return K}}function i(e,t){return F.select(t,e)||[]}export{We as buildLoginUrl,de as buildOidcLoginUrl,Fe as buildOidcLogoutUrl,fe as buildSAML2LoginUrl,He as createMcpAuthorizationCode,qe as createMcpSessionResource,Ke as decodeSamlResponse,he as encodeSAML2,et as extractUserClaims,ze as getAuthProviderLoginParams,ce as getOidcLoginParams,V as getOidcMetadata,Ye as getRedoclyTokenPayload,ue as getSaml2LoginParams,tt as getUserParamsFromCookies,Ae as getUsernameFromPayload,j as isOidcProviderConfig,Ge as isRedoclySso,ie as isSaml2ProviderConfig,Be as oidcExchangeCodeForToken,Qe as parseOidcState,me as parsePreviewBranch,Xe as parseSamlResponse,E as rewritePreviewAuthRedirectUri,Je as verifyMcpAuthorizationCode,Ze 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_DOCS_SERVER_HANDLER_ID as i}from"../plugins/mcp/index.js";import{handleMcpRequest as u}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===i?await u(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_DOCS_SERVER_HANDLER_ID as i}from"../plugins/mcp/index.js";import{handleMcpRequest as u}from"../plugins/mcp/handlers/handle-mcp-request.js";async function l(r,s,a){try{const e=n.startTiming(),t=r.requestHandlerId===i?await u(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,2 +1,2 @@
1
- import*as E from"node:http";import{AsyncLocalStorage as A}from"node:async_hooks";import{Readable as u,Stream as C}from"node:stream";import{pipeline as H}from"node:stream/promises";import{ReadableStream as k}from"node:stream/web";import{getPathPrefix as S}from"@redocly/theme/core/utils";import{ALLOWED_CORS_ORIGINS as L}from"../../constants/common.js";import{logger as d}from"../tools/notifiers/logger.js";import{shutdowner as x}from"../tools/shutdowner.js";import{envConfig as I}from"../../config/env-config.js";import{getClientIp as T}from"./utils/get-client-ip.js";import{normalizeIpAddress as $}from"./utils.js";const y=new A;globalThis.redoclyCookieStorage=y;function B(n,c=4e3){return new Promise((m,p)=>{const l=E.createServer(async(r,t)=>{const v=r.headers.cookie||"";y.run(v,async()=>{let s;try{const e=new URL(r.url||"",`http://${r.headers.host}`),o=[],f=r.rawHeaders.length;for(let i=0;i<f;i+=2)o.push([r.rawHeaders[i],r.rawHeaders[i+1]]);const a={headers:o,method:r.method};r.method==="GET"||r.method==="HEAD"||(a.body=u.toWeb(r),a.duplex="half");const h=new Request(e.toString(),a),R=T(h)||"127.0.0.1",b=h?.headers?.get("x-forwarded-host")||$(r.socket.remoteAddress);h.context={remoteAddr:{hostname:b,port:r.socket.localPort,ipAddress:R},url:e},s=await n.fetch(h)}catch(e){s=new Response(null,{status:500}),e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError"?s=new Response(null,{status:504}):e.code==="ERR_INVALID_URL"&&(s=new Response("Invalid URL",{status:404})),d.error(`Error while handling request: %s
2
- %s`,e.message,e.stack))}const w=r.headers.origin;w&&L.some(e=>w===e)&&(t.setHeader("Access-Control-Allow-Origin",w),t.setHeader("Access-Control-Allow-Credentials","true"));for(const[e,o]of s.headers||[])try{e==="set-cookie"?t.setHeader(e,s.headers.getSetCookie(e)):t.setHeader(e,o)}catch(f){d.error(`Error while setting header: ${f?.message}`)}if(t.setHeader("Vary","Cookie"),t.statusCode=s.status||500,s.body)try{if(P(s)){const e=new C.Transform({transform(o,f,a){if(t.closed||t.destroyed)return a();t.write(o,f)?process.nextTick(a):t.once("drain",a)},flush(o){if(t.closed||t.destroyed)return o();t.end(),o()}});await H(s.body instanceof k?u.fromWeb(s.body):s.body,e)}else{const e=await s.text();t.setHeader("Content-Length",Buffer.byteLength(e)),t.end(e)}}catch(e){console.error(e);const o=e instanceof Error?e:new Error("unknown error",{cause:e});t.destroy(o)}else t.end()})});x.registerShutdownCallback(()=>new Promise(r=>{d.verbose("Shutting down http server"),l.close(()=>{d.verbose("Http server shut down"),r()})})),l.listen(parseInt(String(c),10)).on("listening",()=>{I.isDevelopMode?d.logInFooter("server",` \u{1F310} Preview URL: http://127.0.0.1:${c}${S()}`):d.logInFooter("server",`Server started at: http://127.0.0.1:${c}${S()}`),m(l)}).on("error",p)})}function P(n){const c=n.headers.get("content-type")||"",m=n.headers.get("x-accel-buffering")||"",p=n.headers.get("content-encoding"),l=n.headers.get("content-length"),r=n.headers.get("transfer-encoding");return p||r||l||/^no$/i.test(m)||!/^(text\/(?!event-stream\b))/i.test(c)}export{B as startHttpServer};
1
+ import*as b from"node:http";import{AsyncLocalStorage as A}from"node:async_hooks";import{Readable as S,Stream as C}from"node:stream";import{pipeline as H}from"node:stream/promises";import{ReadableStream as k}from"node:stream/web";import{getPathPrefix as u}from"@redocly/theme/core/utils";import{ALLOWED_CORS_ORIGINS as L}from"../constants/common.js";import{logger as d}from"../tools/notifiers/logger.js";import{shutdowner as x}from"../tools/shutdowner.js";import{envConfig as I}from"../config/env-config.js";import{getClientIp as T}from"./utils/get-client-ip.js";import{normalizeIpAddress as O}from"./utils.js";import{CORS_PROXY_STREAM_HEADER as P}from"./routes/cors-proxy.js";const R=new A;globalThis.redoclyCookieStorage=R;function X(n,c=4e3){return new Promise((m,p)=>{const f=b.createServer(async(t,r)=>{const y=t.headers.cookie||"";R.run(y,async()=>{let s;try{const e=new URL(t.url||"",`http://${t.headers.host}`),o=[],l=t.rawHeaders.length;for(let i=0;i<l;i+=2)o.push([t.rawHeaders[i],t.rawHeaders[i+1]]);const a={headers:o,method:t.method};t.method==="GET"||t.method==="HEAD"||(a.body=S.toWeb(t),a.duplex="half");const h=new Request(e.toString(),a),v=T(h)||"127.0.0.1",E=h?.headers?.get("x-forwarded-host")||O(t.socket.remoteAddress);h.context={remoteAddr:{hostname:E,port:t.socket.localPort,ipAddress:v},url:e},s=await n.fetch(h)}catch(e){s=new Response(null,{status:500}),e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError"?s=new Response(null,{status:504}):e.code==="ERR_INVALID_URL"&&(s=new Response("Invalid URL",{status:404})),d.error(`Error while handling request: %s
2
+ %s`,e.message,e.stack))}const w=t.headers.origin;w&&L.some(e=>w===e)&&(r.setHeader("Access-Control-Allow-Origin",w),r.setHeader("Access-Control-Allow-Credentials","true"));for(const[e,o]of s.headers||[])try{e==="set-cookie"?r.setHeader(e,s.headers.getSetCookie(e)):r.setHeader(e,o)}catch(l){d.error(`Error while setting header: ${l?.message}`)}if(r.setHeader("Vary","Cookie"),r.statusCode=s.status||500,s.body)try{if(_(s)){const e=new C.Transform({transform(o,l,a){if(r.closed||r.destroyed)return a();r.write(o,l)?process.nextTick(a):r.once("drain",a)},flush(o){if(r.closed||r.destroyed)return o();r.end(),o()}});await H(s.body instanceof k?S.fromWeb(s.body):s.body,e)}else{const e=await s.text();r.setHeader("Content-Length",Buffer.byteLength(e)),r.end(e)}}catch(e){console.error(e);const o=e instanceof Error?e:new Error("unknown error",{cause:e});r.destroy(o)}else r.end()})});x.registerShutdownCallback(()=>new Promise(t=>{d.verbose("Shutting down http server"),f.close(()=>{d.verbose("Http server shut down"),t()})})),f.listen(parseInt(String(c),10)).on("listening",()=>{I.isDevelopMode?d.logInFooter("server",` \u{1F310} Preview URL: http://127.0.0.1:${c}${u()}`):d.logInFooter("server",`Server started at: http://127.0.0.1:${c}${u()}`),m(f)}).on("error",p)})}function _(n){const c=n.headers.get("content-type")||"",m=n.headers.get("x-accel-buffering")||"",p=n.headers.get("content-encoding"),f=n.headers.get("content-length"),t=n.headers.get("transfer-encoding");return n.headers.get(P)==="1"||p||t||f||/^no$/i.test(m)||!/^(text\/(?!event-stream\b))/i.test(c)}export{X as startHttpServer};
@@ -1 +1 @@
1
- import{envConfig as o}from"../../../config/env-config.js";const t=(r,e)=>r.secureMethods?.includes(e)??!1;function f(r={}){return async(e,n)=>{const a=e.req.method;if(!t(r,a))return await n();const i=e.req.header("apiKey");if(!i)return e.json({message:"API key is required"},401);try{if(!o.BH_API_URL)return e.json({message:"API key validation service not configured"},500);const s=new URL("api-keys-verify",o.BH_API_URL).toString();if(!(await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:i})})).ok)return e.json({message:"Invalid API key"},401);await n()}catch{return e.json({message:"API key validation failed"},400)}}}export{f as apiKeyMiddleware};
1
+ import{envConfig as o}from"../../config/env-config.js";const t=(r,e)=>r.secureMethods?.includes(e)??!1;function f(r={}){return async(e,n)=>{const a=e.req.method;if(!t(r,a))return await n();const i=e.req.header("apiKey");if(!i)return e.json({message:"API key is required"},401);try{if(!o.BH_API_URL)return e.json({message:"API key validation service not configured"},500);const s=new URL("api-keys-verify",o.BH_API_URL).toString();if(!(await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:i})})).ok)return e.json({message:"Invalid API key"},401);await n()}catch{return e.json({message:"API key validation failed"},400)}}}export{f as apiKeyMiddleware};
@@ -1 +1 @@
1
- import{KvService as l}from"../../persistence/kv/services/kv-service.js";import{DEFAULT_AUTHENTICATED_TEAM as y}from"../../../constants/common.js";import{envConfig as s}from"../../../config/env-config.js";import{JWT_SECRET_KEY as I}from"../../constants/common.js";import*as m from"../jwt/jwt.js";import{AlgorithmTypes as T}from"../jwt/types.js";const h=60,p=e=>["POST","PUT","DELETE","PATCH"].includes(e),f=e=>["GET"].includes(e);function K({serverOutDir:e,protectReadMethods:t=!0}){return async(r,a)=>await w(r,a,e,t)}const w=async(e,t,r,a=!0)=>{const n=e.req.method,i=p(n)||f(n)&&a,o=e.req.header("apiKey");if(o)return await g(e,t,o,r);const u=e.req.header("authorization")?.replace("Bearer ","");return u?await E(e,t,u):i?e.json({message:"API key is required"},401):await t()},g=async(e,t,r,a)=>{if(!s.BH_API_URL||!s.ORGANIZATION_ID)return e.json({message:"API key validation service not configured"},500);try{const n=await l.getInstance({baseDbDir:a});let i=await _(n,r);if(i)return e.set("apiKeyTeams",i.teams),await t();const o=new URL(`/api/orgs/${s.ORGANIZATION_ID}/session`,s.BH_API_URL).toString(),c=await fetch(o,{method:"GET",headers:{Authorization:`Bearer ${r}`}});if(!c.ok)return e.json({message:"Invalid API key"},401);const A=(await c.json())?.user?.teams?.[s.ORGANIZATION_ID]??[],d=[y,...A];return e.set("apiKeyTeams",d),await n.set(["api-keys","reunite",r],{valid:!0,teams:d},{ttlInSeconds:h}),await t()}catch{return e.json({message:"API key validation failed"},400)}},E=async(e,t,r)=>{try{const a=await m.verify(r,I,T.HS256),n=m.decode(r).payload.isInternalConnection;return!a||!n?e.json({message:"API key is required"},401):await t()}catch{return e.json({message:"API key validation failed"},400)}},_=async(e,t)=>{try{return await e.get(["api-keys","reunite",t])}catch{return null}};export{K as catalogAuthMiddleware};
1
+ import{KvService as l}from"../../persistence/kv/services/kv-service.js";import{DEFAULT_AUTHENTICATED_TEAM as y}from"../../../constants/common.js";import{envConfig as s}from"../../config/env-config.js";import{JWT_SECRET_KEY as I}from"../../constants/common.js";import*as m from"../jwt/jwt.js";import{AlgorithmTypes as T}from"../jwt/types.js";const h=60,p=e=>["POST","PUT","DELETE","PATCH"].includes(e),f=e=>["GET"].includes(e);function K({serverOutDir:e,protectReadMethods:t=!0}){return async(r,a)=>await w(r,a,e,t)}const w=async(e,t,r,a=!0)=>{const n=e.req.method,i=p(n)||f(n)&&a,o=e.req.header("apiKey");if(o)return await g(e,t,o,r);const u=e.req.header("authorization")?.replace("Bearer ","");return u?await E(e,t,u):i?e.json({message:"API key is required"},401):await t()},g=async(e,t,r,a)=>{if(!s.BH_API_URL||!s.ORGANIZATION_ID)return e.json({message:"API key validation service not configured"},500);try{const n=await l.getInstance({baseDbDir:a});let i=await _(n,r);if(i)return e.set("apiKeyTeams",i.teams),await t();const o=new URL(`/api/orgs/${s.ORGANIZATION_ID}/session`,s.BH_API_URL).toString(),c=await fetch(o,{method:"GET",headers:{Authorization:`Bearer ${r}`}});if(!c.ok)return e.json({message:"Invalid API key"},401);const A=(await c.json())?.user?.teams?.[s.ORGANIZATION_ID]??[],d=[y,...A];return e.set("apiKeyTeams",d),await n.set(["api-keys","reunite",r],{valid:!0,teams:d},{ttlInSeconds:h}),await t()}catch{return e.json({message:"API key validation failed"},400)}},E=async(e,t,r)=>{try{const a=await m.verify(r,I,T.HS256),n=m.decode(r).payload.isInternalConnection;return!a||!n?e.json({message:"API key is required"},401):await t()}catch{return e.json({message:"API key validation failed"},400)}},_=async(e,t)=>{try{return await e.get(["api-keys","reunite",t])}catch{return null}};export{K as catalogAuthMiddleware};
@@ -1 +1 @@
1
- import{cors as o}from"hono/cors";import{envConfig as r}from"../../../config/env-config.js";function n(e){return r.PROJECT_URL?o({origin:r.PROJECT_URL,allowMethods:e.allowMethods}):o()}export{n as corsMiddleware};
1
+ import{cors as o}from"hono/cors";import{envConfig as r}from"../../config/env-config.js";function n(e){return r.PROJECT_URL?o({origin:r.PROJECT_URL,allowMethods:e.allowMethods}):o()}export{n as corsMiddleware};
@@ -1 +1 @@
1
- import{pathToFileURL as l}from"url";import{isDefined as m}from"../../../../utils/guards/is-defined.js";import{slash as s}from"../../../../utils/path/slash.js";import{envConfig as o}from"../../../../config/env-config.js";import{compose as w}from"./hono-compose.js";function D(i){return async(e,a)=>{await i.waitForPluginsLifecycle();const n=await f(i.serverOutDir),d=(await Promise.all(i.getAllMiddleware().map(({id:t})=>n[t]).map(async t=>typeof t=="function"?(await t()).default:void 0))).filter(m),r=await w(d)(e,a,i);if(!r.finalized)throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return r.res}}async function f(i){try{let e;return o.isRuntimeMode?e=await import("@portal/middleware"):e=await import(l(`${s(i)}/middleware-entry.js`)+"?"+new Date),e.middleware}catch(e){if(o.isDevelopMode)return{};throw e}}export{D as dynamicMiddleware};
1
+ import{pathToFileURL as l}from"url";import{isDefined as m}from"../../../../utils/guards/is-defined.js";import{slash as s}from"../../../../utils/path/slash.js";import{envConfig as o}from"../../../config/env-config.js";import{compose as w}from"./hono-compose.js";function D(i){return async(e,a)=>{await i.waitForPluginsLifecycle();const n=await f(i.serverOutDir),d=(await Promise.all(i.getAllMiddleware().map(({id:t})=>n[t]).map(async t=>typeof t=="function"?(await t()).default:void 0))).filter(m),r=await w(d)(e,a,i);if(!r.finalized)throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return r.res}}async function f(i){try{let e;return o.isRuntimeMode?e=await import("@portal/middleware"):e=await import(l(`${s(i)}/middleware-entry.js`)+"?"+new Date),e.middleware}catch(e){if(o.isDevelopMode)return{};throw e}}export{D as dynamicMiddleware};
@@ -1 +1 @@
1
- import{envConfig as o}from"../../../config/env-config.js";import{shutdowner as r}from"../../tools/shutdowner.js";import{logger as n}from"../../tools/notifiers/logger.js";let t=null;const e=o.WEB_SERVER_IDLE_TIMEOUT;function m(){if(e){if(isNaN(+e))throw new Error(`IDLE_TIMEOUT must be a number, got ${e}`);t&&clearTimeout(t),t=setTimeout(()=>{n.info("Server is idle, stopping..."),r.exitWithCode(0)},+e)}}function T(){return async(u,i)=>{m(),await i()}}export{T as idleTimeoutMiddleware,m as startIdleTimeout};
1
+ import{envConfig as o}from"../../config/env-config.js";import{shutdowner as r}from"../../tools/shutdowner.js";import{logger as n}from"../../tools/notifiers/logger.js";let t=null;const e=o.WEB_SERVER_IDLE_TIMEOUT;function m(){if(e){if(isNaN(+e))throw new Error(`IDLE_TIMEOUT must be a number, got ${e}`);t&&clearTimeout(t),t=setTimeout(()=>{n.info("Server is idle, stopping..."),r.exitWithCode(0)},+e)}}function T(){return async(u,i)=>{m(),await i()}}export{T as idleTimeoutMiddleware,m as startIdleTimeout};
@@ -1 +1 @@
1
- import{minimatch as p}from"minimatch";import{withoutPathPrefix as c}from"@redocly/theme/core/utils";import{removeTrailingSlash as l}from"../../../utils/url/remove-trailing-slash.js";import{SERVER_EDITOR_APP_URL as d}from"../../../constants/common.js";function y(n){return async(e,i)=>{try{await i()}finally{const r=n.getConfig();if(r.responseHeaders){const a=c(new URL(e.req.url).pathname),t=Object.keys(r.responseHeaders);for(const s of t)if(p(a,s))for(const{name:f,value:m}of r.responseHeaders[s])e.header(f,m)}const o=e.req.header("referer");o&&l(o)===d&&e.header("Cross-Origin-Resource-Policy","cross-origin")}}}export{y as responseHeadersMiddleware};
1
+ import{minimatch as p}from"minimatch";import{withoutPathPrefix as c}from"@redocly/theme/core/utils";import{removeTrailingSlash as l}from"../../../utils/url/remove-trailing-slash.js";import{SERVER_EDITOR_APP_URL as d}from"../../constants/common.js";function y(n){return async(e,i)=>{try{await i()}finally{const r=n.getConfig();if(r.responseHeaders){const a=c(new URL(e.req.url).pathname),t=Object.keys(r.responseHeaders);for(const s of t)if(p(a,s))for(const{name:f,value:m}of r.responseHeaders[s])e.header(f,m)}const o=e.req.header("referer");o&&l(o)===d&&e.header("Cross-Origin-Resource-Policy","cross-origin")}}}export{y as responseHeadersMiddleware};
@@ -1 +1 @@
1
- const i={".aac":"audio/aac",".abw":"application/x-abiword",".arc":"application/x-freearc",".avif":"image/avif",".avi":"video/x-msvideo",".azw":"application/vnd.amazon.ebook",".bin":"application/octet-stream",".bmp":"image/bmp",".bz":"application/x-bzip",".bz2":"application/x-bzip2",".cda":"application/x-cdf",".csh":"application/x-csh",".css":"text/css",".csv":"text/csv",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".eot":"application/vnd.ms-fontobject",".epub":"application/epub+zip",".gz":"application/gzip",".gif":"image/gif",".htm":"text/html",".html":"text/html",".ico":"image/vnd.microsoft.icon",".ics":"text/calendar",".jar":"application/java-archive",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"application/javascript",".json":"application/json",".jsonld":"application/ld+json",".mid":"audio/x-midi",".midi":"audio/x-midi",".mjs":"text/javascript",".mp3":"audio/mpeg",".mp4":"video/mp4",".mpeg":"video/mpeg",".mpkg":"application/vnd.apple.installer+xml",".odp":"application/vnd.oasis.opendocument.presentation",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odt":"application/vnd.oasis.opendocument.text",".oga":"audio/ogg",".ogv":"video/ogg",".ogx":"application/ogg",".opus":"audio/opus",".otf":"font/otf",".png":"image/png",".pdf":"application/pdf",".php":"application/x-httpd-php",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".rar":"application/vnd.rar",".rtf":"application/rtf",".sh":"application/x-sh",".svg":"image/svg+xml",".tar":"application/x-tar",".tif":"image/tiff",".tiff":"image/tiff",".ts":"video/mp2t",".ttf":"font/ttf",".txt":"text/plain",".vsd":"application/vnd.visio",".wav":"audio/wav",".weba":"audio/webm",".webm":"video/webm",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2",".xhtml":"application/xhtml+xml",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".xml":"application/xml",".xul":"application/vnd.mozilla.xul+xml",".zip":"application/zip",".3gp":"video/3gpp",".3g2":"video/3gpp2",".7z":"application/x-7z-compressed"},a={"font/otf":365*24*60*60,"font/ttf":365*24*60*60,"font/woff":365*24*60*60,"font/woff2":365*24*60*60,"application/vnd.ms-fontobject":365*24*60*60};export{a as DEFAULT_MAX_AGE_FOR_MIME_TYPE,i as MIME_TYPES};
1
+ const i={".aac":"audio/aac",".abw":"application/x-abiword",".arc":"application/x-freearc",".avif":"image/avif",".avi":"video/x-msvideo",".azw":"application/vnd.amazon.ebook",".bin":"application/octet-stream",".bmp":"image/bmp",".bz":"application/x-bzip",".bz2":"application/x-bzip2",".cda":"application/x-cdf",".csh":"application/x-csh",".css":"text/css",".csv":"text/csv",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".eot":"application/vnd.ms-fontobject",".epub":"application/epub+zip",".gz":"application/gzip",".gif":"image/gif",".htm":"text/html",".html":"text/html",".ico":"image/vnd.microsoft.icon",".ics":"text/calendar",".jar":"application/java-archive",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"application/javascript",".json":"application/json",".jsonld":"application/ld+json",".mid":"audio/x-midi",".midi":"audio/x-midi",".md":"text/markdown",".mjs":"text/javascript",".mp3":"audio/mpeg",".mp4":"video/mp4",".mpeg":"video/mpeg",".mpkg":"application/vnd.apple.installer+xml",".odp":"application/vnd.oasis.opendocument.presentation",".ods":"application/vnd.oasis.opendocument.spreadsheet",".odt":"application/vnd.oasis.opendocument.text",".oga":"audio/ogg",".ogv":"video/ogg",".ogx":"application/ogg",".opus":"audio/opus",".otf":"font/otf",".png":"image/png",".pdf":"application/pdf",".php":"application/x-httpd-php",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".rar":"application/vnd.rar",".rtf":"application/rtf",".sh":"application/x-sh",".svg":"image/svg+xml",".tar":"application/x-tar",".tif":"image/tiff",".tiff":"image/tiff",".ts":"video/mp2t",".ttf":"font/ttf",".txt":"text/plain",".vsd":"application/vnd.visio",".wav":"audio/wav",".weba":"audio/webm",".webm":"video/webm",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2",".xhtml":"application/xhtml+xml",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".xml":"application/xml",".xul":"application/vnd.mozilla.xul+xml",".zip":"application/zip",".3gp":"video/3gpp",".3g2":"video/3gpp2",".7z":"application/x-7z-compressed"},a={"font/otf":365*24*60*60,"font/ttf":365*24*60*60,"font/woff":365*24*60*60,"font/woff2":365*24*60*60,"application/vnd.ms-fontobject":365*24*60*60};export{a as DEFAULT_MAX_AGE_FOR_MIME_TYPE,i as MIME_TYPES};
@@ -1 +1 @@
1
- import{setCookie as _,deleteCookie as q}from"hono/cookie";import{AuthProviderType as W}from"@redocly/config";import{withPathPrefix as I,getPathPrefix as R}from"@redocly/theme/core/utils";import{compareURIs as Y}from"../../../utils/url/compare-uris.js";import{ensureArray as b}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as F,JWT_SECRET_KEY as v,ORG_SLUG as Q,ORG_ID as Z}from"../../constants/common.js";import{DEFAULT_COOKIE_EXPIRATION as B,ServerRoutes as S}from"../../../constants/common.js";import{sanitizeRedirectPathname as z}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as M}from"../../telemetry/index.js";import{envConfig as H}from"../../../config/env-config.js";import{getAuthProviderLoginParams as x,isOidcProviderConfig as $,isSaml2ProviderConfig as ee,oidcExchangeCodeForToken as re,buildLoginUrl as oe,decodeSamlResponse as ne,extractUserClaims as te,parseSamlResponse as ie,parseOidcState as se,verifySAMLResponse as ae,getUsernameFromPayload as de,buildOidcLogoutUrl as ce,getOidcMetadata as j,getRedoclyTokenPayload as le,isRedoclySso as ue,rewritePreviewAuthRedirectUri as pe,parsePreviewBranch as N,buildOidcLoginUrl as ge,createMcpSessionResource as k}from"../auth.js";import*as O from"../jwt/jwt.js";import{AlgorithmTypes as P}from"../jwt/types.js";import{handleErrorPageRender as fe}from"../utils.js";import{encodeBase64URL as me}from"../jwt/encode.js";async function ve(i){if(H.isProductionEnv)return i.newResponse(null,404,{});const{password:e,...r}=await i.req.json(),a=await O.sign({...r,name:r.username||r.email||"Unknown"},v,P.HS256);return _(i,"authorization",a,{path:R()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),i.newResponse(null,200,{})}function $e(){return async i=>{const e=i.get("logger"),r=encodeURIComponent(i.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${S.LOGIN}/?error=${encodeURIComponent(r)}`;return i.newResponse(null,301,{Location:a})}}function K(i){if(!i||!i.includes(S.MCP_CALLBACK))return null;try{const e=i.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function Ue(i){return async e=>{const r=e.get("logger"),a=i.getConfig().ssoDirect,n=se(e.req.query("state")),f=n.idpId,t=n.source==="mcp"||n.redirectTo&&typeof n.redirectTo=="string"&&n.redirectTo.includes(S.MCP_CALLBACK),c=t?K(typeof n.redirectTo=="string"?n.redirectTo:void 0):null,s=a?.[f];if(!$(s))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await j(f,s);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,l=e.req.query("code"),m=e.req.query("error");if(m)return t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:`OIDC error: ${m}`,error_details:e.req.query("error_description")||null}]),fe(e,i,{slug:"/"},403,"403OIDC");if(!l){const w="Code is expected but not present";return r.error(`OIDC login error: ${w}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const h=e.req.header("x-forwarded-host"),g=e.req.header("x-forwarded-proto")||"https",A=t&&typeof n.redirectUri=="string"?n.redirectUri:new URL(I(S.OIDC_CALLBACK),h?`${g}://${h}`:e.req.url).toString(),C=e.get("cookies")?.code_verifier,u=await re(p,l,A,s,{...s.tokenRequestCustomParams,...C?{code_verifier:C}:{}});if(u.error)return r.error(`Error from OIDC provider: "${u.error}"`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:`Token exchange error: ${u.error}`,error_details:u.error_description||null}]),e.text(`Forbidden: ${u.error_description||u.error}`,403);if(!u?.id_token){const w="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${w}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const{payload:o,header:U}=O.decode(u.id_token),J=U.alg===P.RS256;if(s.audience?.length&&![...b(o.aud||[]),...b(o[F]||[])].some(L=>s.audience?.includes(L))){const L="No valid audience found in id_token";return r.error(`OIDC login error: ${L}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:L,error_details:null}]),new Response(`Forbidden: ${L}`)}const E=J?u.id_token:await O.sign({...o,idpId:f},v,P.HS256);de(o)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const D=s?.tokenExpirationTime?Date.now()+s.tokenExpirationTime*1e3:o.exp*1e3||Date.now()+B*1e3;if(s.introspectEndpoint){const w=await fetch(s.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:u.access_token})});if(w.ok){const T=(await w.json()).ext?.federatedIdentity;T&&(_(e,"federated_access_token",T.access_token||"",{path:R()||"/",httpOnly:!1,expires:new Date(D)}),_(e,"federated_id_token",T.id_token||"",{path:R()||"/",httpOnly:!1,expires:new Date(D)}))}else r.warn(`OIDC introspect error: ${w.statusText}`)}if(_(e,"authorization",E,{path:R()||"/",httpOnly:!0,expires:new Date(D)}),E!==u.id_token&&_(e,"idp_id_token",u.id_token||"",{path:R()||"/",httpOnly:!0,expires:new Date(D)}),_(e,"idp_access_token",u.access_token||"",{path:R()||"/",httpOnly:!0,expires:new Date(D)}),q(e,"code_verifier",{path:R()||"/"}),t&&n.redirectTo&&typeof n.redirectTo=="string"&&n.redirectTo.includes(S.MCP_CALLBACK)){const L=`${e.req.url.split("?")[0].replace(S.OIDC_CALLBACK,"")}${n.redirectTo}`;return e.newResponse(null,302,{Location:L})}const G=typeof n.redirectTo=="string"?n.redirectTo:void 0;let V=z(new URL(G||"/",e.req.url).pathname);const X=e.newResponse(null,302,{Location:V});return r.updateContext({email:o.email,subject:o.sub}),r.info("OIDC login successful"),X}catch(p){const l=p instanceof Error?p.message:String(p),m=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${l}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:l,error_details:m}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const y="Something went wrong";return r.error(`OIDC login error: ${y}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:y,error_details:null}]),e.text(y,500)}}function Te(i){return async e=>{const r=e.get("logger"),n=e.get("auth").claims?.idpId,t=i.getConfig().ssoDirect?.[n];if(e.req.method==="POST")return $(t)||q(e,"authorization",{path:R()||"/"}),r.info("Logout successful"),e.newResponse(null,200,{});let c;if($(t)){const s=(await j(n,t)).end_session_endpoint;if(s){const d=new URL(e.req.url),y=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,l=`${y}://${p}`,m=N(l),h=m?me(JSON.stringify({branch:N(l)})):void 0,g=m?`${pe(l)}/_auth/logout`:`${l}/post-logout`;c=ce(s,g,e.get("cookies")?.idp_id_token||e.get("cookies")?.authorization||"",h)}}return r.info("Logout successful"),q(e,"authorization",{path:R()||"/"}),e.newResponse(null,302,{Location:c||I("/")})}}function qe(i){return async e=>{const r=i.getConfig().logoutReturnUrl,a=r||I("/");return e.newResponse(null,302,{Location:a})}}function be(i){return async e=>{const r=e.get("logger"),a=e.req.param("code"),n=H.BH_API_URL,f=(t,c,s)=>t&&c?`${t} ${c.charAt(0)}`:s;try{if(!n)throw new Error("BH_API_URL is not set");const t=i.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(I("/"));const c=await fetch(`${n}/user-invites/public/${a}`);if(!c.ok)return c.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(I("/"))):(r.error("Invite error",await c.text()),e.redirect(I("/")));const s=await c.json(),d=new URL(I("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",s.organization.name),d.searchParams.set("invitedBy",f(s.invitedBy.firstName,s.invitedBy.lastName,s.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function Ee(i){return async e=>{const r=e.get("logger"),a=i.getConfig().ssoDirect,n=new URL(e.req.url),f=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||n.protocol.slice(0,-1)||"https",c=e.req.header("x-forwarded-host")||n.host,s=`${t}://${c}`;let d=n.searchParams.get("idpId");const y=n.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const l=n.searchParams.get("mcp_redirect_uri"),m=!!l;if(!a?.[d]){const o="Invalid idpId";if(r.error(`IdP login error: ${o}`),m){const U=K(y||void 0);M.sendMcpAuthorizationFailedMessage([{...k(U),error:o,error_details:null}])}return e.text(`Forbidden: ${o}`,403)}const g=d&&a?await x(d,a[d]):void 0,A={};for(const o of Object.keys(g?.extraParams||{}))A[o]=n.searchParams.get(o)||g?.extraParams?.[o]||void 0;let C,u={};if(m&&l&&g&&g.type===W.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${l}`);const o=ge("",{...g,extraParams:A},y,f,{redirectUriOverride:l,sourceOverride:"mcp",branchOverride:void 0});C=o.loginUrl,u=o.cookies||{}}else if(g){const o=oe({...g,extraParams:A},s,y,f);C=o.loginUrl,u=o.cookies||{}}return Object.keys(u).forEach(o=>{_(e,o,u[o].value,u[o].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:C||new URL(e.req.url).pathname})}}function Fe(i){return async e=>{const r=e.get("logger"),a=await e.req.formData(),n=a.get("SAMLResponse"),f=a.get("RelayState");if(typeof n!="string"||typeof f!="string"){const o="SAMLResponse is required";return r.error(`SAML2 login error: ${o}`),e.text(`Bad request: ${o}`,400)}const t=ne(n),{success:c,uid:s,nameFormat:d,attrs:y,issuerId:p,expiresAt:l}=ie(t),{idpId:m,redirectTo:h}=JSON.parse(f);if(!c){const o="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${o}`),e.text(`Permission denied: ${o}`,401)}if(!l||Math.ceil(Date.now()/1e3)>=l){const o="SAML2 Token Expired";return r.error(`SAML2 login error: ${o}`),e.text(o,401)}const g=i.getConfig().ssoDirect?.[m];if(!g||!ee(g)){const o="Cannot find valid IdP";return r.error(`SAML2 login error: ${o}`),e.text(`Permission denied: ${o}`,401)}if(!(g.issuerId&&p&&Y(g.issuerId,p))){const o="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${o}`),e.text(`Permission denied: ${o}`,401)}if(!await ae(t,g.x509PublicCert)){const o="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${o}`),e.text(o,401)}const C=te(s,d,y,g.teamsAttributeName);if(!C.sub){const o="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${o}`),e.text(o,400)}if(!C.email){const o="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${o}`),e.text(o,400)}const u=await O.sign({...C,idpId:m},v,P.HS256);return _(e,"authorization",u,{path:R()||"/",httpOnly:!0,expires:new Date(l*1e3)}),r.updateContext({email:C.email,subject:C.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:h||"/"})}}function Be(i){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),n=I(z(a.pathname)),f=i.getConfig().ssoDirect,t=Object.entries(f||{}).find(([,h])=>$(h)&&ue(h));if(!(f&&t))return e.newResponse(null,302,{Location:n});const s=e.req.query("token"),d=s&&await le(s);if(!d)return e.newResponse(null,302,{Location:n});if(!b(d[F]||[]).some(h=>h===Q||h===Z))return e.newResponse(null,302,{Location:n});const l=await O.sign({...d,idpId:t?.at(0)},v,P.HS256),m=Date.now()+B*1e3;return _(e,"authorization",l,{path:R()||"/",httpOnly:!0,expires:new Date(m),sameSite:"None",secure:!0}),r.info("Token login successful"),e.newResponse(null,302,{Location:n})}}export{ve as authorizeHandler,Ee as idpLoginHandler,be as inviteHandler,Te as logoutHandler,Ue as oidcCallbackHandler,qe as postLogoutHandler,$e as redoclyLoginCallbackHandler,Be as redoclyTokenLoginHandler,Fe as samlCallbackHandler};
1
+ import{setCookie as _,deleteCookie as q}from"hono/cookie";import{AuthProviderType as W}from"@redocly/config";import{withPathPrefix as I,getPathPrefix as R}from"@redocly/theme/core/utils";import{compareURIs as Y}from"../../../utils/url/compare-uris.js";import{ensureArray as b}from"../../../utils/array/ensure-array.js";import{ALTERNATIVE_AUD_CLAIM_NAME as F,JWT_SECRET_KEY as v,ORG_SLUG as Q,ORG_ID as Z}from"../../constants/common.js";import{DEFAULT_COOKIE_EXPIRATION as B,ServerRoutes as S}from"../../../constants/common.js";import{sanitizeRedirectPathname as z}from"../../../utils/url/sanitize-redirect-pathname.js";import{telemetry as M}from"../../telemetry/index.js";import{envConfig as H}from"../../config/env-config.js";import{getAuthProviderLoginParams as x,isOidcProviderConfig as $,isSaml2ProviderConfig as ee,oidcExchangeCodeForToken as re,buildLoginUrl as oe,decodeSamlResponse as ne,extractUserClaims as te,parseSamlResponse as ie,parseOidcState as se,verifySAMLResponse as ae,getUsernameFromPayload as de,buildOidcLogoutUrl as ce,getOidcMetadata as j,getRedoclyTokenPayload as le,isRedoclySso as ue,rewritePreviewAuthRedirectUri as pe,parsePreviewBranch as N,buildOidcLoginUrl as ge,createMcpSessionResource as k}from"../auth.js";import*as O from"../jwt/jwt.js";import{AlgorithmTypes as P}from"../jwt/types.js";import{handleErrorPageRender as fe}from"../utils.js";import{encodeBase64URL as me}from"../jwt/encode.js";async function ve(i){if(H.isProductionEnv)return i.newResponse(null,404,{});const{password:e,...r}=await i.req.json(),a=await O.sign({...r,name:r.username||r.email||"Unknown"},v,P.HS256);return _(i,"authorization",a,{path:R()||"/",httpOnly:!0,secure:!0,sameSite:"none"}),i.newResponse(null,200,{})}function $e(){return async i=>{const e=i.get("logger"),r=encodeURIComponent(i.req.query("message")||"");e.error(`Login error: ${r}`);const a=`${S.LOGIN}/?error=${encodeURIComponent(r)}`;return i.newResponse(null,301,{Location:a})}}function K(i){if(!i||!i.includes(S.MCP_CALLBACK))return null;try{const e=i.split("/"),r=e[e.length-1];if(r){const a=Buffer.from(r,"base64url").toString("utf-8");return JSON.parse(a).mcpSessionId||null}}catch{}return null}function Ue(i){return async e=>{const r=e.get("logger"),a=i.getConfig().ssoDirect,n=se(e.req.query("state")),f=n.idpId,t=n.source==="mcp"||n.redirectTo&&typeof n.redirectTo=="string"&&n.redirectTo.includes(S.MCP_CALLBACK),c=t?K(typeof n.redirectTo=="string"?n.redirectTo:void 0):null,s=a?.[f];if(!$(s))return r.error("OIDC login error: missing OIDC provider config"),e.text("Forbidden",403);const d=await j(f,s);if(a&&!d.token_endpoint){const p="Invalid OIDC configuration: token_endpoint is required";return r.error(`OIDC login error: ${p}`),e.text(p,500)}try{const p=d.token_endpoint,l=e.req.query("code"),m=e.req.query("error");if(m)return t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:`OIDC error: ${m}`,error_details:e.req.query("error_description")||null}]),fe(e,i,{slug:"/"},403,"403OIDC");if(!l){const w="Code is expected but not present";return r.error(`OIDC login error: ${w}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const h=e.req.header("x-forwarded-host"),g=e.req.header("x-forwarded-proto")||"https",A=t&&typeof n.redirectUri=="string"?n.redirectUri:new URL(I(S.OIDC_CALLBACK),h?`${g}://${h}`:e.req.url).toString(),C=e.get("cookies")?.code_verifier,u=await re(p,l,A,s,{...s.tokenRequestCustomParams,...C?{code_verifier:C}:{}});if(u.error)return r.error(`Error from OIDC provider: "${u.error}"`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:`Token exchange error: ${u.error}`,error_details:u.error_description||null}]),e.text(`Forbidden: ${u.error_description||u.error}`,403);if(!u?.id_token){const w="No id_token, please, add openid to scopes";return r.error(`OIDC login error: ${w}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:w,error_details:null}]),new Response(`Forbidden: ${w}`,{status:403})}const{payload:o,header:U}=O.decode(u.id_token),J=U.alg===P.RS256;if(s.audience?.length&&![...b(o.aud||[]),...b(o[F]||[])].some(L=>s.audience?.includes(L))){const L="No valid audience found in id_token";return r.error(`OIDC login error: ${L}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:L,error_details:null}]),new Response(`Forbidden: ${L}`)}const E=J?u.id_token:await O.sign({...o,idpId:f},v,P.HS256);de(o)||r.warn("To display your username, the required 'email' or 'full_profile' scope must be added to the identity provider configuration");const D=s?.tokenExpirationTime?Date.now()+s.tokenExpirationTime*1e3:o.exp*1e3||Date.now()+B*1e3;if(s.introspectEndpoint){const w=await fetch(s.introspectEndpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({access_token:u.access_token})});if(w.ok){const T=(await w.json()).ext?.federatedIdentity;T&&(_(e,"federated_access_token",T.access_token||"",{path:R()||"/",httpOnly:!1,expires:new Date(D)}),_(e,"federated_id_token",T.id_token||"",{path:R()||"/",httpOnly:!1,expires:new Date(D)}))}else r.warn(`OIDC introspect error: ${w.statusText}`)}if(_(e,"authorization",E,{path:R()||"/",httpOnly:!0,expires:new Date(D)}),E!==u.id_token&&_(e,"idp_id_token",u.id_token||"",{path:R()||"/",httpOnly:!0,expires:new Date(D)}),_(e,"idp_access_token",u.access_token||"",{path:R()||"/",httpOnly:!0,expires:new Date(D)}),q(e,"code_verifier",{path:R()||"/"}),t&&n.redirectTo&&typeof n.redirectTo=="string"&&n.redirectTo.includes(S.MCP_CALLBACK)){const L=`${e.req.url.split("?")[0].replace(S.OIDC_CALLBACK,"")}${n.redirectTo}`;return e.newResponse(null,302,{Location:L})}const G=typeof n.redirectTo=="string"?n.redirectTo:void 0;let V=z(new URL(G||"/",e.req.url).pathname);const X=e.newResponse(null,302,{Location:V});return r.updateContext({email:o.email,subject:o.sub}),r.info("OIDC login successful"),X}catch(p){const l=p instanceof Error?p.message:String(p),m=p instanceof Error?p.stack:String(p);if(r.error(`OIDC login error: ${l}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:l,error_details:m}]),p.error==="access_denied")return r.info("Access denied"),e.text("Forbidden",403)}const y="Something went wrong";return r.error(`OIDC login error: ${y}`),t&&M.sendMcpAuthorizationFailedMessage([{...k(c),error:y,error_details:null}]),e.text(y,500)}}function Te(i){return async e=>{const r=e.get("logger"),n=e.get("auth").claims?.idpId,t=i.getConfig().ssoDirect?.[n];if(e.req.method==="POST")return $(t)||q(e,"authorization",{path:R()||"/"}),r.info("Logout successful"),e.newResponse(null,200,{});let c;if($(t)){const s=(await j(n,t)).end_session_endpoint;if(s){const d=new URL(e.req.url),y=e.req.header("x-forwarded-proto")||d.protocol.slice(0,-1)||"https",p=e.req.header("x-forwarded-host")||d.host,l=`${y}://${p}`,m=N(l),h=m?me(JSON.stringify({branch:N(l)})):void 0,g=m?`${pe(l)}/_auth/logout`:`${l}/post-logout`;c=ce(s,g,e.get("cookies")?.idp_id_token||e.get("cookies")?.authorization||"",h)}}return r.info("Logout successful"),q(e,"authorization",{path:R()||"/"}),e.newResponse(null,302,{Location:c||I("/")})}}function qe(i){return async e=>{const r=i.getConfig().logoutReturnUrl,a=r||I("/");return e.newResponse(null,302,{Location:a})}}function be(i){return async e=>{const r=e.get("logger"),a=e.req.param("code"),n=H.BH_API_URL,f=(t,c,s)=>t&&c?`${t} ${c.charAt(0)}`:s;try{if(!n)throw new Error("BH_API_URL is not set");const t=i.getConfig().ssoDirect;if(!t||!Object.keys(t).length)return r.warn("Invite no sso configured to handle"),e.redirect(I("/"));const c=await fetch(`${n}/user-invites/public/${a}`);if(!c.ok)return c.status===404?(r.warn(`Invite ${a} not found redirect to homepage`),e.redirect(I("/"))):(r.error("Invite error",await c.text()),e.redirect(I("/")));const s=await c.json(),d=new URL(I("/invite"),e.req.url);return d.searchParams.set("code",a),d.searchParams.set("org",s.organization.name),d.searchParams.set("invitedBy",f(s.invitedBy.firstName,s.invitedBy.lastName,s.invitedBy.name)),e.newResponse(null,302,{Location:d.toString()})}catch(t){return r.error("Error processing invite",{error:t,inviteCode:a}),e.text(t.message||"Failed to process invite",400)}}}function Ee(i){return async e=>{const r=e.get("logger"),a=i.getConfig().ssoDirect,n=new URL(e.req.url),f=e.req.query("inviteCode"),t=e.req.header("x-forwarded-proto")||n.protocol.slice(0,-1)||"https",c=e.req.header("x-forwarded-host")||n.host,s=`${t}://${c}`;let d=n.searchParams.get("idpId");const y=n.searchParams.get("redirectTo"),p=Object.keys(a||{})[0];d=d||p;const l=n.searchParams.get("mcp_redirect_uri"),m=!!l;if(!a?.[d]){const o="Invalid idpId";if(r.error(`IdP login error: ${o}`),m){const U=K(y||void 0);M.sendMcpAuthorizationFailedMessage([{...k(U),error:o,error_details:null}])}return e.text(`Forbidden: ${o}`,403)}const g=d&&a?await x(d,a[d]):void 0,A={};for(const o of Object.keys(g?.extraParams||{}))A[o]=n.searchParams.get(o)||g?.extraParams?.[o]||void 0;let C,u={};if(m&&l&&g&&g.type===W.OIDC){r.info(`Building MCP OAuth login URL with redirect_uri: ${l}`);const o=ge("",{...g,extraParams:A},y,f,{redirectUriOverride:l,sourceOverride:"mcp",branchOverride:void 0});C=o.loginUrl,u=o.cookies||{}}else if(g){const o=oe({...g,extraParams:A},s,y,f);C=o.loginUrl,u=o.cookies||{}}return Object.keys(u).forEach(o=>{_(e,o,u[o].value,u[o].options)}),r.info(`IdP login initiated for ID '${d}'`),e.newResponse(null,302,{Location:C||new URL(e.req.url).pathname})}}function Fe(i){return async e=>{const r=e.get("logger"),a=await e.req.formData(),n=a.get("SAMLResponse"),f=a.get("RelayState");if(typeof n!="string"||typeof f!="string"){const o="SAMLResponse is required";return r.error(`SAML2 login error: ${o}`),e.text(`Bad request: ${o}`,400)}const t=ne(n),{success:c,uid:s,nameFormat:d,attrs:y,issuerId:p,expiresAt:l}=ie(t),{idpId:m,redirectTo:h}=JSON.parse(f);if(!c){const o="SAML2 assertion is not successful";return r.error(`SAML2 login error: ${o}`),e.text(`Permission denied: ${o}`,401)}if(!l||Math.ceil(Date.now()/1e3)>=l){const o="SAML2 Token Expired";return r.error(`SAML2 login error: ${o}`),e.text(o,401)}const g=i.getConfig().ssoDirect?.[m];if(!g||!ee(g)){const o="Cannot find valid IdP";return r.error(`SAML2 login error: ${o}`),e.text(`Permission denied: ${o}`,401)}if(!(g.issuerId&&p&&Y(g.issuerId,p))){const o="IssuerID is misconfigured or untrusted assertions issuer received";return r.error(`SAML2 login error: ${o}`),e.text(`Permission denied: ${o}`,401)}if(!await ae(t,g.x509PublicCert)){const o="SAMLResponse signature invalid";return r.error(`SAML2 login error: ${o}`),e.text(o,401)}const C=te(s,d,y,g.teamsAttributeName);if(!C.sub){const o="The provider did not return a valid user identity.";return r.error(`SAML2 login error: ${o}`),e.text(o,400)}if(!C.email){const o="The provider did not return a valid user email.";return r.error(`SAML2 login error: ${o}`),e.text(o,400)}const u=await O.sign({...C,idpId:m},v,P.HS256);return _(e,"authorization",u,{path:R()||"/",httpOnly:!0,expires:new Date(l*1e3)}),r.updateContext({email:C.email,subject:C.sub}),r.info("SAML2 login successful"),e.newResponse(null,302,{Location:h||"/"})}}function Be(i){return async e=>{const r=e.get("logger"),a=new URL(e.req.query("redirectTo")||"/",e.req.url),n=I(z(a.pathname)),f=i.getConfig().ssoDirect,t=Object.entries(f||{}).find(([,h])=>$(h)&&ue(h));if(!(f&&t))return e.newResponse(null,302,{Location:n});const s=e.req.query("token"),d=s&&await le(s);if(!d)return e.newResponse(null,302,{Location:n});if(!b(d[F]||[]).some(h=>h===Q||h===Z))return e.newResponse(null,302,{Location:n});const l=await O.sign({...d,idpId:t?.at(0)},v,P.HS256),m=Date.now()+B*1e3;return _(e,"authorization",l,{path:R()||"/",httpOnly:!0,expires:new Date(m),sameSite:"None",secure:!0}),r.info("Token login successful"),e.newResponse(null,302,{Location:n})}}export{ve as authorizeHandler,Ee as idpLoginHandler,be as inviteHandler,Te as logoutHandler,Ue as oidcCallbackHandler,qe as postLogoutHandler,$e as redoclyLoginCallbackHandler,Be as redoclyTokenLoginHandler,Fe as samlCallbackHandler};
@@ -0,0 +1,5 @@
1
+ import type { Context } from 'hono';
2
+ export declare function corsProxyHandler(proxyBasePath?: string): (ctx: Context) => Promise<Response>;
3
+ export declare function resolveCorsProxyTarget(requestUrl: string, proxyBasePath: string): URL | null;
4
+ export declare const CORS_PROXY_STREAM_HEADER = "x-redocly-proxy-streaming";
5
+ //# sourceMappingURL=cors-proxy.d.ts.map
@@ -0,0 +1,2 @@
1
+ import{withPathPrefix as O}from"@redocly/theme/core/utils";import{ServerRoutes as _}from"../../../constants/common.js";import{getRequestOrigin as q}from"../utils/get-request-origin.js";const C=new Set(["connection","keep-alive","proxy-authenticate","proxy-connection","proxy-authorization","te","trailer","transfer-encoding","upgrade","host"]),P=new Set(["cookie","cookie2"]),T=new Set(["set-cookie","set-cookie2"]),E="x-redocly-proxy-streaming",H="x-http-method-override",w="x-redocly-cookie";function x(o=O(_.CORS_PROXY)){return async e=>{const r=new URL(e.req.url).pathname;if(r===o||r===`${o}/`)return e.text(`Realm CORS proxy endpoint.
2
+ Usage: ${o}/https://api.example.com/path`);const n=L(e.req.url,o);if(!n)return e.text("Invalid proxied URL",400);const i=q(e),c=n.origin===i,h=n.pathname===o||n.pathname.startsWith(`${o}/`);if(c&&!h)return new Response("Please use a direct request",{status:308,headers:{Location:n.toString(),Vary:"origin","Cache-Control":"private"}});const s=new Headers,f=S(e.req.raw.headers);for(const[t,y]of e.req.raw.headers)f.has(t.toLowerCase())||P.has(t.toLowerCase())||s.append(t,y);const d=s.get(w);if(d){const t=e.req.raw.headers.get("cookie")||"";s.set("cookie",t?`${t}; ${d}`:d),s.delete(w)}const u=e.req.raw.headers.get("origin")||"";A(u)&&s.delete("origin");let p=e.req.method;const m=s.get(H);m&&(p=m.toUpperCase(),s.delete(H));const R={method:p,headers:s,redirect:"follow"};p!=="GET"&&p!=="HEAD"&&e.req.raw.body&&(R.body=e.req.raw.body,R.duplex="half");let a;try{a=await fetch(n,R)}catch(t){return e.text(`Failed to proxy request: ${t instanceof Error?t.message:"unknown error"}`,502)}const l=new Headers(a.headers),g=S(a.headers);for(const t of g)l.delete(t);for(const t of T)l.delete(t);return l.set(E,"1"),new Response(a.body,{status:a.status,statusText:a.statusText,headers:l})}}function k(o){try{return decodeURIComponent(o)}catch{return o}}function D(o){return o.replace(/^(https?):\/(?!\/)/i,"$1://")}function $(o,e){return e?o.includes("?")?e==="?"?o:`${o.endsWith("?")||o.endsWith("&")?o:`${o}&`}${e.slice(1)}`:`${o}${e}`:o}function S(o){const e=new Set(C),r=o.get("connection");if(!r)return e;for(const n of r.split(",")){const i=n.trim().toLowerCase();i&&e.add(i)}return e}function A(o){const e=o.toLowerCase();return e.includes(".redocly.app")||e.includes("localhost")}function L(o,e){const r=new URL(o),n=r.pathname===e,i=r.pathname.startsWith(`${e}/`);if(!n&&!i)return null;const c=r.pathname.slice(e.length).replace(/^\/+/,"");if(!c)return null;const h=[c,k(c)];for(const s of h){const f=D(s),d=$(f,r.search);try{const u=new URL(d);if(u.protocol==="http:"||u.protocol==="https:")return u}catch{continue}}return null}const z=E;export{z as CORS_PROXY_STREAM_HEADER,x as corsProxyHandler,L as resolveCorsProxyTarget};
@@ -1 +1 @@
1
- import u from"path";import{REDOCLY_ROUTE_RBAC as E,REDOCLY_TEAMS_RBAC as w}from"@redocly/config";import{withoutPathPrefix as q,withPathPrefix as D}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_CACHE_HEADER_VALUE as L,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as O}from"../../constants/common.js";import{removeTrailingSlash as v}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as F}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as H}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as z}from"../../../config/env-config.js";import{sanitizePath as B}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as G}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as Y}from"../../../utils/path/is-path-in-folder.js";import{processRedirects as $}from"./helpers/process-redirects.js";import{renderPage as k,getServerProps as N}from"../../ssr/index.js";import{canAccessAsset as W,canAccessResource as _}from"../../utils/rbac.js";import{handleErrorPageRender as y,handleUnauthorized as P,handleUnauthorizedAsset as U}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as X,MIME_TYPES as j}from"../mime-types.js";import{fileExistsAsync as V}from"../../utils/index.js";import{getRedirectRoute as Z}from"../utils/legacy-openapi-redirects.js";import{telemetry as J}from"../../../cli/telemetry/index.js";import{telemetry as K}from"../../telemetry/index.js";function Ee(e,I,T){return async o=>{const h=o.get("logger"),l=o.req,i=new URL(l.url),n=q(B(decodeURIComponent(i.pathname))),R=u.parse(n).ext===".md",m=G(n),r=(l.method==="GET"||l.method==="HEAD")&&!R?e.getRouteBySlug(m,{followRedirect:!1})||F(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(n===t.slug||n.startsWith(t.slug+"/"))):void 0,A=e.getRedirect(m);if(A){const t=$({redirect:A,reqUrlSearch:i.search});return K.sendRedirectMessage([{object:"redirect",from:m,templateId:t.type.toString()}]),o.newResponse(null,t.type,{Location:t.location})}const d=z.isProductionEnv?301:302;if(r?.metadata?.type==="openapi"){const t=Z(i.pathname);if(t)return h.info("Legacy OpenAPI docs redirect from "+i.pathname),o.newResponse(null,d,{Location:encodeURI(t)});if(i.pathname.match(/[A-Z]/))return h.warn("Redirect to lowercase route to avoid 404 error"),o.newResponse(null,d,{Location:encodeURI(i.pathname.toLowerCase())})}if(n.endsWith("/")&&n!=="/"){const t=H(new URL(m||"/",o.req.url).pathname);return o.newResponse(null,d,{Location:encodeURI(D((t==="/"?"/":v(t))+i.search))})}const{isAuthenticated:c,teams:f,claims:{email:p}}=o.get("auth");if(r){if(!_(r,{isAuthenticated:c,email:p,teams:f},e.config.rbac,e.config.requiresLogin))return c?y(o,e,{slug:r.slug,[w]:r[w],[E]:r[E]},403):P(o,e,r.slug);const t=await I(r),s=await N(r,o,t,e),{html:b,statusCode:M}=await k(r,s,o,e,J);return o.html(b,M,{"Cache-Control":L})}const a=u.resolve(e.outdir,"."+n);if(!Y(a,e.outdir))return U(o);if(R){const t=n==="index.html.md"?"/":n.replace(/\.md$/,""),s=e.getRouteBySlug(t,{followRedirect:!1});if(s&&!_(s,{isAuthenticated:c,email:p,teams:f},e.config.rbac,e.config.requiresLogin))return P(o,e,n)}if(!W(n,e.getGlobalConfig("rbac"),e.getGlobalConfig("requiresLogin"),e.getGlobalConfig("directoryPaths"),{isAuthenticated:c,email:p,teams:f}))return U(o);const C=j[u.extname(a)]||"text/plain",g=a.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||a.match(/runtime\/chunks\/.*/)?O:X[C],S=g?{"Cache-Control":`public, max-age=${g}, immutable`,Expires:new Date(Date.now()+g*1e3).toUTCString()}:{"Cache-Control":L};if(await V(a)){const t=l.query("download")!=null,s=await T(a);return o.newResponse(s,200,{"Content-Type":C,"Access-Control-Allow-Origin":"*",...S,...t&&{"Content-Disposition":`attachment; filename="${u.basename(a)}"`}})}else return y(o,e,{slug:m},404)}}export{Ee as dynamicRouteHandler};
1
+ import u from"path";import{REDOCLY_ROUTE_RBAC as L,REDOCLY_TEAMS_RBAC as P}from"@redocly/config";import{withoutPathPrefix as O,withPathPrefix as v}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_CACHE_HEADER_VALUE as _,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as F}from"../../constants/common.js";import{removeTrailingSlash as H}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as z}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as B}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as G}from"../../config/env-config.js";import{sanitizePath as Y}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as $}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as k}from"../../../utils/path/is-path-in-folder.js";import{getMdAssetPathname as N}from"./helpers/get-md-asset-pathname.js";import{processRedirects as W}from"./helpers/process-redirects.js";import{renderPage as X,getServerProps as j}from"../../ssr/index.js";import{canAccessAsset as V,canAccessResource as y}from"../../utils/rbac.js";import{handleErrorPageRender as I,handleUnauthorized as U,handleUnauthorizedAsset as T}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as Z,MIME_TYPES as J}from"../mime-types.js";import{fileExistsAsync as K}from"../../utils/index.js";import{isAiAgentRequest as Q}from"../../utils/ai-agent-detection.js";import{getRedirectRoute as x}from"../utils/legacy-openapi-redirects.js";import{telemetry as ee}from"../../../cli/telemetry/index.js";import{telemetry as te}from"../../telemetry/index.js";function Ie(e,S,b){return async n=>{const R=n.get("logger"),i=n.req,a=new URL(i.url),r=O(Y(decodeURIComponent(a.pathname))),d=u.parse(r).ext===".md",g=Q({accept:i.header("accept"),signatureAgent:i.header("signature-agent"),signature:i.header("signature"),signatureInput:i.header("signature-input"),userAgent:i.header("user-agent")}),c=$(r),o=(i.method==="GET"||i.method==="HEAD")&&!d&&!g?e.getRouteBySlug(c,{followRedirect:!1})||z(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(r===t.slug||r.startsWith(t.slug+"/"))):void 0,C=e.getRedirect(c);if(C){const t=W({redirect:C,reqUrlSearch:a.search});return te.sendRedirectMessage([{object:"redirect",from:c,templateId:t.type.toString()}]),n.newResponse(null,t.type,{Location:t.location})}const f=G.isProductionEnv?301:302;if(o?.metadata?.type==="openapi"){const t=x(a.pathname);if(t)return R.info("Legacy OpenAPI docs redirect from "+a.pathname),n.newResponse(null,f,{Location:encodeURI(t)});if(a.pathname.match(/[A-Z]/))return R.warn("Redirect to lowercase route to avoid 404 error"),n.newResponse(null,f,{Location:encodeURI(a.pathname.toLowerCase())})}if(r.endsWith("/")&&r!=="/"){const t=B(new URL(c||"/",n.req.url).pathname);return n.newResponse(null,f,{Location:encodeURI(v((t==="/"?"/":H(t))+a.search))})}const{isAuthenticated:l,teams:p,claims:{email:h}}=n.get("auth");if(o){if(!y(o,{isAuthenticated:l,email:h,teams:p},e.config.rbac,e.config.requiresLogin))return l?I(n,e,{slug:o.slug,[P]:o[P],[L]:o[L]},403):U(n,e,o.slug);const t=await S(o),m=await j(o,n,t,e),{html:q,statusCode:D}=await X(o,m,n,e,ee);return n.html(q,D,{"Cache-Control":_})}const E=N(r,g,d),s=u.resolve(e.outdir,"."+E);if(!k(s,e.outdir))return T(n);if(d||g){const t=r==="index.html.md"?"/":r.replace(/\.md$/,""),m=e.getRouteBySlug(t,{followRedirect:!1});if(m&&!y(m,{isAuthenticated:l,email:h,teams:p},e.config.rbac,e.config.requiresLogin))return U(n,e,r)}if(!V(E,e.getGlobalConfig("rbac"),e.getGlobalConfig("requiresLogin"),e.getGlobalConfig("directoryPaths"),{isAuthenticated:l,email:h,teams:p}))return T(n);const w=J[u.extname(s)]||"text/plain",A=s.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||s.match(/runtime\/chunks\/.*/)?F:Z[w],M=A?{"Cache-Control":`public, max-age=${A}, immutable`,Expires:new Date(Date.now()+A*1e3).toUTCString()}:{"Cache-Control":_};if(await K(s)){const t=i.query("download")!=null,m=await b(s);return n.newResponse(m,200,{"Content-Type":w,"Access-Control-Allow-Origin":"*",...M,...t&&{"Content-Disposition":`attachment; filename="${u.basename(s)}"`}})}else return I(n,e,{slug:c},404)}}export{Ie as dynamicRouteHandler};
@@ -1 +1 @@
1
- import{context as n,SpanStatusCode as s,trace as o}from"@opentelemetry/api";import{envConfig as a}from"../../../config/env-config.js";const m=e=>{const t=o?.getSpan(n.active());return t&&(t.setStatus({code:s.ERROR,message:e.message}),t.recordException(e),t.end()),e instanceof Error&&"name"in e&&e.name==="URIError"?new Response("Malformed URL",{status:400}):a.isDevelopMode&&e?.name==="PageMissingDefaultExportError"?new Response(e.message,{status:200}):new Response("Internal Server Error",{status:500})};export{m as errorHandler};
1
+ import{context as n,SpanStatusCode as s,trace as o}from"@opentelemetry/api";import{envConfig as a}from"../../config/env-config.js";const m=e=>{const t=o?.getSpan(n.active());return t&&(t.setStatus({code:s.ERROR,message:e.message}),t.recordException(e),t.end()),e instanceof Error&&"name"in e&&e.name==="URIError"?new Response("Malformed URL",{status:400}):a.isDevelopMode&&e?.name==="PageMissingDefaultExportError"?new Response(e.message,{status:200}):new Response("Internal Server Error",{status:500})};export{m as errorHandler};
@@ -1 +1 @@
1
- import{FEEDBACK_API_URL as k}from"../../constants/common.js";import{mapObject as j}from"../../../utils/object/map-object.js";import{getClientIp as y}from"../utils/get-client-ip.js";import{canAccessResource as A}from"../../utils/rbac.js";function w(n){if(!n)return n;const e=["userAgent","firstName","lastName","auth_time","platform","id","email","ipAddress"];return j(n,(o,a)=>e.includes(a)?o:"*****")}function C({component:n,path:e,location:o,lang:a,score:d,max:s,reasons:i,comment:r,metadata:c,email:m}){return{feedbackComponent:n.toUpperCase(),path:e,location:o,lang:a,score:d,maxScore:s,reasons:i,comment:r,email:m,metadata:w(c)}}async function F(n,e){return(await fetch(k,{method:"POST",body:JSON.stringify(C(n)),headers:e})).json()}function U(n){return async e=>{const o=await e.req.json(),a=e.req.header("user-agent"),d=y(e.req.raw),s=e.req.header("Sec-Ch-Ua-Platform"),i={...o.metadata,userAgent:a,ipAddress:d,platform:s?s.replace(/"/g,""):"unknown"},r=[];(!o.path||o.path==="")&&r.push("`path` is required");const c=["sentiment","rating","comment","problem","mood","scale"];if(c.includes(o.component)||r.push(`\`component\` field should be one of ${c.join(", ")}.`),r.length)return e.json({errors:r},400);const{claims:m,isAuthenticated:u,teams:l}=e.get("auth"),h={isAuthenticated:u,email:m?.email,teams:l};if(Object.keys(n.config.rbac||{}).length>0){const t=o.path,g=new URL(t).pathname,p=n.getRouteBySlug(g);if(!p)return e.json({errors:["Resource not found"]},404);if(!A(p,h,n.config.rbac,n.config.requiresLogin))return e.json({errors:["Forbidden: no permission to send feedback for resource"]},403)}const b={"Content-Type":"application/json"},f=m?.email||o?.email||i?.email;try{const t=await F({...o,email:f,metadata:{email:f,...i}},b);return e.json({message:"Thanks for your feedback",...t},200,{})}catch(t){return e.json({errors:["Failed to send feedback",t.message]},500)}}}export{U as feedbackHandler,w as normalizeFeedbackMetadata};
1
+ import{FEEDBACK_API_URL as k}from"../../constants/common.js";import{MAX_CONTEXT_LENGTH as p,MAX_EMAIL_LENGTH as _,MAX_LANG_LENGTH as j,MAX_PATH_LENGTH as E,MAX_REASONS_COUNT as N}from"../../constants/feedback.js";import{mapObject as T}from"../../../utils/object/map-object.js";import{getClientIp as C}from"../utils/get-client-ip.js";import{canAccessResource as S}from"../../utils/rbac.js";function o(n,e){if(n!=null)return String(n).replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,"").trim().slice(0,e)||void 0}function F(n){if(!n)return n;const e=["userAgent","firstName","lastName","auth_time","platform","id","email","ipAddress"];return T(n,(r,a)=>e.includes(a)?r:"*****")}function L({component:n,path:e,location:r,lang:a,score:m,max:s,reasons:i,comment:t,metadata:f,email:u}){const l=Array.isArray(i)?i.map(c=>o(String(c),p)).filter(c=>!!c).slice(0,N):void 0;return{feedbackComponent:n.toUpperCase(),path:o(e,E),location:o(r,p),lang:o(a,j),score:typeof m=="number"?m:void 0,maxScore:typeof s=="number"?s:void 0,reasons:l?.length?l:void 0,comment:o(t,p),email:o(u,_),metadata:F(f)}}async function w(n,e){return(await fetch(k,{method:"POST",body:JSON.stringify(L(n)),headers:e})).json()}function G(n){return async e=>{const r=await e.req.json(),a=e.req.header("user-agent"),m=C(e.req.raw),s=e.req.header("Sec-Ch-Ua-Platform"),i={...r.metadata,userAgent:a,ipAddress:m,platform:s?s.replace(/"/g,""):"unknown"},t=[];(!r.path||r.path==="")&&t.push("`path` is required");const f=["sentiment","rating","comment","problem","mood","scale"];if(f.includes(r.component)||t.push(`\`component\` field should be one of ${f.join(", ")}.`),t.length)return e.json({errors:t},400);const{claims:u,isAuthenticated:l,teams:c}=e.get("auth"),b={isAuthenticated:l,email:u?.email,teams:c};if(Object.keys(n.config.rbac||{}).length>0){const d=r.path,y=new URL(d).pathname,g=n.getRouteBySlug(y);if(!g)return e.json({errors:["Resource not found"]},404);if(!S(g,b,n.config.rbac,n.config.requiresLogin))return e.json({errors:["Forbidden: no permission to send feedback for resource"]},403)}const A={"Content-Type":"application/json"},h=u?.email||r?.email||i?.email;try{const d=await w({...r,email:h,metadata:{email:h,...i}},A);return e.json({message:"Thanks for your feedback",...d},200,{})}catch(d){return e.json({errors:["Failed to send feedback",d.message]},500)}}}export{G as feedbackHandler,F as normalizeFeedbackMetadata};
@@ -0,0 +1,2 @@
1
+ export declare function getMdAssetPathname(pathname: string, isAiAgent: boolean, hasMdExtension: boolean): string;
2
+ //# sourceMappingURL=get-md-asset-pathname.d.ts.map
@@ -0,0 +1 @@
1
+ function d(t,e,r){return e&&!r?t==="/"?"index.html.md":t+".md":t}export{d as getMdAssetPathname};
@@ -1 +1 @@
1
- import{serveStatic as H}from"hono/serve-static";import{withPathPrefix as e,withoutPathPrefix as R}from"@redocly/theme/core/utils";import{ServerRoutes as l}from"../../../constants/common.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 g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as S}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as I}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as P,oidcCallbackHandler as D,logoutHandler as A,postLogoutHandler as h,idpLoginHandler as M,redoclyLoginCallbackHandler as N,samlCallbackHandler as v,redoclyTokenLoginHandler as B,inviteHandler as U}from"./auth.js";import{appDataHandler as w}from"./app-data.js";import{searchFacetsHandler as G,searchHandler as F}from"./search.js";import{dynamicRouteHandler as K}from"./dynamic-route.js";import{pageDataHandler as y,sharedPageDataHandler as k}from"./page-data.js";import{pathPrefixRedirectHandler as Y}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as _,resolvePathHandler as O,resolvePathsHandler as b,resolveSlugHandler as r}from"./resolve-route.js";import{feedbackHandler as V}from"./feedback.js";import{loggerMiddleware as x}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as $}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as z}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as Z}from"./otel/otel.js";import{healthCheckHandler as u}from"./health.js";import{askAiHandler as q}from"./ask-ai.js";import{replayOauth2RedirectCallbackHandler as W}from"./replay-oauth2-redirect.js";import{mcpOAuthProtectedResourceHandler as j,mcpOAuthAuthorizationServerHandler as J,mcpDynamicClientRegistrationHandler as Q,mcpAuthorizationHandler as X,mcpTokenPortalHandler as aa,mcpCallbackHandler as E}from"./mcp-oauth.js";import{corsMiddleware as T}from"../middleware/corsMiddleware.js";import{installApiRoutes as ea}from"./api-routes/api-routes.js";import{cookieMiddleware as ia}from"../middleware/cookieMiddleware.js";import{staticContentHandler as la}from"../routes/static-content.js";import{infoHandler as f}from"./info.js";import{catalogHandler as ta}from"./catalog/catalog.js";import{catalogRelationsHandler as ma}from"./catalog/catalog-relations.js";import{bffCatalogHandler as na}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as da}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as oa}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as t}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as pa}from"../middleware/telemetry-middleware.js";import{errorHandler as Aa}from"./error.js";function ja(a,i,m){const{resolveRouteData:d,readStaticAsset:o}=m;a.use("*",z()),a.use("*",ia()),a.use("*",S(i)),a.use("*",c(i)),a.use("*",x()),a.use("*",$(i)),a.use("*",pa()),a.use(e("*"),H({root:`./${C}`,getContent:(n,s)=>la(n,s,i,o),rewriteRequestPath:n=>R(n)})),a.use(e(l.FEEDBACK),T({allowMethods:["POST"]})),a.use(e(l.ASK_AI),T({allowMethods:["POST"]})),a.use("*",_a(i));const p=g(i);a.use(e(l.INFO),f()),L.NEW_CATALOG_ENABLED==="true"&&(a.use(e(l.CATALOG_ENTITIES),t({serverOutDir:i.serverOutDir}),ta(i)),a.use(e(l.CATALOG_ENTITIES_RELATIONS),t({serverOutDir:i.serverOutDir}),ma(i)),a.get(e(l.BFF_CATALOG_ENTITIES),t({serverOutDir:i.serverOutDir,protectReadMethods:!1}),na(i)),a.get(e(l.BFF_CATALOG_RELATED_ENTITIES),t({serverOutDir:i.serverOutDir,protectReadMethods:!1}),oa(i)),a.get(e(l.BFF_CATALOG_REVISIONS),t({serverOutDir:i.serverOutDir,protectReadMethods:!1}),da(i))),a.get(e(l.SHARED_PAGE_DATA),k(i)),a.get(e(l.PAGE_DATA),y(i,d)),a.get(e(l.APP_DATA),w(i)),a.post(e(l.SEARCH),p,F(i)),a.post(e(l.SEARCH_FACETS),p,G(i)),a.post(e(l.AUTHORIZATION),P),a.post(e(l.LOGOUT),A(i)),a.get(e(l.LOGOUT),A(i)),a.get(e(l.POST_LOGOUT),h(i)),a.get(e(l.OIDC_CALLBACK),D(i)),a.get(e(l.REDOCLY_TOKEN_LOGIN),B(i)),a.get(e(l.REDOCLY_LOGIN_CALLBACK),N()),a.get(e(l.IDP_LOGIN),M(i)),a.post(e(l.SAML_CALLBACK),v(i)),a.get(e(l.INVITE),U(i)),a.get(e(l.HEALTH),u),a.get(`${l.MCP_OAUTH_PROTECTED_RESOURCE}${e("/mcp")}`,j()),a.get(l.MCP_OAUTH_AUTHORIZATION_SERVER,J()),a.post(e(l.MCP_DYNAMIC_CLIENT_REGISTRATION),Q()),a.get(e(l.MCP_AUTHORIZATION),X()),a.post(e(l.MCP_TOKEN_PORTAL),aa()),a.get(e(l.MCP_CALLBACK),E()),a.get(e(`${l.MCP_CALLBACK}/*`),E()),I(a,i),ea(a,i),a.post(e(l.FEEDBACK),V(i)),a.post(e(l.RESOLVE_ROUTE_BY_PATH),O(i)),a.post(e(l.RESOLVE_ROUTES_BY_PATHS),b(i)),a.post(e(l.RESOLVE_ROUTE_BY_SLUG),r(i)),a.post(e(l.ASK_AI),q(i)),a.get(e(l.GET_ROUTES_BY_LINE),_(i)),a.post(e(l.OTEL_TRACES),Z),a.get(e(l.REPLAY_OAUTH2_CALLBACK),W),a.all(e("/*"),K(i,d,o)),a.get("*",Y),a.onError(Aa)}function _a(a){return async(i,m)=>{await a.waitForPluginsLifecycle(),await m()}}function Ja(a,i){a.get(e(l.INFO),f()),a.post(e(l.RESOLVE_ROUTE_BY_PATH),O(i)),a.post(e(l.RESOLVE_ROUTE_BY_SLUG),r(i)),a.get(e(l.GET_ROUTES_BY_LINE),_(i))}export{Ja as installDevRoutes,ja as installProdRoutes,_a as waitForPluginsLifecycle};
1
+ import{serveStatic as C}from"hono/serve-static";import{withPathPrefix as e,withoutPathPrefix as H}from"@redocly/theme/core/utils";import{ServerRoutes as i}from"../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as c}from"../../constants/common.js";import{envConfig as L}from"../../config/env-config.js";import{authMiddleware as S}from"../middleware/authMiddleware.js";import{ensureSearchData as g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as P}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as I}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as D,oidcCallbackHandler as h,logoutHandler as O,postLogoutHandler as M,idpLoginHandler as N,redoclyLoginCallbackHandler as v,samlCallbackHandler as B,redoclyTokenLoginHandler as w,inviteHandler as U}from"./auth.js";import{appDataHandler as G}from"./app-data.js";import{searchFacetsHandler as F,searchHandler as y}from"./search.js";import{dynamicRouteHandler as K}from"./dynamic-route.js";import{pageDataHandler as Y,sharedPageDataHandler as k}from"./page-data.js";import{pathPrefixRedirectHandler as b}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as _,resolvePathHandler as E,resolvePathsHandler as V,resolveSlugHandler as T}from"./resolve-route.js";import{feedbackHandler as x}from"./feedback.js";import{loggerMiddleware as $}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as z}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as Z}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as X}from"./otel/otel.js";import{healthCheckHandler as q}from"./health.js";import{askAiHandler as W}from"./ask-ai.js";import{semanticSearchHandler as j}from"./semantic-search.js";import{replayOauth2RedirectCallbackHandler as J}from"./replay-oauth2-redirect.js";import{corsProxyHandler as r}from"./cors-proxy.js";import{mcpOAuthProtectedResourceHandler as Q,mcpOAuthAuthorizationServerHandler as u,mcpDynamicClientRegistrationHandler as aa,mcpAuthorizationHandler as ea,mcpTokenPortalHandler as ia,mcpCallbackHandler as f}from"./mcp-oauth.js";import{corsMiddleware as d}from"../middleware/corsMiddleware.js";import{installApiRoutes as la}from"./api-routes/api-routes.js";import{cookieMiddleware as ta}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ma}from"../routes/static-content.js";import{infoHandler as s}from"./info.js";import{catalogHandler as na}from"./catalog/catalog.js";import{catalogRelationsHandler as da}from"./catalog/catalog-relations.js";import{bffCatalogHandler as oa}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as pa}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as Aa}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as t}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as Oa}from"../middleware/telemetry-middleware.js";import{errorHandler as _a}from"./error.js";function ae(a,l,m){const{resolveRouteData:o,readStaticAsset:p}=m;a.use("*",Z()),a.use("*",ta()),a.use("*",P(l)),a.use("*",S(l)),a.use("*",$()),a.use("*",z(l)),a.use("*",Oa()),a.use(e("*"),C({root:`./${c}`,getContent:(n,R)=>ma(n,R,l,p),rewriteRequestPath:n=>H(n)})),a.use(e(i.FEEDBACK),d({allowMethods:["POST"]})),a.use(e(i.ASK_AI),d({allowMethods:["POST"]})),a.use(e(i.SEMANTIC_SEARCH),d({allowMethods:["POST"]})),a.use("*",Ea(l));const A=g(l);a.use(e(i.INFO),s()),L.NEW_CATALOG_ENABLED==="true"&&(a.use(e(i.CATALOG_ENTITIES),t({serverOutDir:l.serverOutDir}),na(l)),a.use(e(i.CATALOG_ENTITIES_RELATIONS),t({serverOutDir:l.serverOutDir}),da(l)),a.get(e(i.BFF_CATALOG_ENTITIES),t({serverOutDir:l.serverOutDir,protectReadMethods:!1}),oa(l)),a.get(e(i.BFF_CATALOG_RELATED_ENTITIES),t({serverOutDir:l.serverOutDir,protectReadMethods:!1}),Aa(l)),a.get(e(i.BFF_CATALOG_REVISIONS),t({serverOutDir:l.serverOutDir,protectReadMethods:!1}),pa(l))),a.get(e(i.SHARED_PAGE_DATA),k(l)),a.get(e(i.PAGE_DATA),Y(l,o)),a.get(e(i.APP_DATA),G(l)),a.post(e(i.SEARCH),A,y(l)),a.post(e(i.SEARCH_FACETS),A,F(l)),a.post(e(i.AUTHORIZATION),D),a.post(e(i.LOGOUT),O(l)),a.get(e(i.LOGOUT),O(l)),a.get(e(i.POST_LOGOUT),M(l)),a.get(e(i.OIDC_CALLBACK),h(l)),a.get(e(i.REDOCLY_TOKEN_LOGIN),w(l)),a.get(e(i.REDOCLY_LOGIN_CALLBACK),v()),a.get(e(i.IDP_LOGIN),N(l)),a.post(e(i.SAML_CALLBACK),B(l)),a.get(e(i.INVITE),U(l)),a.get(e(i.HEALTH),q),a.get(`${i.MCP_OAUTH_PROTECTED_RESOURCE}${e("/mcp")}`,Q()),a.get(i.MCP_OAUTH_AUTHORIZATION_SERVER,u()),a.post(e(i.MCP_DYNAMIC_CLIENT_REGISTRATION),aa()),a.get(e(i.MCP_AUTHORIZATION),ea()),a.post(e(i.MCP_TOKEN_PORTAL),ia()),a.get(e(i.MCP_CALLBACK),f()),a.get(e(`${i.MCP_CALLBACK}/*`),f()),I(a,l),a.all(e(i.CORS_PROXY),r()),a.all(e(`${i.CORS_PROXY}/*`),r()),la(a,l),a.post(e(i.FEEDBACK),x(l)),a.post(e(i.RESOLVE_ROUTE_BY_PATH),E(l)),a.post(e(i.RESOLVE_ROUTES_BY_PATHS),V(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),T(l)),a.post(e(i.ASK_AI),W(l)),a.post(e(i.SEMANTIC_SEARCH),j(l)),a.get(e(i.GET_ROUTES_BY_LINE),_(l)),a.post(e(i.OTEL_TRACES),X),a.get(e(i.REPLAY_OAUTH2_CALLBACK),J),a.all(e("/*"),K(l,o,p)),a.get("*",b),a.onError(_a)}function Ea(a){return async(l,m)=>{await a.waitForPluginsLifecycle(),await m()}}function ee(a,l){a.get(e(i.INFO),s()),a.post(e(i.RESOLVE_ROUTE_BY_PATH),E(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),T(l)),a.get(e(i.GET_ROUTES_BY_LINE),_(l))}export{ee as installDevRoutes,ae as installProdRoutes,Ea as waitForPluginsLifecycle};
@@ -1 +1 @@
1
- import{envConfig as r}from"../../../config/env-config.js";function e(){return async n=>n.json({version:r.REDOCLY_PORTAL_VERSION},200)}export{e as infoHandler};
1
+ import{envConfig as r}from"../../config/env-config.js";function e(){return async n=>n.json({version:r.REDOCLY_PORTAL_VERSION},200)}export{e as infoHandler};
@@ -1 +1 @@
1
- import{getCookie as y}from"hono/cookie";import{ulid as w}from"ulid";import{AUTH_URL as m,JWT_SECRET_KEY as M}from"../../constants/common.js";import{ServerRoutes as d}from"../../../constants/common.js";import{withPathPrefix as p}from"@redocly/theme/core/utils";import{telemetry as u}from"../../telemetry/index.js";import{envConfig as g}from"../../../config/env-config.js";import{createMcpAuthorizationCode as I,verifyMcpAuthorizationCode as k,createMcpSessionResource as _}from"../auth.js";import*as h from"../jwt/jwt.js";import{AlgorithmTypes as T}from"../jwt/types.js";import{getRequestOrigin as f}from"../utils/get-request-origin.js";const n=(e,r,o=200,a)=>e.json(r,o,{"Content-Type":"application/json",...a??{}});async function A(e){const r=Math.floor(Date.now()/1e3);return h.sign({type:"mcp_context",...e,iat:r,exp:r+600},M,T.HS256)}async function P(e){await h.verify(e,M,T.HS256);const{payload:r}=h.decode(e);if(r.type!=="mcp_context")throw new Error("Invalid context token type");return r}function q(){return async e=>{if(e.req.method!=="GET")return n(e,{error:"Method not allowed"},405,{Allow:"GET"});const r=f(e);return n(e,{resource:`${r}${p("/mcp")}`,authorization_servers:[r],bearer_methods_supported:["header"],resource_documentation:`${r}${d.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:["openid","profile","email","offline_access"],bearer_token_types_supported:["Bearer"]})}}function b(){return async e=>{const r=f(e);return n(e,{issuer:m||"",authorization_endpoint:`${r}${p(d.MCP_AUTHORIZATION)}`,token_endpoint:`${r}${p(d.MCP_TOKEN_PORTAL)}`,jwks_uri:`${m||""}/.well-known/jwks.json`,registration_endpoint:`${r}${p(d.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,scopes_supported:["openid","profile","email","offline_access"],response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token","client_credentials"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"]})}}function N(){return async e=>{if(e.req.method!=="POST")return n(e,{error:"Method not allowed"},405);try{return n(e,{client_id:g.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:["authorization_code","refresh_token"],response_types:["code"],scope:"openid offline email",subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201)}catch(r){return n(e,{error:"invalid_request",error_description:r?.message||"Unable to register client"},500)}}}function j(){return async e=>{const r=new URL(e.req.url),{searchParams:o}=r,a=o.get("redirect_uri"),t=w();u.sendMcpAuthorizationStartedMessage([{..._(t),redirect_uri:a||null}]);const s=f(e),c={isMcpFlow:!0,originalRedirectUri:a,mcpClientId:o.get("client_id"),mcpState:o.get("state"),mcpSessionId:t,timestamp:Date.now()};try{const i=await A(c),l=new URL(p(d.IDP_LOGIN),s);return l.searchParams.set("redirectTo",`${d.MCP_CALLBACK}/${i}`),l.searchParams.set("idpId","oidc"),e.redirect(l.toString())}catch(i){const l=i instanceof Error?i.message:String(i),S=i instanceof Error?i.stack:String(i);u.sendMcpAuthorizationFailedMessage([{..._(t),error:l,error_details:S}]);const C=new URL(p(`${m}/oauth2/auth`));return C.search=o.toString(),e.redirect(C.toString())}}}function F(){return async e=>{if(e.req.method!=="POST")return n(e,{error:"Method not allowed"},405);try{const r=await e.req.formData(),o=r.get("grant_type"),a=r.get("code"),t=r.get("redirect_uri")||void 0;if(o!=="authorization_code"||!a)return n(e,{error:"invalid_request",error_description:"Invalid grant type or missing authorization code"},400);try{const s=await k(a);if(t&&t!==s.redirect_uri)return n(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(g.OAUTH_CLIENT_ID&&s.client_id&&s.client_id!==g.OAUTH_CLIENT_ID)return n(e,{error:"invalid_client",error_description:"Client mismatch"},400);const c=s.id_token;return typeof c!="string"||c.length===0?n(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400):n(e,{access_token:c,token_type:"Bearer",expires_in:3600,scope:"openid profile email",id_token:c},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch{return n(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(r){const o=r instanceof Error?r.message:String(r);return n(e,{error:"server_error",error_description:"Failed to process token request",error_details:o},500)}}}function B(){return async e=>{const r=new URL(e.req.url);let o=r.searchParams.get("context");if(!o&&r.pathname.startsWith(p(`${d.MCP_CALLBACK}/`))){const t=r.pathname.split("/");o=t[t.length-1]}if(!o)return u.sendMcpAuthorizationFailedMessage([{..._(null),error:"Missing context parameter",error_details:null}]),e.text("Missing context parameter",400);let a=null;try{const t=await P(o);if(a=t.mcpSessionId||null,!t.isMcpFlow||!t.originalRedirectUri)throw new Error("Invalid MCP context");const s=y(e,"idp_id_token")||y(e,"authorization"),c=await I({idToken:s||"",clientId:t.mcpClientId||"",redirectUri:t.originalRedirectUri,ttlSec:600}),i=new URL(t.originalRedirectUri);return i.searchParams.set("code",c),t.mcpState&&i.searchParams.set("state",t.mcpState),u.sendMcpAuthorizationCompletedMessage([{..._(a),redirect_uri:t.originalRedirectUri||null}]),e.redirect(i.toString())}catch(t){const s=t instanceof Error?t.message:String(t),c=t instanceof Error?t.stack:String(t);return u.sendMcpAuthorizationFailedMessage([{..._(a),error:s,error_details:c}]),e.text(`Invalid MCP callback: ${s}`,400)}}}export{A as createMcpContextToken,j as mcpAuthorizationHandler,B as mcpCallbackHandler,N as mcpDynamicClientRegistrationHandler,b as mcpOAuthAuthorizationServerHandler,q as mcpOAuthProtectedResourceHandler,F as mcpTokenPortalHandler,P as verifyAndParseMcpContextToken};
1
+ import{getCookie as h}from"hono/cookie";import{ulid as w}from"ulid";import{AUTH_URL as f,JWT_SECRET_KEY as y}from"../../constants/common.js";import{ServerRoutes as p}from"../../../constants/common.js";import{withPathPrefix as l}from"@redocly/theme/core/utils";import{telemetry as _}from"../../telemetry/index.js";import{envConfig as C}from"../../config/env-config.js";import{createMcpAuthorizationCode as S,verifyMcpAuthorizationCode as A,createMcpSessionResource as u}from"../auth.js";import*as m from"../jwt/jwt.js";import{AlgorithmTypes as M}from"../jwt/types.js";import{getRequestOrigin as T}from"../utils/get-request-origin.js";const n=(e,r,o=200,a)=>e.json(r,o,{"Content-Type":"application/json",...a??{}});async function I(e){const r=Math.floor(Date.now()/1e3);return m.sign({type:"mcp_context",...e,iat:r,exp:r+600},y,M.HS256)}async function P(e){await m.verify(e,y,M.HS256);const{payload:r}=m.decode(e);if(r.type!=="mcp_context")throw new Error("Invalid context token type");return r}function q(){return async e=>{if(e.req.method!=="GET")return n(e,{error:"Method not allowed"},405,{Allow:"GET"});const r=T(e);return n(e,{resource:`${r}${l("/mcp")}`,authorization_servers:[r],bearer_methods_supported:["header"],resource_documentation:`${r}${p.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:["openid","profile","email","offline_access"],bearer_token_types_supported:["Bearer"]})}}function b(){return async e=>{const r=T(e);return n(e,{issuer:f||"",authorization_endpoint:`${r}${l(p.MCP_AUTHORIZATION)}`,token_endpoint:`${r}${l(p.MCP_TOKEN_PORTAL)}`,jwks_uri:`${f||""}/.well-known/jwks.json`,registration_endpoint:`${r}${l(p.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,scopes_supported:["openid","profile","email","offline_access"],response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token","client_credentials"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"]})}}function N(){return async e=>{if(e.req.method!=="POST")return n(e,{error:"Method not allowed"},405);try{return n(e,{client_id:C.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:["authorization_code","refresh_token"],response_types:["code"],scope:"openid offline email",subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201)}catch(r){return n(e,{error:"invalid_request",error_description:r?.message||"Unable to register client"},500)}}}function j(){return async e=>{const r=new URL(e.req.url),{searchParams:o}=r,a=o.get("redirect_uri"),t=w();_.sendMcpAuthorizationStartedMessage([{...u(t),redirect_uri:a||null}]);const i=T(e),c={isMcpFlow:!0,originalRedirectUri:a,mcpClientId:o.get("client_id"),mcpState:o.get("state"),mcpSessionId:t,timestamp:Date.now()};try{const s=await I(c),d=new URL(l(p.IDP_LOGIN),i);return d.searchParams.set("redirectTo",`${p.MCP_CALLBACK}/${s}`),d.searchParams.set("idpId","oidc"),e.redirect(d.toString())}catch(s){const d=s instanceof Error?s.message:String(s),g=s instanceof Error?s.stack:String(s);_.sendMcpAuthorizationFailedMessage([{...u(t),error:d,error_details:g}]);const k=new URL(l(`${f}/oauth2/auth`));return k.search=o.toString(),e.redirect(k.toString())}}}function F(){return async e=>{if(e.req.method!=="POST")return n(e,{error:"Method not allowed"},405);try{const r=await e.req.formData(),o=r.get("grant_type"),a=r.get("code"),t=r.get("redirect_uri")||void 0;if(o!=="authorization_code"||!a)return n(e,{error:"invalid_request",error_description:"Invalid grant type or missing authorization code"},400);try{const i=await A(a);if(t&&t!==i.redirect_uri)return n(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(C.OAUTH_CLIENT_ID&&i.client_id&&i.client_id!==C.OAUTH_CLIENT_ID)return n(e,{error:"invalid_client",error_description:"Client mismatch"},400);const c=i.id_token;if(typeof c!="string"||c.length===0)return n(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400);let s=c;if(i.idp_access_token){const{payload:g}=m.decode(c);s=await m.sign({...g,idp_access_token:i.idp_access_token},y)}return n(e,{access_token:s,token_type:"Bearer",expires_in:3600,scope:"openid profile email",id_token:c},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch{return n(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(r){const o=r instanceof Error?r.message:String(r);return n(e,{error:"server_error",error_description:"Failed to process token request",error_details:o},500)}}}function B(){return async e=>{const r=new URL(e.req.url);let o=r.searchParams.get("context");if(!o&&r.pathname.startsWith(l(`${p.MCP_CALLBACK}/`))){const t=r.pathname.split("/");o=t[t.length-1]}if(!o)return _.sendMcpAuthorizationFailedMessage([{...u(null),error:"Missing context parameter",error_details:null}]),e.text("Missing context parameter",400);let a=null;try{const t=await P(o);if(a=t.mcpSessionId||null,!t.isMcpFlow||!t.originalRedirectUri)throw new Error("Invalid MCP context");const i=h(e,"idp_id_token")||h(e,"authorization"),c=h(e,"idp_access_token"),s=await S({idToken:i||"",idpAccessToken:c||void 0,clientId:t.mcpClientId||"",redirectUri:t.originalRedirectUri,ttlSec:600}),d=new URL(t.originalRedirectUri);return d.searchParams.set("code",s),t.mcpState&&d.searchParams.set("state",t.mcpState),_.sendMcpAuthorizationCompletedMessage([{...u(a),redirect_uri:t.originalRedirectUri||null}]),e.redirect(d.toString())}catch(t){const i=t instanceof Error?t.message:String(t),c=t instanceof Error?t.stack:String(t);return _.sendMcpAuthorizationFailedMessage([{...u(a),error:i,error_details:c}]),e.text(`Invalid MCP callback: ${i}`,400)}}}export{I as createMcpContextToken,j as mcpAuthorizationHandler,B as mcpCallbackHandler,N as mcpDynamicClientRegistrationHandler,b as mcpOAuthAuthorizationServerHandler,q as mcpOAuthProtectedResourceHandler,F as mcpTokenPortalHandler,P as verifyAndParseMcpContextToken};
@@ -1 +1 @@
1
- import{envConfig as c}from"../../../../config/env-config.js";import{getClientIp as v}from"../../utils/get-client-ip.js";import{PRODUCT_NAME as d}from"../../../../config/product-gates.js";import{toAttribute as t,getAttributesStringValue as g}from"./otlp.js";const p=c.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces";async function T(e){const o=await e.req.json(),r=m(e),s={resourceSpans:o.resourceSpans.map(n=>{const u=g(n.resource.attributes.find(i=>i.key==="session_id"));return u?{...n,resource:{...n.resource,attributes:[...n.resource.attributes,...y(r,u)]},scopeSpans:n.scopeSpans.map(i=>({...i,spans:i.spans.map(a=>({...a,attributes:a.name.startsWith("event.")&&a.name!=="event.undefined"?A(a,r,u):a.attributes}))}))}:n})};return await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),e.newResponse(null,200,{})}function m(e){const o=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,r=v(e.req.raw)||e.req.raw.context.remoteAddr?.hostname,s=e.req.raw.headers.get("user-agent"),n=e.req.raw.headers.get("accept-language"),u=n?.split(",")[0];return{userId:o,clientIp:r,userAgent:s||void 0,acceptLanguage:n||void 0,locale:u}}function y(e,o){const r=[t("redocly.organization.id",c.ORGANIZATION_ID),t("redocly.organization.slug",c.ORGANIZATION_SLUG),t("redocly.project.id",c.PROJECT_ID),t("redocly.project.slug",c.PROJECT_SLUG),t("redocly.product.type",d.toLowerCase()),t("redocly.client.ip",e.clientIp),t("redocly.client.userAgent",e.userAgent),t("redocly.client.acceptLanguage",e.acceptLanguage),t("redocly.client.locale",e.locale)];return e.userId?r.push(t("redocly.user.id",e.userId)):r.push(t("redocly.anonymous.id",l(o))),r.filter(s=>s!==void 0)}function f(e,o,r){const s=b(e.userId,o),n=new Date(Math.floor(Number(r.startTimeUnixNano)/1e6)).toISOString(),u=r.attributes.find(_=>_.key==="cloudevents.event_data.uri"),i=u&&"stringValue"in u.value?[t("cloudevents.event_data.page.uri",u.value.stringValue)]:[];return[t("cloudevents.event_spec_version","1.0"),t("cloudevents.event_object","event"),t("cloudevents.event_origin","realm-ui"),t("cloudevents.event_source",s.uri),t("cloudevents.event_source_details.id",s.id),t("cloudevents.event_source_details.object",s.object),t("cloudevents.event_source_details.uri",s.uri),t("cloudevents.event_data_content_type","application/json; charset=utf-8"),t("cloudevents.event_organization_id",c.ORGANIZATION_ID),t("cloudevents.event_organization_slug",c.ORGANIZATION_SLUG),t("cloudevents.event_project_id",c.PROJECT_ID),t("cloudevents.event_project_slug",c.PROJECT_SLUG),t("cloudevents.event_product_type",d.toLowerCase()),t("cloudevents.event_session_id",o),t("cloudevents.event_time",n),t("cloudevents.event_client.ip",e.clientIp),t("cloudevents.event_client.user_agent",e.userAgent),t("cloudevents.event_client.accept_language",e.acceptLanguage),t("cloudevents.event_client.locale",e.locale),...i]}function A(e,o,r){return[...e.attributes.filter(n=>{const u="stringValue"in n.value&&n.value.stringValue==="",i=/cloudevents\.event_source_details\..+/.test(n.key);return!(u||i)}),...f(o,r,e)].filter(n=>n!==void 0)}function b(e,o){return e?{id:e,object:"user",uri:`${c.MAIN_API_URL}/users/${e}`}:{id:l(o),object:"anonymous",uri:`${c.MAIN_API_URL}/anonymous/${l(o)}`}}function l(e){return e.replace("ses_","ann_")}export{T as otelTracesHandler,A as toCloudEventAttributes,b as toSource};
1
+ import{envConfig as c}from"../../../config/env-config.js";import{getClientIp as v}from"../../utils/get-client-ip.js";import{PRODUCT_NAME as d}from"../../../../config/product-gates.js";import{toAttribute as t,getAttributesStringValue as g}from"./otlp.js";const p=c.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces";async function T(e){const o=await e.req.json(),r=m(e),s={resourceSpans:o.resourceSpans.map(n=>{const u=g(n.resource.attributes.find(i=>i.key==="session_id"));return u?{...n,resource:{...n.resource,attributes:[...n.resource.attributes,...y(r,u)]},scopeSpans:n.scopeSpans.map(i=>({...i,spans:i.spans.map(a=>({...a,attributes:a.name.startsWith("event.")&&a.name!=="event.undefined"?A(a,r,u):a.attributes}))}))}:n})};return await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),e.newResponse(null,200,{})}function m(e){const o=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,r=v(e.req.raw)||e.req.raw.context.remoteAddr?.hostname,s=e.req.raw.headers.get("user-agent"),n=e.req.raw.headers.get("accept-language"),u=n?.split(",")[0];return{userId:o,clientIp:r,userAgent:s||void 0,acceptLanguage:n||void 0,locale:u}}function y(e,o){const r=[t("redocly.organization.id",c.ORGANIZATION_ID),t("redocly.organization.slug",c.ORGANIZATION_SLUG),t("redocly.project.id",c.PROJECT_ID),t("redocly.project.slug",c.PROJECT_SLUG),t("redocly.product.type",d.toLowerCase()),t("redocly.client.ip",e.clientIp),t("redocly.client.userAgent",e.userAgent),t("redocly.client.acceptLanguage",e.acceptLanguage),t("redocly.client.locale",e.locale)];return e.userId?r.push(t("redocly.user.id",e.userId)):r.push(t("redocly.anonymous.id",l(o))),r.filter(s=>s!==void 0)}function f(e,o,r){const s=b(e.userId,o),n=new Date(Math.floor(Number(r.startTimeUnixNano)/1e6)).toISOString(),u=r.attributes.find(_=>_.key==="cloudevents.event_data.uri"),i=u&&"stringValue"in u.value?[t("cloudevents.event_data.page.uri",u.value.stringValue)]:[];return[t("cloudevents.event_spec_version","1.0"),t("cloudevents.event_object","event"),t("cloudevents.event_origin","realm-ui"),t("cloudevents.event_source",s.uri),t("cloudevents.event_source_details.id",s.id),t("cloudevents.event_source_details.object",s.object),t("cloudevents.event_source_details.uri",s.uri),t("cloudevents.event_data_content_type","application/json; charset=utf-8"),t("cloudevents.event_organization_id",c.ORGANIZATION_ID),t("cloudevents.event_organization_slug",c.ORGANIZATION_SLUG),t("cloudevents.event_project_id",c.PROJECT_ID),t("cloudevents.event_project_slug",c.PROJECT_SLUG),t("cloudevents.event_product_type",d.toLowerCase()),t("cloudevents.event_session_id",o),t("cloudevents.event_time",n),t("cloudevents.event_client.ip",e.clientIp),t("cloudevents.event_client.user_agent",e.userAgent),t("cloudevents.event_client.accept_language",e.acceptLanguage),t("cloudevents.event_client.locale",e.locale),...i]}function A(e,o,r){return[...e.attributes.filter(n=>{const u="stringValue"in n.value&&n.value.stringValue==="",i=/cloudevents\.event_source_details\..+/.test(n.key);return!(u||i)}),...f(o,r,e)].filter(n=>n!==void 0)}function b(e,o){return e?{id:e,object:"user",uri:`${c.MAIN_API_URL}/users/${e}`}:{id:l(o),object:"anonymous",uri:`${c.MAIN_API_URL}/anonymous/${l(o)}`}}function l(e){return e.replace("ses_","ann_")}export{T as otelTracesHandler,A as toCloudEventAttributes,b as toSource};
@@ -1 +1 @@
1
- import{DEV_LOGIN_SLUG as U,ServerRoutes as $}from"../../../constants/common.js";import{CACHE_CONTROL_NO_CACHE_HEADER_VALUE as a,DEFAULT_TITLE as F}from"../../constants/common.js";import{findInIterable as O}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 j,isResourcePubliclyAccessible as B}from"../../utils/rbac.js";import{getServerProps as H}from"../../ssr/index.js";import{readSharedData as G}from"../../utils/index.js";import{getRedirectLoginUrl as M}from"../utils/get-redirect-login-url.js";import{processRedirects as V}from"./helpers/process-redirects.js";import{removeErrorDetails as k}from"../utils/remove-error-details.js";import{telemetry as K}from"../../telemetry/index.js";function ae(e,s){return async(t,p)=>{const l=t.get("logger"),{req:u}=t,{pathname:d}=new URL(u.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 g=d.match(/page-data(.*)data.json$/);if(!g)return p();const c=decodeURI(g[1]),n=c==="/index/"?"/":N(c),o=e.getRouteBySlug(n,{followRedirect:!1})||O(e.routesBySlug.values(),r=>r.hasClientRoutes&&c.startsWith(r.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:v,picture:A,email:I}}=t.get("auth"),R={isAuthenticated:C,email:I,teams:D},m={isAuthenticated:C,name:v,picture:A,email:I,teams:D},L=e.getRedirect(n);if(L){const r=V({redirect:L}).location;return K.sendRedirectMessage([{object:"redirect",from:n,templateId:"404"}]),t.json({templateId:"404",redirectTo:r,sharedDataIds:{},props:{}},301,{"Cache-Control":a})}if(!o){const r=e.getRouteBySlug(n,{followRedirect:!0});return l.error(`Page not found: ${d}`),t.json({templateId:"404",redirectTo:r?.slug,sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:m},404,{"Cache-Control":a})}if(l.verbose(`Page viewed: ${o.slug}`),!q(o,R,e.config.rbac,e.config.requiresLogin)&&o.slug!==U){if(C)return t.json({templateId:"403",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}},userData:m},403,{"Cache-Control":a});const r=Object.keys(h||{}).length>0;return t.json({templateId:"404",sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:m,...r?{redirectTo:M(e,o.slug)}:{}},r?401:404,{"Cache-Control":a})}const S=j(o.versions,R,e.config.rbac,e.config.requiresLogin),P=e.routesSharedData.get(o.slug)||{},T=await s(o),y=await H(o,t,T,e),{sharedDataIds:_,...E}=y,w={templateId:o.templateId,versions:S,sharedDataIds:{...P,..._||{}},props:b.isProductionEnv?k(E):E,slug:o.slug,userData:m,isPublic:B(o,e.config)};return t.json(w,200,{"Cache-Control":a})}}function se(e){return async(s,t)=>{const p=s.get("logger"),{req:l}=s,{pathname:u}=new URL(l.url),d=u.match(/\/page-data\/shared\/(.*)\.json/);if(!d)return t();const f=decodeURIComponent(d[1]),h=await G(f,e.outdir),{isAuthenticated:i,teams:g,claims:{email:c}}=s.get("auth"),n=j(h,{isAuthenticated:i,email:c,teams:g},e.config.rbac,e.config.requiresLogin);return n?s.json(n,200,{"Cache-Control":a}):(p.error(`Shared data not found: ${u}`),s.text("Not Found",404,{"Cache-Control":a}))}}export{ae as pageDataHandler,se as sharedPageDataHandler};
1
+ import{DEV_LOGIN_SLUG as U,ServerRoutes as $}from"../../../constants/common.js";import{CACHE_CONTROL_NO_CACHE_HEADER_VALUE as a,DEFAULT_TITLE as F}from"../../constants/common.js";import{findInIterable as O}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 j,isResourcePubliclyAccessible as B}from"../../utils/rbac.js";import{getServerProps as H}from"../../ssr/index.js";import{readSharedData as G}from"../../utils/index.js";import{getRedirectLoginUrl as M}from"../utils/get-redirect-login-url.js";import{processRedirects as V}from"./helpers/process-redirects.js";import{removeErrorDetails as k}from"../utils/remove-error-details.js";import{telemetry as K}from"../../telemetry/index.js";function ae(e,s){return async(t,p)=>{const l=t.get("logger"),{req:u}=t,{pathname:d}=new URL(u.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 g=d.match(/page-data(.*)data.json$/);if(!g)return p();const c=decodeURI(g[1]),n=c==="/index/"?"/":N(c),o=e.getRouteBySlug(n,{followRedirect:!1})||O(e.routesBySlug.values(),r=>r.hasClientRoutes&&c.startsWith(r.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:v,picture:A,email:I}}=t.get("auth"),R={isAuthenticated:C,email:I,teams:D},m={isAuthenticated:C,name:v,picture:A,email:I,teams:D},L=e.getRedirect(n);if(L){const r=V({redirect:L}).location;return K.sendRedirectMessage([{object:"redirect",from:n,templateId:"404"}]),t.json({templateId:"404",redirectTo:r,sharedDataIds:{},props:{}},301,{"Cache-Control":a})}if(!o){const r=e.getRouteBySlug(n,{followRedirect:!0});return l.error(`Page not found: ${d}`),t.json({templateId:"404",redirectTo:r?.slug,sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:m},404,{"Cache-Control":a})}if(l.verbose(`Page viewed: ${o.slug}`),!q(o,R,e.config.rbac,e.config.requiresLogin)&&o.slug!==U){if(C)return t.json({templateId:"403",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}},userData:m},403,{"Cache-Control":a});const r=Object.keys(h||{}).length>0;return t.json({templateId:"404",sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:m,...r?{redirectTo:M(e,o.slug)}:{}},r?401:404,{"Cache-Control":a})}const S=j(o.versions,R,e.config.rbac,e.config.requiresLogin),P=e.routesSharedData.get(o.slug)||{},T=await s(o),y=await H(o,t,T,e),{sharedDataIds:_,...E}=y,w={templateId:o.templateId,versions:S,sharedDataIds:{...P,..._||{}},props:b.isProductionEnv?k(E):E,slug:o.slug,userData:m,isPublic:B(o,e.config)};return t.json(w,200,{"Cache-Control":a})}}function se(e){return async(s,t)=>{const p=s.get("logger"),{req:l}=s,{pathname:u}=new URL(l.url),d=u.match(/\/page-data\/shared\/(.*)\.json/);if(!d)return t();const f=decodeURIComponent(d[1]),h=await G(f,e.outdir),{isAuthenticated:i,teams:g,claims:{email:c}}=s.get("auth"),n=j(h,{isAuthenticated:i,email:c,teams:g},e.config.rbac,e.config.requiresLogin);return n?s.json(n,200,{"Cache-Control":a}):(p.error(`Shared data not found: ${u}`),s.text("Not Found",404,{"Cache-Control":a}))}}export{ae as pageDataHandler,se as sharedPageDataHandler};
@@ -1 +1 @@
1
- import{getPathPrefix as i}from"@redocly/theme/core/utils";import{envConfig as a}from"../../../config/env-config.js";async function p(e,r){const t=new URL(e.req.url),n=i(),o=a.isProductionEnv?301:302;if(n&&t.pathname==="/")return e.newResponse(null,o,{Location:n});await r()}export{p as pathPrefixRedirectHandler};
1
+ import{getPathPrefix as i}from"@redocly/theme/core/utils";import{envConfig as a}from"../../config/env-config.js";async function p(e,r){const t=new URL(e.req.url),n=i(),o=a.isProductionEnv?301:302;if(n&&t.pathname==="/")return e.newResponse(null,o,{Location:n});await r()}export{p as pathPrefixRedirectHandler};