@redocly/realm 0.138.0-next.1 → 0.138.0-next.11

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 (296) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/dist/bin.js +0 -0
  3. package/dist/cli/build/analytics/collect-analytics.js +1 -1
  4. package/dist/cli/build/analytics/collectors/get-sidebars-usage.d.ts +12 -0
  5. package/dist/cli/build/analytics/collectors/get-sidebars-usage.js +1 -0
  6. package/dist/cli/build/index.js +1 -1
  7. package/dist/cli/develop.js +1 -1
  8. package/dist/cli/eject/resolveEjectParams.js +1 -1
  9. package/dist/cli/generate/string-utils.js +1 -1
  10. package/dist/cli/stats/collectors/extension-sampling.js +1 -1
  11. package/dist/cli/translations/collect-config-translations.js +1 -1
  12. package/dist/client/App.js +1 -1
  13. package/dist/client/TestProvider.d.ts +3 -1
  14. package/dist/client/TestProvider.js +1 -1
  15. package/dist/client/app/Link.js +1 -1
  16. package/dist/client/app/ReviewComments/ReviewComments.js +2 -2
  17. package/dist/client/app/Sidebar/Sidebar.js +1 -1
  18. package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
  19. package/dist/client/app/hooks/codeHighlight/treeview-transformer.js +1 -1
  20. package/dist/client/app/hooks/codeHighlight/useCodeHighlight.js +1 -1
  21. package/dist/client/app/hooks/index.d.ts +1 -0
  22. package/dist/client/app/hooks/index.js +1 -1
  23. package/dist/client/app/hooks/markdown/useMarkdownText.js +1 -1
  24. package/dist/client/app/hooks/useConsent.d.ts +11 -0
  25. package/dist/client/app/hooks/useConsent.js +1 -0
  26. package/dist/client/app/l10n/L10nContext.d.ts +10 -0
  27. package/dist/client/app/l10n/L10nContext.js +1 -0
  28. package/dist/client/app/l10n/hooks/useL10n.js +1 -1
  29. package/dist/client/app/l10n/hooks/useTranslate.js +1 -1
  30. package/dist/client/app/l10n/hooks/useTranslationKeys.d.ts +2 -0
  31. package/dist/client/app/l10n/hooks/useTranslationKeys.js +1 -1
  32. package/dist/client/app/l10n/ssrL10n.d.ts +4 -0
  33. package/dist/client/app/l10n/ssrL10n.js +1 -0
  34. package/dist/client/app/markdoc/custom-components/openapi/openapi-example.js +1 -1
  35. package/dist/client/app/markdoc/custom-components/openapi/openapi-response-sample.js +1 -1
  36. package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
  37. package/dist/client/app/markdoc/hooks/use-store.d.ts +2 -3
  38. package/dist/client/app/pages/DevLogin/DevLoginForm.js +1 -1
  39. package/dist/client/app/pages/Invite/Invite.js +1 -1
  40. package/dist/client/app/search/index.d.ts +1 -1
  41. package/dist/client/app/search/index.js +1 -1
  42. package/dist/client/app/search/useSearch.d.ts +3 -0
  43. package/dist/client/app/search/useSearch.js +1 -1
  44. package/dist/client/app/webmcp/index.d.ts +2 -0
  45. package/dist/client/app/webmcp/index.js +1 -0
  46. package/dist/client/app/webmcp/tools/api-tools.d.ts +8 -0
  47. package/dist/client/app/webmcp/tools/api-tools.js +1 -0
  48. package/dist/client/app/webmcp/tools/shared.d.ts +13 -0
  49. package/dist/client/app/webmcp/tools/shared.js +1 -0
  50. package/dist/client/app/webmcp/tools/site-tools.d.ts +5 -0
  51. package/dist/client/app/webmcp/tools/site-tools.js +3 -0
  52. package/dist/client/app/webmcp/types.d.ts +36 -0
  53. package/dist/client/app/webmcp/types.js +0 -0
  54. package/dist/client/app/webmcp/useWebMcpTools.d.ts +9 -0
  55. package/dist/client/app/webmcp/useWebMcpTools.js +1 -0
  56. package/dist/client/providers/page-data/hooks.d.ts +2 -0
  57. package/dist/client/providers/page-data/hooks.js +1 -1
  58. package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
  59. package/dist/client/runtime/loader.js +1 -1
  60. package/dist/client/server-entry.d.ts +2 -1
  61. package/dist/client/server-entry.js +1 -1
  62. package/dist/client/templates/api-docs/helpers.js +1 -1
  63. package/dist/client/templates/api-docs/template.js +7 -3
  64. package/dist/client/utils/catalog/parse-filter-query.js +1 -1
  65. package/dist/client/{app/Sidebar/helpers → utils}/filter-out-versioned-items.d.ts +12 -2
  66. package/dist/client/utils/filter-out-versioned-items.js +1 -0
  67. package/dist/client/utils/navigation-tabs.d.ts +14 -0
  68. package/dist/client/utils/navigation-tabs.js +1 -0
  69. package/dist/compiled/svgo/svgo-node.js +39 -39
  70. package/dist/constants/common.d.ts +1 -0
  71. package/dist/constants/common.js +1 -1
  72. package/dist/constants/l10n/langs/ar.js +1 -1
  73. package/dist/constants/l10n/langs/de.js +1 -1
  74. package/dist/constants/l10n/langs/en.js +1 -1
  75. package/dist/constants/l10n/langs/es.js +1 -1
  76. package/dist/constants/l10n/langs/fr.js +1 -1
  77. package/dist/constants/l10n/langs/hi.js +1 -1
  78. package/dist/constants/l10n/langs/it.js +1 -1
  79. package/dist/constants/l10n/langs/ja.js +1 -1
  80. package/dist/constants/l10n/langs/ko.js +1 -1
  81. package/dist/constants/l10n/langs/pl.js +1 -1
  82. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  83. package/dist/constants/l10n/langs/pt.js +1 -1
  84. package/dist/constants/l10n/langs/ru.js +1 -1
  85. package/dist/constants/l10n/langs/uk.js +1 -1
  86. package/dist/constants/l10n/langs/zh.js +1 -1
  87. package/dist/markdoc/nodes/table.d.ts +2 -0
  88. package/dist/markdoc/nodes/table.js +1 -1
  89. package/dist/server/config/env-config.d.ts +0 -6
  90. package/dist/server/config/env-schema.d.ts +0 -15
  91. package/dist/server/config/env-schemas/feature-flags.d.ts +0 -12
  92. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  93. package/dist/server/constants/common.d.ts +3 -1
  94. package/dist/server/constants/common.js +1 -1
  95. package/dist/server/constants/entitlements.js +1 -1
  96. package/dist/server/constants/plugins/consent.d.ts +3 -0
  97. package/dist/server/constants/plugins/consent.js +1 -0
  98. package/dist/server/constants/plugins/search.js +1 -1
  99. package/dist/server/esbuild/esbuild-logger.js +3 -3
  100. package/dist/server/plugins/analytics/adobe/index.js +1 -1
  101. package/dist/server/plugins/analytics/amplitude/browser-hooks.js +1 -1
  102. package/dist/server/plugins/analytics/amplitude/index.js +1 -1
  103. package/dist/server/plugins/analytics/fullstory/index.js +1 -1
  104. package/dist/server/plugins/analytics/ga/index.js +1 -1
  105. package/dist/server/plugins/analytics/gtm/browser-hooks.js +1 -1
  106. package/dist/server/plugins/analytics/gtm/index.js +1 -1
  107. package/dist/server/plugins/analytics/heap/browser-hooks.js +1 -1
  108. package/dist/server/plugins/analytics/rudderstack/index.js +1 -1
  109. package/dist/server/plugins/analytics/segment/index.js +1 -1
  110. package/dist/server/plugins/api-docs/index.js +1 -1
  111. package/dist/server/plugins/api-docs/utils/apply-nav-item-to-root.d.ts +9 -0
  112. package/dist/server/plugins/api-docs/utils/apply-nav-item-to-root.js +1 -0
  113. package/dist/server/plugins/api-docs/utils/decorators.js +1 -1
  114. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +1 -1
  115. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -1
  116. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.d.ts +5 -1
  117. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +7 -1
  118. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -1
  119. package/dist/server/plugins/catalog-entities/utils/ajv-validator.js +1 -1
  120. package/dist/server/plugins/catalog-entities/utils/extract-parts-from-components-ref.js +1 -1
  121. package/dist/server/plugins/catalog-entities/utils/is-valid-tag-name.js +1 -1
  122. package/dist/server/plugins/catalog-entities/utils/openapi-component-content-extractor.js +1 -1
  123. package/dist/server/plugins/config-parser/format-custom-tags.d.ts +1 -0
  124. package/dist/server/plugins/config-parser/format-custom-tags.js +1 -1
  125. package/dist/server/plugins/config-parser/index.js +1 -1
  126. package/dist/server/plugins/config-parser/loaders/redocly-config-loader.js +1 -1
  127. package/dist/server/plugins/config-parser/loaders/versions-config-loader.js +1 -1
  128. package/dist/server/plugins/config-parser/safe-parse.js +1 -1
  129. package/dist/server/plugins/consent/build-consent-script.d.ts +6 -0
  130. package/dist/server/plugins/consent/build-consent-script.js +230 -0
  131. package/dist/server/plugins/consent/gate-ssr-components.d.ts +5 -0
  132. package/dist/server/plugins/consent/gate-ssr-components.js +1 -0
  133. package/dist/server/plugins/consent/index.d.ts +3 -0
  134. package/dist/server/plugins/consent/index.js +1 -0
  135. package/dist/server/plugins/consent/is-consent-enabled.d.ts +8 -0
  136. package/dist/server/plugins/consent/is-consent-enabled.js +1 -0
  137. package/dist/server/plugins/consent/zone-modes.d.ts +8 -0
  138. package/dist/server/plugins/consent/zone-modes.js +1 -0
  139. package/dist/server/plugins/default-theme/extract-team-names.js +1 -1
  140. package/dist/server/plugins/dev-onboarding/template/App.js +5 -5
  141. package/dist/server/plugins/dev-onboarding/template/components/ApiKeyOverview.js +3 -3
  142. package/dist/server/plugins/get-reserved-routes.d.ts +4 -2
  143. package/dist/server/plugins/get-reserved-routes.js +1 -1
  144. package/dist/server/plugins/l10n/index.js +1 -1
  145. package/dist/server/plugins/lifecycle.js +2 -2
  146. package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +2 -0
  147. package/dist/server/plugins/markdown/search/get-ai-search-documents.js +9 -9
  148. package/dist/server/plugins/markdown/search/nodes/tag-node.d.ts +1 -1
  149. package/dist/server/plugins/markdown/search/nodes/tag-node.js +1 -1
  150. package/dist/server/plugins/markdown/search/to-markdown.js +1 -1
  151. package/dist/server/plugins/markdown/utils/sanitize-malformed-md-content.js +1 -1
  152. package/dist/server/plugins/mcp/audit/audit-log.js +1 -1
  153. package/dist/server/plugins/mcp/audit/secret-patterns.js +1 -1
  154. package/dist/server/plugins/mcp/auth/assistant-anonymous-token.d.ts +9 -0
  155. package/dist/server/plugins/mcp/auth/assistant-anonymous-token.js +1 -0
  156. package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +5 -3
  157. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  158. package/dist/server/plugins/mcp/codemode/build-tool-list.d.ts +6 -1
  159. package/dist/server/plugins/mcp/codemode/build-tool-list.js +2 -2
  160. package/dist/server/plugins/mcp/codemode/build-tool-type-declarations.js +4 -4
  161. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +3 -3
  162. package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +0 -1
  163. package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +1 -2
  164. package/dist/server/plugins/mcp/codemode/capabilities/utils.js +4 -4
  165. package/dist/server/plugins/mcp/codemode/code-execution-audit.d.ts +3 -2
  166. package/dist/server/plugins/mcp/codemode/code-execution-audit.js +1 -1
  167. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +3 -4
  168. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -1
  169. package/dist/server/plugins/mcp/codemode/prompts.js +1 -1
  170. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +2 -2
  171. package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +0 -2
  172. package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
  173. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  174. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  175. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -1
  176. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  177. package/dist/server/plugins/mcp/docs-mcp/tools/core/create-anonymous-session.js +1 -1
  178. package/dist/server/plugins/mcp/docs-mcp/tools/core/whoami.js +1 -1
  179. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.d.ts +2 -0
  180. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.js +1 -1
  181. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.d.ts +6 -0
  182. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.js +1 -1
  183. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoint-info.js +1 -1
  184. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-security-schemes.js +1 -1
  185. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.d.ts +2 -0
  186. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.js +1 -1
  187. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.d.ts +6 -2
  188. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
  189. package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.d.ts +20 -14
  190. package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.js +1 -1
  191. package/dist/server/plugins/mcp/gateway-mcp/credential-validation.js +1 -1
  192. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +16 -10
  193. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -5
  194. package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.js +1 -1
  195. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
  196. package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.js +1 -1
  197. package/dist/server/plugins/mcp/gateway-mcp/fetch/url-placeholders.js +1 -1
  198. package/dist/server/plugins/mcp/gateway-mcp/rate-limit/ip-key.js +1 -1
  199. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.d.ts +0 -6
  200. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +2 -2
  201. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  202. package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -1
  203. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +35 -35
  204. package/dist/server/plugins/mcp/index.js +1 -1
  205. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  206. package/dist/server/plugins/mcp/servers/mcp-server.js +2 -4
  207. package/dist/server/plugins/mcp/types.d.ts +5 -11
  208. package/dist/server/plugins/mcp/utils/disabled-tools.d.ts +3 -0
  209. package/dist/server/plugins/mcp/utils/disabled-tools.js +1 -0
  210. package/dist/server/plugins/mcp/utils/json-schema-validator.d.ts +2 -2
  211. package/dist/server/plugins/mcp/utils/json-schema-validator.js +1 -1
  212. package/dist/server/plugins/mcp/utils/mcp-client.js +1 -1
  213. package/dist/server/plugins/mcp/utils/public-endpoint.d.ts +9 -0
  214. package/dist/server/plugins/mcp/utils/public-endpoint.js +1 -0
  215. package/dist/server/plugins/mcp/utils/telemetry-attributes.d.ts +2 -1
  216. package/dist/server/plugins/mcp/utils/telemetry-attributes.js +1 -1
  217. package/dist/server/plugins/mcp/utils/tool-registration.d.ts +2 -1
  218. package/dist/server/plugins/mcp/utils/tool-registration.js +1 -1
  219. package/dist/server/plugins/mcp/utils/xmcp-utils.d.ts +0 -7
  220. package/dist/server/plugins/mcp/utils/xmcp-utils.js +1 -1
  221. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  222. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +5 -7
  223. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  224. package/dist/server/plugins/nav-utils.js +1 -1
  225. package/dist/server/plugins/scorecard-classic/index.js +1 -1
  226. package/dist/server/plugins/scorecard-classic/template/Grid/GridHeader.js +21 -8
  227. package/dist/server/plugins/scorecard-classic/template/ScorecardDashboard.js +3 -3
  228. package/dist/server/plugins/scorecard-classic/template/index.styles.d.ts +1 -0
  229. package/dist/server/plugins/scorecard-classic/template/index.styles.js +15 -5
  230. package/dist/server/plugins/scorecard-classic/template/useData.js +1 -1
  231. package/dist/server/plugins/scorecard-classic/template/views.js +1 -1
  232. package/dist/server/plugins/search/engines/flexsearch/index.js +2 -1
  233. package/dist/server/plugins/search/engines/flexsearch/search-index.d.ts +2 -2
  234. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  235. package/dist/server/plugins/search/llmstxt/index.js +1 -1
  236. package/dist/server/plugins/sidebars/index.js +7 -3
  237. package/dist/server/plugins/sidebars/tabs.d.ts +19 -0
  238. package/dist/server/plugins/sidebars/tabs.js +1 -0
  239. package/dist/server/plugins/sso/index.js +1 -1
  240. package/dist/server/ssr/render.js +1 -1
  241. package/dist/server/store.d.ts +2 -0
  242. package/dist/server/store.js +1 -1
  243. package/dist/server/tools/notifiers/helpers/privacy/mask-subject.js +1 -1
  244. package/dist/server/tools/notifiers/helpers/privacy/remove-pii.js +1 -1
  245. package/dist/server/types/plugins/search.d.ts +7 -5
  246. package/dist/server/utils/catalog-classic/get-catalog-shared-data-id.d.ts +3 -0
  247. package/dist/server/utils/catalog-classic/get-catalog-shared-data-id.js +1 -0
  248. package/dist/server/utils/envs/interpolate-env-variables.js +1 -1
  249. package/dist/server/utils/rbac-expand.js +1 -1
  250. package/dist/server/utils/rbac.js +1 -1
  251. package/dist/server/utils/redact-url.d.ts +6 -0
  252. package/dist/server/utils/redact-url.js +1 -0
  253. package/dist/server/utils/report-all-errors.js +1 -1
  254. package/dist/server/utils/sandbox-context.js +1 -1
  255. package/dist/server/utils/search/highlight-text-for-search.d.ts +1 -0
  256. package/dist/server/utils/search/highlight-text-for-search.js +1 -1
  257. package/dist/server/utils/search/text-match.d.ts +6 -0
  258. package/dist/server/utils/search/text-match.js +1 -0
  259. package/dist/server/utils/static-data.js +1 -1
  260. package/dist/server/utils/write-problems-report.d.ts +3 -0
  261. package/dist/server/utils/write-problems-report.js +1 -0
  262. package/dist/server/web-server/auth.d.ts +16 -2
  263. package/dist/server/web-server/auth.js +4 -4
  264. package/dist/server/web-server/jwt/jwt.js +1 -1
  265. package/dist/server/web-server/jwt/token-types.d.ts +11 -0
  266. package/dist/server/web-server/jwt/token-types.js +1 -0
  267. package/dist/server/web-server/jwt/types.d.ts +4 -4
  268. package/dist/server/web-server/jwt/types.js +1 -1
  269. package/dist/server/web-server/middleware/ensureSearchData.js +1 -1
  270. package/dist/server/web-server/middleware/responseHeadersMiddleware.js +1 -1
  271. package/dist/server/web-server/middleware/telemetry-middleware.js +1 -1
  272. package/dist/server/web-server/routes/ask-ai.js +1 -1
  273. package/dist/server/web-server/routes/auth.d.ts +1 -1
  274. package/dist/server/web-server/routes/auth.js +1 -1
  275. package/dist/server/web-server/routes/cors-proxy.js +2 -2
  276. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  277. package/dist/server/web-server/routes/index.js +1 -1
  278. package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
  279. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  280. package/dist/server/web-server/routes/semantic-search.d.ts +1 -1
  281. package/dist/server/web-server/routes/semantic-search.js +1 -1
  282. package/dist/server/web-server/routes/static-content.js +1 -1
  283. package/dist/server/workers/worker-pool.js +1 -1
  284. package/dist/types/entitlements.d.ts +1 -0
  285. package/dist/utils/path/parse-path-versions.js +1 -1
  286. package/dist/utils/string/to-kebab-case.js +1 -1
  287. package/package.json +9 -9
  288. package/dist/client/app/Sidebar/helpers/filter-out-versioned-items.js +0 -1
  289. package/dist/server/plugins/mcp/auth/token-audience-telemetry.d.ts +0 -7
  290. package/dist/server/plugins/mcp/auth/token-audience-telemetry.js +0 -1
  291. package/dist/server/plugins/mcp/auth/token-audience.d.ts +0 -6
  292. package/dist/server/plugins/mcp/auth/token-audience.js +0 -1
  293. /package/dist/server/{plugins/mcp/gateway-mcp/fetch → web-server/utils}/ssrf-blocklist.d.ts +0 -0
  294. /package/dist/server/{plugins/mcp/gateway-mcp/fetch → web-server/utils}/ssrf-blocklist.js +0 -0
  295. /package/dist/server/{plugins/mcp/gateway-mcp/fetch → web-server/utils}/ssrf-safe-lookup.d.ts +0 -0
  296. /package/dist/server/{plugins/mcp/gateway-mcp/fetch → web-server/utils}/ssrf-safe-lookup.js +0 -0
@@ -1 +1 @@
1
- import{writeFileSync as D}from"node:fs";import L from"path";import{SCORECARD_OUTPUT_FILE_NAME as w}from"../../constants/common.js";import{mapObject as E}from"../../../utils/object/map-object.js";import{envConfig as A}from"../../config/env-config.js";import{removeLeadingSlash as j}from"../../../utils/url/remove-leading-slash.js";import{combineUrls as O}from"@redocly/theme/core/utils";import{logger as _}from"../../tools/notifiers/logger.js";import{getRouteSlugToCatalogSlugMap as F}from"../../utils/catalog-classic/get-route-slug-to-catalog-slug-map.js";import{deepEqual as I}from"../../../utils/object/deep-equal.js";import{ensureDir as N}from"../../utils/index.js";import{getTemplatePath as q}from"./get-template-path.js";import{getAllRuleNames as U}from"./lint.js";import{getScorecardConfig as T}from"./get-scorecard-config.js";import{getScorecardSlug as k}from"./shared-utils.js";import{scorecardConfigLoader as M}from"./loaders/scorecard-config.js";import{scorecardLoader as W}from"./loaders/scorecard.js";import{computeScorecard as B}from"./compute-scorecard.js";import{telemetryTraceStep as J}from"../../../cli/telemetry/helpers/trace-step.js";const $="scorecardClassic";let u={},R={};async function ne({id:b,requiredEntitlements:P,loadersPrefix:v=""}){let p=null,y=null,h=!1;return{id:b??"scorecardClassic",requiredEntitlements:P??["scorecard"],loaders:{[`${v}scorecard-config`]:M,[`${v}scorecard`]:W},async processContent(r,l){await J("com.redocly.build.plugin.scorecardClassic",async S=>{const a=r.createTemplate($,q("./template/index.js")),g=await l.getConfig(),m=T(g),f=g?.reunite??{},i=[()=>p===null,()=>!I(u,m),()=>!I(R,f)].some(e=>e());u=m,S?.setAttribute("config",JSON.stringify(u||{})),R=f;const n=g.catalogClassic??{},c=u.levels||[];if(c.length<1)throw Error("Invalid configuration of levels config");i&&(p=await B({actions:r,context:l,scorecardConfig:u,reuniteConfig:R}));const{data:{configs:o}}=await l.cache.load("",`${v}scorecard-config`),{perLevel:d,all:s}=U(o);y={levelNames:c.map(e=>e.name),rules:s,rulesPerLevel:d};for(const[e,t]of Object.entries(n)){const C=O(t.slug,"scorecard/");r.addRoute({duplicateInAllLocales:!0,slug:C,fsPath:O(t.slug,"scorecard/"),templateId:a,hasClientRoutes:!0,excludeFromSidebar:!0,serverPropsGetterIds:[],sharedData:[{id:"scorecard",key:"scorecard"},{key:"catalog",id:"catalog-"+e}],getNavText:()=>Promise.resolve(t.title||"API design scorecard"),getStaticData:async()=>({props:{catalogId:e,catalogConfig:{...t,items:void 0},scorecardConfig:u,scorecardInfo:y}})})}})},afterRoutesCreated:async(r,l)=>{const S=await l.getConfig(),a=S.catalogClassic??{},g=T(S);if(Object.keys(a).length){const i=Object.keys(a).length>1?await F(r,l,a):null,n={};for(const[c,o]of Object.entries(p||{})){const d=r.getRouteByFsPath(c),s=d?.slug;if(s){if(d&&!g.ignoreMetadata){const e=i?i.get(s)??Object.values(a)[0].slug:Object.values(a)[0].slug,t=O(e,"scorecard/");d.metadata={...d.metadata,scorecardStatus:o.status,scorecardLevel:o.scorecardLevel,scorecardLevelIdx:o.scorecardLevelIdx,scorecardLevels:E(o.levels,C=>({uniqueErrors:C.uniqueErrors,uniqueWarnings:C.uniqueWarnings})),scoreCardSlug:t+"apis/"+encodeURIComponent(j(s))}}if(n[s]={...o,levels:E(o.levels,e=>({...e,problems:e.problems.map(t=>({ruleId:t.ruleId,severity:t.severity}))}))},!h){const e=L.resolve(r.outdir,"_scorecard",k(s));D(N(e),JSON.stringify(o))}}}await r.createSharedData("scorecard",n)}const m={};for(const[i,n]of Object.entries(p||{})){const c=r.getRouteByFsPath(i)?.slug;c&&(m[c]=n)}const f=A.REDOCLY_METADATA_OUTPUT_FOLDER;!h&&f&&(_.info("Writing scorecard data..."),D(L.join(f,w),JSON.stringify({scorecardData:m,...y}))),h=!0}}}export{ne as scorecardClassicPlugin};
1
+ import{writeFileSync as R}from"node:fs";import I from"path";import{SCORECARD_OUTPUT_FILE_NAME as w}from"../../constants/common.js";import{mapObject as L}from"../../../utils/object/map-object.js";import{envConfig as A}from"../../config/env-config.js";import{removeLeadingSlash as j}from"../../../utils/url/remove-leading-slash.js";import{combineUrls as O}from"@redocly/theme/core/utils";import{logger as _}from"../../tools/notifiers/logger.js";import{getRouteSlugToCatalogSlugMap as F}from"../../utils/catalog-classic/get-route-slug-to-catalog-slug-map.js";import{getCatalogSharedDataId as N}from"../../utils/catalog-classic/get-catalog-shared-data-id.js";import{deepEqual as E}from"../../../utils/object/deep-equal.js";import{ensureDir as q}from"../../utils/index.js";import{getTemplatePath as U}from"./get-template-path.js";import{getAllRuleNames as k}from"./lint.js";import{getScorecardConfig as T}from"./get-scorecard-config.js";import{getScorecardSlug as M}from"./shared-utils.js";import{scorecardConfigLoader as W}from"./loaders/scorecard-config.js";import{scorecardLoader as B}from"./loaders/scorecard.js";import{computeScorecard as J}from"./compute-scorecard.js";import{telemetryTraceStep as $}from"../../../cli/telemetry/helpers/trace-step.js";const x="scorecardClassic";let u={},D={};async function ue({id:b,requiredEntitlements:P,loadersPrefix:v=""}){let p=null,y=null,h=!1;return{id:b??"scorecardClassic",requiredEntitlements:P??["scorecard"],loaders:{[`${v}scorecard-config`]:W,[`${v}scorecard`]:B},async processContent(r,l){await $("com.redocly.build.plugin.scorecardClassic",async S=>{const a=r.createTemplate(x,U("./template/index.js")),g=await l.getConfig(),m=T(g),f=g?.reunite??{},i=[()=>p===null,()=>!E(u,m),()=>!E(D,f)].some(e=>e());u=m,S?.setAttribute("config",JSON.stringify(u||{})),D=f;const n=g.catalogClassic??{},c=u.levels||[];if(c.length<1)throw Error("Invalid configuration of levels config");i&&(p=await J({actions:r,context:l,scorecardConfig:u,reuniteConfig:D}));const{data:{configs:t}}=await l.cache.load("",`${v}scorecard-config`),{perLevel:d,all:s}=k(t);y={levelNames:c.map(e=>e.name),rules:s,rulesPerLevel:d};for(const[e,o]of Object.entries(n)){const C=O(o.slug,"scorecard/");r.addRoute({duplicateInAllLocales:!0,slug:C,fsPath:O(o.slug,"scorecard/"),templateId:a,hasClientRoutes:!0,excludeFromSidebar:!0,serverPropsGetterIds:[],sharedData:[{id:"scorecard",key:"scorecard"},{key:"catalog",id:N(e)}],getNavText:()=>Promise.resolve(o.title||"API design scorecard"),getStaticData:async()=>({props:{catalogId:e,catalogConfig:{...o,items:void 0},scorecardConfig:u,scorecardInfo:y}})})}})},afterRoutesCreated:async(r,l)=>{const S=await l.getConfig(),a=S.catalogClassic??{},g=T(S);if(Object.keys(a).length){const i=Object.keys(a).length>1?await F(r,l,a):null,n={};for(const[c,t]of Object.entries(p||{})){const d=r.getRouteByFsPath(c),s=d?.slug;if(s){if(d&&!g.ignoreMetadata){const e=i?i.get(s)??Object.values(a)[0].slug:Object.values(a)[0].slug,o=O(e,"scorecard/");d.metadata={...d.metadata,scorecardStatus:t.status,scorecardLevel:t.scorecardLevel,scorecardLevelIdx:t.scorecardLevelIdx,scorecardLevels:L(t.levels,C=>({uniqueErrors:C.uniqueErrors,uniqueWarnings:C.uniqueWarnings})),scoreCardSlug:o+"apis/"+encodeURIComponent(j(s))}}if(n[s]={...t,levels:L(t.levels,e=>({...e,problems:e.problems.map(o=>({ruleId:o.ruleId,severity:o.severity}))}))},!h){const e=I.resolve(r.outdir,"_scorecard",M(s));R(q(e),JSON.stringify(t))}}}await r.createSharedData("scorecard",n)}const m={};for(const[i,n]of Object.entries(p||{})){const c=r.getRouteByFsPath(i)?.slug;c&&(m[c]=n)}const f=A.REDOCLY_METADATA_OUTPUT_FOLDER;!h&&f&&(_.info("Writing scorecard data..."),R(I.join(f,w),JSON.stringify({scorecardData:m,...y}))),h=!0}}}export{ue as scorecardClassicPlugin};
@@ -1,12 +1,12 @@
1
- import o from"react";import l from"styled-components";import{flexRender as a}from"@tanstack/react-table";const C=({headerGroups:e,gridTemplateColumns:t,groupHeaderTitle:n})=>o.createElement(s,null,n&&o.createElement(g,{gridTemplateColumns:t,role:"row"},o.createElement(d,{gridColumn:"1",role:"cell"}),o.createElement(d,{gridColumn:"2 / -1",role:"cell"},o.createElement("span",null,n))),e.map((i,c)=>o.createElement(p,{key:`header-group-${c}`,gridTemplateColumns:t,role:"row"},i.headers.map((r,m)=>o.createElement(u,{key:r.id,gridColumn:m+1,onClick:r.column.getToggleSortingHandler(),role:"cell"},a(r.column.columnDef.header,r.getContext()),r.column.getCanSort()?o.createElement(x,null,r.column.getIsSorted()?r.column.getIsSorted()==="desc"?"\u25BE":"\u25B4":"\u21D5"):null))))),s=l.div`
1
+ import r from"react";import t from"styled-components";import{flexRender as g}from"@tanstack/react-table";const w=({headerGroups:e,gridTemplateColumns:i,groupHeaderTitle:l})=>r.createElement(p,null,l&&r.createElement(u,{gridTemplateColumns:i,role:"row"},r.createElement(c,{gridColumn:"1",role:"cell"}),r.createElement(c,{gridColumn:"2 / -1",role:"cell"},r.createElement("span",null,l))),e.map((a,m)=>r.createElement(b,{key:`header-group-${m}`,gridTemplateColumns:i,role:"row"},a.headers.map((o,s)=>{const d=g(o.column.columnDef.header,o.getContext()),n=o.column.getIsSorted();return r.createElement(x,{key:o.id,gridColumn:s+1,$sortable:o.column.getCanSort(),role:"columnheader","aria-sort":n==="asc"?"ascending":n==="desc"?"descending":void 0},o.column.getCanSort()?r.createElement(f,{type:"button",onClick:o.column.getToggleSortingHandler()},d,r.createElement(h,{"aria-hidden":"true"},n?n==="desc"?"\u25BE":"\u25B4":"\u21D5")):d)})))),p=t.div`
2
2
  border: 1px solid var(--border-color-primary);
3
3
  min-width: 775px;
4
- `,g=l.div`
4
+ `,u=t.div`
5
5
  display: grid;
6
6
  grid-template-columns: ${e=>e.gridTemplateColumns};
7
7
  width: 100%;
8
8
  min-width: 775px;
9
- `,d=l.div`
9
+ `,c=t.div`
10
10
  padding: 5px 15px;
11
11
  background-color: var(--bg-color-raised);
12
12
  font-weight: bold;
@@ -21,12 +21,12 @@ import o from"react";import l from"styled-components";import{flexRender as a}fro
21
21
  &:nth-child(2) {
22
22
  border-bottom: 1px solid var(--border-color-primary);
23
23
  }
24
- `,p=l.div`
24
+ `,b=t.div`
25
25
  display: grid;
26
26
  grid-template-columns: ${e=>e.gridTemplateColumns};
27
27
  width: 100%;
28
- `,u=l.div`
29
- padding: 5px 15px;
28
+ `,x=t.div`
29
+ padding: ${({$sortable:e})=>e?"0":"5px 15px"};
30
30
  background-color: var(--bg-color-raised);
31
31
  font-weight: bold;
32
32
  color: var(--text-color-secondary);
@@ -37,6 +37,19 @@ import o from"react";import l from"styled-components";import{flexRender as a}fro
37
37
  &:first-child {
38
38
  justify-content: flex-start;
39
39
  }
40
- `,x=l.span`
40
+ `,f=t.button`
41
+ display: block;
42
+ width: 100%;
43
+ height: 100%;
44
+ box-sizing: border-box;
45
+ margin: 0;
46
+ padding: 5px 15px;
47
+ border: 0;
48
+ background: none;
49
+ font: inherit;
50
+ color: inherit;
51
+ text-align: inherit;
52
+ cursor: pointer;
53
+ `,h=t.span`
41
54
  font-family: monospace;
42
- `;export{C as GridHeader};
55
+ `;export{w as GridHeader};
@@ -1,8 +1,8 @@
1
- import*as e from"react";import{useState as k}from"react";import N from"styled-components";import{HighlightContext as x}from"@redocly/portal-legacy-ui";import{breakpoints as O,getScorecardColorVariable as B}from"@redocly/theme/core/utils";import{FilterContent as D}from"@redocly/theme/components/Filter/FilterContent";import{FilterPopover as I}from"@redocly/theme/components/Filter/FilterPopover";import{CatalogPageWrapper as L,CatalogPageContent as M,CatalogTitle as R,CatalogDescription as W,CatalogPageDescriptionWrapper as j}from"@redocly/theme/components/CatalogClassic/CatalogClassic";import{useModalScrollLock as $}from"@redocly/theme/core/hooks";import{CatalogClassicActions as H}from"@redocly/theme/components/CatalogClassic/CatalogClassicActions";import{Sidebar as _}from"@redocly/theme/components/Sidebar/Sidebar";import{CardValue as p,CardsWrapper as q,ModeSwitcherTab as z,ModeSwitcherTabs as G,CardRow as J,ProblemsByStatusCardBody as K,ScoreCardStatusCardBody as Q,TableWrap as d,ContentWithDotWrap as U,ScorecardCard as h,ScorecardCardTitle as S}from"./index.styles";import{NON_CONFORMANT as T}from"./utils";import{ApiLevel as X,StatusDistribution as Y}from"./components";import{ApiListView as Z,TeamsView as ee,RulesView as te}from"./views";import{useData as re}from"./useData";function he(y){const{apis:v,summary:r,problemsByRule:A,nonConformantByTeam:P,sortedStatsByTeam:m,filterTerm:a,setFilterTerm:u,filters:l,scorecardInfo:f,hasTeam:i,hasPublishedAt:V,catalogConfig:E,teamLabel:n,teamProperty:w}=re(y),b={apis:"APIs",rules:"Rules",...i&&{teams:n}},[C,g]=e.useState(!1),[o,s]=k("apis");return $(C),e.createElement(x.Provider,{value:[a]},e.createElement(L,null,e.createElement(ae,{menu:e.createElement(D,{setFilterTerm:u,filters:l,filterTerm:a,filterValuesCasing:E.filterValuesCasing})}),C&&e.createElement(I,{onClose:()=>g(!1),setFilterTerm:u,filterTerm:a,filters:l,filterValuesCasing:E.filterValuesCasing}),e.createElement(H,{onOpenFilter:()=>g(!0),filters:l,filterTerm:a}),e.createElement(M,{id:"scorecard-page-content"},e.createElement(j,null,e.createElement(R,null,"API design scorecard"),e.createElement(W,null,"See the health of your API designs.")),e.createElement(q,null,e.createElement(h,null,e.createElement(S,null,"Scorecard status"),e.createElement(Q,null,e.createElement("div",null,e.createElement(p,null,r.total),e.createElement("br",null),"APIs"),e.createElement("div",null,Object.entries(r.levels).map(([t,c],F)=>e.createElement(U,{key:t},e.createElement(p,{style:{width:"40px",textAlign:"right"}},c),e.createElement(X,{level:t,colorVariable:B(F,Object.values(r.levels).length)}))))),e.createElement(Y,{summary:r})),i&&e.createElement(h,null,e.createElement(S,null,`${T} APIs by ${n}`),e.createElement(K,null,P.slice(0,4).map((t,c)=>e.createElement(J,{key:c},e.createElement("span",{style:{flex:1,textAlign:"left"}},t.team),e.createElement(p,null,t.levels[T].apis))),m.length>4&&e.createElement("a",{href:"#",onClick:()=>s("teams")},"See all (",m.length,")")))),e.createElement(G,{"data-component-name":"Scorecard/ModeSwitcherTabs"},Object.keys(b).map(t=>t&&e.createElement(z,{"data-component-name":"Scorecard/ModeSwitcherTab",key:t,isActive:o===t,onClick:()=>s(t)},b[t]))),e.createElement(d,{isActive:o==="apis"},e.createElement(Z,{data:v,levelNames:f.levelNames,hasTeam:i,hasPublishedAt:V,teamLabel:n})),e.createElement(d,{isActive:o==="rules"},e.createElement(te,{data:A})),i&&e.createElement(d,{isActive:o==="teams"},e.createElement(ee,{data:m,levelNames:f.levelNames,filters:l,setActiveTab:s,teamLabel:n,teamProperty:w})))))}const ae=N(_)`
1
+ import*as e from"react";import{useState as F}from"react";import N from"styled-components";import{HighlightContext as x}from"@redocly/portal-legacy-ui";import{breakpoints as B,getScorecardColorVariable as L}from"@redocly/theme/core/utils";import{FilterContent as O}from"@redocly/theme/components/Filter/FilterContent";import{FilterPopover as D}from"@redocly/theme/components/Filter/FilterPopover";import{CatalogPageWrapper as I,CatalogPageContent as M,CatalogTitle as R,CatalogDescription as W,CatalogPageDescriptionWrapper as j}from"@redocly/theme/components/CatalogClassic/CatalogClassic";import{useModalScrollLock as $}from"@redocly/theme/core/hooks";import{CatalogClassicActions as H}from"@redocly/theme/components/CatalogClassic/CatalogClassicActions";import{Sidebar as _}from"@redocly/theme/components/Sidebar/Sidebar";import{CardValue as p,CardsWrapper as q,ModeSwitcherTab as z,ModeSwitcherTabs as G,CardRow as J,ProblemsByStatusCardBody as K,ScoreCardStatusCardBody as Q,TableWrap as d,ContentWithDotWrap as U,ScorecardCard as h,ScorecardCardTitle as S,LinkButton as X}from"./index.styles";import{NON_CONFORMANT as T}from"./utils";import{ApiLevel as Y,StatusDistribution as Z}from"./components";import{ApiListView as ee,TeamsView as te,RulesView as re}from"./views";import{useData as ae}from"./useData";function Se(y){const{apis:v,summary:r,problemsByRule:A,nonConformantByTeam:P,sortedStatsByTeam:m,filterTerm:a,setFilterTerm:u,filters:l,scorecardInfo:f,hasTeam:i,hasPublishedAt:V,catalogConfig:E,teamLabel:n,teamProperty:w}=ae(y),b={apis:"APIs",rules:"Rules",...i&&{teams:n}},[C,g]=e.useState(!1),[o,s]=F("apis");return $(C),e.createElement(x.Provider,{value:[a]},e.createElement(I,null,e.createElement(le,{menu:e.createElement(O,{setFilterTerm:u,filters:l,filterTerm:a,filterValuesCasing:E.filterValuesCasing})}),C&&e.createElement(D,{onClose:()=>g(!1),setFilterTerm:u,filterTerm:a,filters:l,filterValuesCasing:E.filterValuesCasing}),e.createElement(H,{onOpenFilter:()=>g(!0),filters:l,filterTerm:a}),e.createElement(M,{id:"scorecard-page-content"},e.createElement(j,null,e.createElement(R,null,"API design scorecard"),e.createElement(W,null,"See the health of your API designs.")),e.createElement(q,null,e.createElement(h,null,e.createElement(S,null,"Scorecard status"),e.createElement(Q,null,e.createElement("div",null,e.createElement(p,null,r.total),e.createElement("br",null),"APIs"),e.createElement("div",null,Object.entries(r.levels).map(([t,c],k)=>e.createElement(U,{key:t},e.createElement(p,{style:{width:"40px",textAlign:"right"}},c),e.createElement(Y,{level:t,colorVariable:L(k,Object.values(r.levels).length)}))))),e.createElement(Z,{summary:r})),i&&e.createElement(h,null,e.createElement(S,null,`${T} APIs by ${n}`),e.createElement(K,null,P.slice(0,4).map((t,c)=>e.createElement(J,{key:c},e.createElement("span",{style:{flex:1,textAlign:"left"}},t.team),e.createElement(p,null,t.levels[T].apis))),m.length>4&&e.createElement(X,{onClick:()=>s("teams")},"See all (",m.length,")")))),e.createElement(G,{"data-component-name":"Scorecard/ModeSwitcherTabs"},Object.keys(b).map(t=>t&&e.createElement(z,{"data-component-name":"Scorecard/ModeSwitcherTab",key:t,isActive:o===t,onClick:()=>s(t)},b[t]))),e.createElement(d,{isActive:o==="apis"},e.createElement(ee,{data:v,levelNames:f.levelNames,hasTeam:i,hasPublishedAt:V,teamLabel:n})),e.createElement(d,{isActive:o==="rules"},e.createElement(re,{data:A})),i&&e.createElement(d,{isActive:o==="teams"},e.createElement(te,{data:m,levelNames:f.levelNames,filters:l,setActiveTab:s,teamLabel:n,teamProperty:w})))))}const le=N(_)`
2
2
  display: none;
3
3
 
4
- @media screen and (min-width: ${O.medium}) {
4
+ @media screen and (min-width: ${B.medium}) {
5
5
  display: flex;
6
6
  }
7
7
  --menu-container-padding-top: 0;
8
- `;export{he as ScorecardDashboard};
8
+ `;export{Se as ScorecardDashboard};
@@ -64,4 +64,5 @@ export declare const LevelComplianceCardTitle: import("styled-components/dist/ty
64
64
  }, never>>> & string;
65
65
  export declare const ContentWithDotWrap: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
66
66
  export declare const EmojiWrap: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
67
+ export declare const LinkButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, keyof import("react").ButtonHTMLAttributes<HTMLButtonElement> | keyof import("react").ClassAttributes<HTMLButtonElement>> & import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement>, "about" | "accessKey" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "autoCapitalize" | "autoCorrect" | "autoFocus" | "autoSave" | "children" | "className" | "color" | "content" | "contentEditable" | "contextMenu" | "dangerouslySetInnerHTML" | "datatype" | "defaultChecked" | "defaultValue" | "dir" | "disabled" | "draggable" | "enterKeyHint" | "exportparts" | "form" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "hidden" | "id" | "inert" | "inlist" | "inputMode" | "is" | "itemID" | "itemProp" | "itemRef" | "itemScope" | "itemType" | "key" | "lang" | "name" | "nonce" | "onAbort" | "onAbortCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAuxClick" | "onAuxClickCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onBeforeToggle" | "onBlur" | "onBlurCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onChange" | "onChangeCapture" | "onClick" | "onClickCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onContextMenu" | "onContextMenuCapture" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onError" | "onErrorCapture" | "onFocus" | "onFocusCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onInput" | "onInputCapture" | "onInvalid" | "onInvalidCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onLoad" | "onLoadCapture" | "onLoadStart" | "onLoadStartCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onPaste" | "onPasteCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerMove" | "onPointerMoveCapture" | "onPointerOut" | "onPointerOutCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerUp" | "onPointerUpCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onReset" | "onResetCapture" | "onScroll" | "onScrollCapture" | "onScrollEnd" | "onScrollEndCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onSelect" | "onSelectCapture" | "onStalled" | "onStalledCapture" | "onSubmit" | "onSubmitCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onToggle" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onTransitionCancel" | "onTransitionCancelCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "onTransitionRun" | "onTransitionRunCapture" | "onTransitionStart" | "onTransitionStartCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onWheel" | "onWheelCapture" | "part" | "popover" | "popoverTarget" | "popoverTargetAction" | "prefix" | "property" | "radioGroup" | "ref" | "rel" | "resource" | "results" | "rev" | "role" | "security" | "slot" | "spellCheck" | "style" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "tabIndex" | "title" | "translate" | "type" | "typeof" | "unselectable" | "value" | "vocab"> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, keyof import("react").ButtonHTMLAttributes<HTMLButtonElement> | keyof import("react").ClassAttributes<HTMLButtonElement>> & import("react").ClassAttributes<HTMLButtonElement> & import("react").ButtonHTMLAttributes<HTMLButtonElement>, "about" | "accessKey" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "autoCapitalize" | "autoCorrect" | "autoFocus" | "autoSave" | "children" | "className" | "color" | "content" | "contentEditable" | "contextMenu" | "dangerouslySetInnerHTML" | "datatype" | "defaultChecked" | "defaultValue" | "dir" | "disabled" | "draggable" | "enterKeyHint" | "exportparts" | "form" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "hidden" | "id" | "inert" | "inlist" | "inputMode" | "is" | "itemID" | "itemProp" | "itemRef" | "itemScope" | "itemType" | "key" | "lang" | "name" | "nonce" | "onAbort" | "onAbortCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAuxClick" | "onAuxClickCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onBeforeToggle" | "onBlur" | "onBlurCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onChange" | "onChangeCapture" | "onClick" | "onClickCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onContextMenu" | "onContextMenuCapture" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onError" | "onErrorCapture" | "onFocus" | "onFocusCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onInput" | "onInputCapture" | "onInvalid" | "onInvalidCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onLoad" | "onLoadCapture" | "onLoadStart" | "onLoadStartCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onPaste" | "onPasteCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerMove" | "onPointerMoveCapture" | "onPointerOut" | "onPointerOutCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerUp" | "onPointerUpCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onReset" | "onResetCapture" | "onScroll" | "onScrollCapture" | "onScrollEnd" | "onScrollEndCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onSelect" | "onSelectCapture" | "onStalled" | "onStalledCapture" | "onSubmit" | "onSubmitCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onToggle" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onTransitionCancel" | "onTransitionCancelCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "onTransitionRun" | "onTransitionRunCapture" | "onTransitionStart" | "onTransitionStartCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onWheel" | "onWheelCapture" | "part" | "popover" | "popoverTarget" | "popoverTargetAction" | "prefix" | "property" | "radioGroup" | "ref" | "rel" | "resource" | "results" | "rev" | "role" | "security" | "slot" | "spellCheck" | "style" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "tabIndex" | "title" | "translate" | "type" | "typeof" | "unselectable" | "value" | "vocab">>> & string;
67
68
  //# sourceMappingURL=index.styles.d.ts.map
@@ -55,7 +55,7 @@ import r from"styled-components";import{Popup as t}from"reactjs-popup";import{Bu
55
55
  border: 1px solid var(--border-color-primary);
56
56
  background-color: var(${o=>o.colorVariable});
57
57
  margin-top: 1px;
58
- `,v=r.p`
58
+ `,u=r.p`
59
59
  margin: 16px 0 32px 0;
60
60
  font-size: 16px;
61
61
  color: var(--text-color-secondary);
@@ -88,7 +88,7 @@ import r from"styled-components";import{Popup as t}from"reactjs-popup";import{Bu
88
88
  @media screen and (max-width: 767px) {
89
89
  flex-direction: column;
90
90
  }
91
- `,u=r.input`
91
+ `,v=r.input`
92
92
  border: var(--filter-input-border);
93
93
  min-width: var(--filter-input-min-width);
94
94
  width: 100%;
@@ -197,12 +197,12 @@ import r from"styled-components";import{Popup as t}from"reactjs-popup";import{Bu
197
197
  text-align: center;
198
198
  display: block;
199
199
  }
200
- `,E=r(i)`
200
+ `,B=r(i)`
201
201
  display: flex;
202
202
  flex-direction: row;
203
203
  justify-content: space-between;
204
204
  gap: 10px;
205
- `,B=r.div`
205
+ `,E=r.div`
206
206
  display: flex;
207
207
  flex-direction: row;
208
208
  align-items: center;
@@ -217,4 +217,14 @@ import r from"styled-components";import{Popup as t}from"reactjs-popup";import{Bu
217
217
  'Noto Color Emoji',
218
218
  'EmojiOne Color';
219
219
  vertical-align: middle;
220
- `;export{C as AppPageWrapper,f as CardRow,a as CardValue,b as CardsWrapper,v as CatalogDescription,n as CatalogPageWrapper,W as Code,B as ContentWithDotWrap,m as Dot,M as EmojiWrap,I as FilePreview,g as GaugeNumber,P as GroupTh,T as InstanceControlsWrap,$ as InstanceMessage,z as InstanceReference,j as InstanceWrap,E as LevelComplianceCardTitle,y as ModeSwitcherTab,h as ModeSwitcherTabs,x as ProblemsByStatusCardBody,s as ScoreCardStatusCardBody,c as ScorecardCard,i as ScorecardCardTitle,S as SortIcon,u as StyledInput,k as StyledPopup,w as TableWrap};
220
+ `,D=r.button.attrs({type:"button"})`
221
+ padding: 0;
222
+ margin: 0;
223
+ border: 0;
224
+ background: none;
225
+ font: inherit;
226
+ font-weight: var(--link-font-weight);
227
+ color: var(--link-color-primary);
228
+ text-align: left;
229
+ cursor: pointer;
230
+ `;export{C as AppPageWrapper,f as CardRow,a as CardValue,b as CardsWrapper,u as CatalogDescription,n as CatalogPageWrapper,W as Code,E as ContentWithDotWrap,m as Dot,M as EmojiWrap,I as FilePreview,g as GaugeNumber,P as GroupTh,T as InstanceControlsWrap,$ as InstanceMessage,z as InstanceReference,j as InstanceWrap,B as LevelComplianceCardTitle,D as LinkButton,y as ModeSwitcherTab,h as ModeSwitcherTabs,x as ProblemsByStatusCardBody,s as ScoreCardStatusCardBody,c as ScorecardCard,i as ScorecardCardTitle,S as SortIcon,v as StyledInput,k as StyledPopup,w as TableWrap};
@@ -1 +1 @@
1
- import{useMemo as p,useState as H,useCallback as J}from"react";import{isDefined as U}from"../../../../utils/guards/is-defined.js";import{useCatalogClassic as G}from"../../../../client/app/hooks";import{usePageSharedData as L}from"../../../../client/providers/page-data/hooks";import{NON_CONFORMANT as v,OTHER_TEAMS_LABEL as K}from"./utils";function j(h,d){return Object.entries(h).find(([g])=>d.startsWith(g))?.[1]}function ee(h){const{catalogConfig:d,scorecardConfig:g,scorecardInfo:c}=h.pageProps,C=L("catalog"),S=C.some(e=>e.metadata?.publishedAt||e.metadata?.createdAt),A=g.teamMetadataProperty?.label||"Team",f=g.teamMetadataProperty?.property||"team",y=g.teamMetadataProperty?.default,T=C.some(e=>e.metadata?.[f]||e.metadata?.owner),k=p(()=>({...d,filters:[{title:"Scorecard level",property:"scorecardLevel",options:[v,...c.levelNames],type:"checkboxes"},S?{title:"Published date",property:"publishedAt",type:"date-range"}:void 0,T&&!d.filters?.find(e=>e.property===f)?{title:A,property:f,type:"select",...y&&{missingCategoryName:y}}:void 0,...d.filters||[]].filter(U)}),[d,T,S,A,y,f,c.levelNames]),N=L("scorecard"),q=C.filter(e=>!!j(N,e.link||"")),{filterTerm:M,setFilterTerm:D,groups:P,filters:E}=G(k,q),u=p(()=>P.flatMap(e=>e.items).map(e=>({api:{...e,publishedAt:e.publishedAt||e.createdAt,team:e[f]||e.owner},scorecard:j(N,e.link)})).filter(e=>e.scorecard),[JSON.stringify(P),N,f]),w=c.levelNames,z=p(()=>{const e={total:u.length,levels:{}};return[v,...w].forEach(r=>{e.levels[r]=u.filter(s=>s.scorecard?.scorecardLevel===r).length}),e},[u,w]),O=p(()=>w.map(e=>{const r={error:new Set,warn:new Set},s={errors:0,warnings:0};for(const t of u){if(!t.scorecard)continue;const o=t.scorecard.levels[e];if(o){s.errors+=o.errors||0,s.warnings+=o.warnings||0;for(const n of o.problems)r[n.severity]?.add(n.ruleId)}}return{name:e,count:s,uniqueCount:{errors:r.error.size,warnings:r.warn.size}}}),[u,w]),R=p(()=>O.reduce((e,r)=>e+r.count.errors+r.count.warnings,0),[O]),V=p(()=>{const e={};for(const r of c.rules)e[r]={count:0,apis:[],ruleId:r,status:0,apisCount:0,warningApisCount:0,errorApisCount:0,teams:{},levels:c.levelNames.reduce((s,t)=>(s[t]={warnings:0,errors:0},s),{})};for(const r of u){if(!r.scorecard)continue;const{scorecard:s,api:t}=r,o=new Set;for(const n of Object.keys(s?.levels||{})){const l=s.levels[n];for(const m of l?.problems||[]){const a=m.ruleId;if(!o.has(a))if(e[a]=e[a]||{count:0,apis:[],ruleId:a,status:0,apisCount:0,levels:{}},e[a].count++,typeof t.team=="string"&&(e[a].teams[t.team]=(e[a].teams[t.team]||0)+1),e[a].levels[n]=e[a].levels[n]||{warnings:0,errors:0},m.severity==="error"?(e[a].levels[n].errors++,e[a].errorApisCount++):(e[a].levels[n].warnings++,e[a].warningApisCount++),!e[a].apis.find(b=>b.link===t.link))e[a].apis.push({...t,count:1,severity:m.severity,problems:[m]});else{const b=e[a].apis.find(_=>_.link===t.link);b&&(b.count++,b.problems.push(m))}}for(const m of l?.problems||[])o.add(m.ruleId)}}for(const r of Object.values(e))r.apisCount=r.apis.length,r.status=r.apisCount>0?1:0,r.warningApisCount=r.apis.filter(s=>["warn","warning"].includes(s.severity)).length,r.errorApisCount=r.apis.filter(s=>s.severity==="error").length;return Object.values(e).sort((r,s)=>{let t=r.ruleId,o=s.ruleId;return t<o?-1:t>o?1:0})},[u,c.levelNames,c.rules]),[i,B]=H({property:"below",direction:"desc"}),W=J(e=>{i.property===e?B(r=>({...r,direction:r.direction==="asc"?"desc":"asc"})):B({property:e,direction:"asc"})},[i]),{sortedStatsByTeam:x,statsByTeam:I}=p(()=>{const e={},r={};for(const s of u){if(!s.scorecard)continue;const{api:t}=s,o=t.team?String(t.team):y||K;if(!o)continue;e[o]=e[o]||{team:o,below:0,minimum:0,highest:0,levels:{}};const n=r[o]=r[o]||{};for(const l of[v,...c.levelNames]){e[o].levels[l]=e[o].levels[l]||{errors:0,warnings:0,uniqueErrors:0,uniqueWarnings:0,apis:0},n[l]=n[l]||{error:new Set,warn:new Set},e[o].levels[l].errors+=s.scorecard?.levels[l]?.errors||0,e[o].levels[l].warnings+=s.scorecard?.levels[l]?.warnings||0,e[o].levels[l].apis+=s.scorecard.scorecardLevel===l?1:0;for(const m of s.scorecard?.levels[l]?.problems||[])n[l][m.severity]?.add(m.ruleId)}}for(const s of Object.keys(e))for(const t of Object.keys(e[s].levels))e[s].levels[t].uniqueErrors=r[s][t].error.size,e[s].levels[t].uniqueWarnings=r[s][t].warn.size;return{sortedStatsByTeam:Object.values(e).sort((s,t)=>{let o=s[i.property],n=t[i.property];return["team","below","minimum","highest"].includes(i.property)||(o=s.levels[i.property].errors*1e3+s.levels[i.property].warnings,n=t.levels[i.property].errors*1e3+t.levels[i.property].warnings),o<n?i.direction==="asc"?-1:1:o>n?i.direction==="asc"?1:-1:0}),statsByTeam:e}},[u,c.levelNames,i.direction,i.property,y]),F=p(()=>Object.values(I).sort((e,r)=>r.levels[v].apis-e.levels[v].apis).filter(e=>e.levels[v].apis>0),[I]);return{apis:u,summary:z,problemsByStatus:O,totalProblems:R,problemsByRule:V,sortedStatsByTeam:x,handleSortRulesTeams:W,nonConformantByTeam:F,filterTerm:M,setFilterTerm:D,groups:P,filters:E,scorecardInfo:c,catalogConfig:k,hasTeam:T,hasPublishedAt:S,teamLabel:A,teamProperty:f}}export{ee as useData};
1
+ import{useMemo as p,useState as H,useCallback as U}from"react";import{isDefined as G}from"../../../../utils/guards/is-defined.js";import{useCatalogClassic as J}from"../../../../client/app/hooks";import{usePageSharedData as L}from"../../../../client/providers/page-data/hooks";import{NON_CONFORMANT as v,OTHER_TEAMS_LABEL as K}from"./utils";function j(S,d){return Object.entries(S).find(([g])=>d.startsWith(g))?.[1]}function ee(S){const{catalogConfig:d,scorecardConfig:g,scorecardInfo:c}=S.pageProps,w=L("catalog"),A=w.some(e=>e.metadata?.publishedAt||e.metadata?.createdAt),T=g.teamMetadataProperty?.label||"Team",f=g.teamMetadataProperty?.property||"team",y=g.teamMetadataProperty?.default,P=w.some(e=>e.metadata?.[f]||e.metadata?.owner),k=p(()=>({...d,filters:[{title:"Scorecard level",property:"scorecardLevel",options:[v,...c.levelNames],type:"checkboxes"},A?{title:"Published date",property:"publishedAt",type:"date-range"}:void 0,P&&!d.filters?.find(e=>e.property===f)?{title:T,property:f,type:"select",...y&&{missingCategoryName:y}}:void 0,...d.filters||[]].filter(G)}),[d,P,A,T,y,f,c.levelNames]),h=L("scorecard"),q=p(()=>w.filter(e=>!!j(h,e.link||"")),[w,h]),{filterTerm:M,setFilterTerm:D,groups:N,filters:E}=J(k,q),u=p(()=>N.flatMap(e=>e.items).map(e=>({api:{...e,publishedAt:e.publishedAt||e.createdAt,team:e[f]||e.owner},scorecard:j(h,e.link)})).filter(e=>e.scorecard),[N,h,f]),C=c.levelNames,z=p(()=>{const e={total:u.length,levels:{}};return[v,...C].forEach(r=>{e.levels[r]=u.filter(s=>s.scorecard?.scorecardLevel===r).length}),e},[u,C]),O=p(()=>C.map(e=>{const r={error:new Set,warn:new Set},s={errors:0,warnings:0};for(const t of u){if(!t.scorecard)continue;const o=t.scorecard.levels[e];if(o){s.errors+=o.errors||0,s.warnings+=o.warnings||0;for(const n of o.problems)r[n.severity]?.add(n.ruleId)}}return{name:e,count:s,uniqueCount:{errors:r.error.size,warnings:r.warn.size}}}),[u,C]),R=p(()=>O.reduce((e,r)=>e+r.count.errors+r.count.warnings,0),[O]),V=p(()=>{const e={};for(const r of c.rules)e[r]={count:0,apis:[],ruleId:r,status:0,apisCount:0,warningApisCount:0,errorApisCount:0,teams:{},levels:c.levelNames.reduce((s,t)=>(s[t]={warnings:0,errors:0},s),{})};for(const r of u){if(!r.scorecard)continue;const{scorecard:s,api:t}=r,o=new Set;for(const n of Object.keys(s?.levels||{})){const l=s.levels[n];for(const m of l?.problems||[]){const a=m.ruleId;if(!o.has(a))if(e[a]=e[a]||{count:0,apis:[],ruleId:a,status:0,apisCount:0,levels:{}},e[a].count++,typeof t.team=="string"&&(e[a].teams[t.team]=(e[a].teams[t.team]||0)+1),e[a].levels[n]=e[a].levels[n]||{warnings:0,errors:0},m.severity==="error"?(e[a].levels[n].errors++,e[a].errorApisCount++):(e[a].levels[n].warnings++,e[a].warningApisCount++),!e[a].apis.find(b=>b.link===t.link))e[a].apis.push({...t,count:1,severity:m.severity,problems:[m]});else{const b=e[a].apis.find(_=>_.link===t.link);b&&(b.count++,b.problems.push(m))}}for(const m of l?.problems||[])o.add(m.ruleId)}}for(const r of Object.values(e))r.apisCount=r.apis.length,r.status=r.apisCount>0?1:0,r.warningApisCount=r.apis.filter(s=>["warn","warning"].includes(s.severity)).length,r.errorApisCount=r.apis.filter(s=>s.severity==="error").length;return Object.values(e).sort((r,s)=>{let t=r.ruleId,o=s.ruleId;return t<o?-1:t>o?1:0})},[u,c.levelNames,c.rules]),[i,B]=H({property:"below",direction:"desc"}),W=U(e=>{i.property===e?B(r=>({...r,direction:r.direction==="asc"?"desc":"asc"})):B({property:e,direction:"asc"})},[i]),{sortedStatsByTeam:x,statsByTeam:I}=p(()=>{const e={},r={};for(const s of u){if(!s.scorecard)continue;const{api:t}=s,o=t.team?String(t.team):y||K;if(!o)continue;e[o]=e[o]||{team:o,below:0,minimum:0,highest:0,levels:{}};const n=r[o]=r[o]||{};for(const l of[v,...c.levelNames]){e[o].levels[l]=e[o].levels[l]||{errors:0,warnings:0,uniqueErrors:0,uniqueWarnings:0,apis:0},n[l]=n[l]||{error:new Set,warn:new Set},e[o].levels[l].errors+=s.scorecard?.levels[l]?.errors||0,e[o].levels[l].warnings+=s.scorecard?.levels[l]?.warnings||0,e[o].levels[l].apis+=s.scorecard.scorecardLevel===l?1:0;for(const m of s.scorecard?.levels[l]?.problems||[])n[l][m.severity]?.add(m.ruleId)}}for(const s of Object.keys(e))for(const t of Object.keys(e[s].levels))e[s].levels[t].uniqueErrors=r[s][t].error.size,e[s].levels[t].uniqueWarnings=r[s][t].warn.size;return{sortedStatsByTeam:Object.values(e).sort((s,t)=>{let o=s[i.property],n=t[i.property];return["team","below","minimum","highest"].includes(i.property)||(o=s.levels[i.property].errors*1e3+s.levels[i.property].warnings,n=t.levels[i.property].errors*1e3+t.levels[i.property].warnings),o<n?i.direction==="asc"?-1:1:o>n?i.direction==="asc"?1:-1:0}),statsByTeam:e}},[u,c.levelNames,i.direction,i.property,y]),F=p(()=>Object.values(I).sort((e,r)=>r.levels[v].apis-e.levels[v].apis).filter(e=>e.levels[v].apis>0),[I]);return{apis:u,summary:z,problemsByStatus:O,totalProblems:R,problemsByRule:V,sortedStatsByTeam:x,handleSortRulesTeams:W,nonConformantByTeam:F,filterTerm:M,setFilterTerm:D,groups:N,filters:E,scorecardInfo:c,catalogConfig:k,hasTeam:P,hasPublishedAt:A,teamLabel:T,teamProperty:f}}export{ee as useData};
@@ -1 +1 @@
1
- import*as e from"react";import{useCallback as H,useMemo as b,useState as G,useEffect as _}from"react";import{useLocation as T}from"react-router";import{Flex as U}from"@redocly/portal-legacy-ui";import{Button as x}from"@redocly/theme/components/Button/Button";import{AddIcon as I}from"@redocly/theme/icons/AddIcon/AddIcon";import{SubtractIcon as D}from"@redocly/theme/icons/SubtractIcon/SubtractIcon";import{ArrowLeftIcon as K}from"@redocly/theme/icons/ArrowLeftIcon/ArrowLeftIcon";import{getScorecardColorVariable as z,withoutPathPrefix as O}from"@redocly/theme/core/utils";import{Link as P}from"../../../../client/app/Link";import N from"../../../../client/app/CircularProgress";import{isDefined as R}from"../../../../utils/guards/is-defined.js";import{removeLeadingSlash as Z}from"../../../../utils/url/remove-leading-slash.js";import{StatusByLevelWidget as J}from"./StatusByLevelWidget";import{OTHER_TEAMS_LABEL as Q,NON_CONFORMANT as X}from"./utils";import{LevelIndicator as Y}from"./LevelIndicator";import{AppPageWrapper as V,CardValue as v,CardsWrapper as j,CatalogDescription as ee,ModeSwitcherTab as te,ModeSwitcherTabs as re,CardRow as B,ProblemsByStatusCardBody as W,ScoreCardStatusCardBody as F,TableWrap as ne,LevelComplianceCardTitle as le,ContentWithDotWrap as C,ScorecardCard as S,ScorecardCardTitle as w}from"./index.styles";import{ApiLevel as M,InstanceStatus as k,LevelStatus as $,RuleStatus as q}from"./components";import{Grid as A}from"./Grid/Grid";import{useDetailedScorecard as ae}from"./useDetailedScorecard";import{Gauge as se,GaugeValue as ce}from"./Gauge";function Te(p){const u=T(),{data:d,levelNames:i,hasPublishedAt:n,hasTeam:s,teamLabel:l}=p,f=H((a,c,E)=>{const g=a.getValue(E)?new Date(a.getValue(E)).getTime():0,t=c.getValue(E)?new Date(c.getValue(E)).getTime():0;return g>t?1:-1},[]),m=b(()=>[{id:"title",header:"API",accessorKey:"api.title",size:200,cell:({getValue:a,row:c})=>e.createElement(P,{to:O(u.pathname)+"/apis/"+encodeURIComponent(Z(c.original.api.link))},a())},n?{header:"Published at",accessorKey:"api.publishedAt",sortingFn:f,cell:({getValue:a})=>{const c=a();return c?new Date(c).toLocaleDateString():"-"}}:void 0,s?{header:l,accessorKey:"api.team"}:void 0,{id:"level",header:"Level",accessorKey:"scorecard.scorecardLevel",cell:({getValue:a,row:c})=>e.createElement(M,{level:a(),colorVariable:z(c.original?.scorecard.scorecardLevelIdx,i.length+1)})},...i.map(a=>({id:a,header:`${a}`,accessorKey:"scorecard.levels",cell:({getValue:c,row:E})=>{const g=c(),t=E.original.api.link;return g?.[a]?e.createElement(Y,{key:t,uniqueErrors:g[a].uniqueErrors,uniqueWarnings:g[a].uniqueWarnings,id:t}):null}}))].filter(R),[f,i,u.pathname,n,s,l]);return e.createElement(A,{columns:m,data:d,sortBy:[{id:"title",desc:!1}]})}function Ie(p){const u=T(),{data:d}=p,i=b(()=>[{header:"Rules",accessorKey:"ruleId",cell:({getValue:n})=>e.createElement(P,{to:O(u.pathname)+"/rules/"+encodeURIComponent(n())},n())},{id:"status",header:"Status",accessorKey:"status",size:200,cell:({row:n})=>e.createElement(q,{errors:n.original.errorApisCount,warnings:n.original.warningApisCount})},{header:"Problem APIs",size:200,accessorKey:"apis",cell:({getValue:n})=>n().length,sortDescFirst:!0},{header:"Problem count",size:200,accessorKey:"count",sortDescFirst:!0}],[u.pathname]);return e.createElement(A,{columns:i,data:d,sortBy:[{id:"status",desc:!0}]})}function De(p){const{data:u,levelNames:d,filters:i,setActiveTab:n,teamLabel:s,teamProperty:l}=p,f=b(()=>[{id:"team",header:`API ${s}`,accessorKey:"team",size:200,cell:({getValue:m})=>e.createElement("a",{href:"#",onClick:a=>{a.preventDefault(),n("apis"),i.find(c=>c.property===l)?.selectOption(m())}},m())},...[X,...d].map(m=>({id:m,header:`${m}`,accessorFn:a=>a.levels[m]?.apis}))],[i,d,n,s,l]);return e.createElement(A,{columns:f,data:u,sortBy:[{id:"team",desc:!1}],groupHeaderTitle:"APIs by level"})}function oe(p){const{data:u,title:d}=p,i=b(()=>[{id:"expand",maxSize:40,size:40,header:()=>null,enableSorting:!1,cell:({row:n})=>n.getCanExpand()?e.createElement(x,{onClick:n.getToggleExpandedHandler(),variant:"text",size:"medium",icon:n.getIsExpanded()?e.createElement(D,null):e.createElement(I,null)}):null},{header:"Rules",accessorKey:"ruleId",cell:({getValue:n,row:s})=>s.getCanExpand()?e.createElement("span",{onClick:s.getToggleExpandedHandler()},n()):null},{header:"Status",accessorKey:"status",size:200,cell:({getValue:n})=>{const s=n();return e.createElement(q,{errors:s?.errorsCount,warnings:s?.warningsCount})},enableSorting:!1},{header:"Problem count",accessorKey:"problemsCount",size:200,sortDescFirst:!0}],[]);return e.createElement(A,{columns:i,data:u,sortBy:[{id:"ruleId",desc:!1}],empty:e.createElement(e.Fragment,null,"\u2705 This API is compliant with ",e.createElement("strong",null,d)," level rules"),subRowKey:"problems"})}function Ke(p){const{catalogSlug:u,slug:d,data:i,hasTeam:n,hasPublishedAt:s,teamLabel:l}=p,{apis:f,apisCount:m,warningApisCount:a,errorApisCount:c,levels:E,count:g}=i,t=f.length===0,h=t?void 0:{id:"expand",maxSize:40,size:40,header:()=>null,enableSorting:!1,cell:({row:r})=>r.getCanExpand()?e.createElement(x,{onClick:r.getToggleExpandedHandler(),variant:"text",size:"medium",icon:r.getIsExpanded()?e.createElement(D,null):e.createElement(I,null)}):null},L=b(()=>[h,{header:"API",accessorKey:"title"},s?{header:"Published at",accessorKey:"publishedAt",cell:({getValue:r})=>{const o=r();return o?new Date(o).toLocaleDateString():"-"}}:void 0,n?{header:l,accessorKey:"team",cell:({getValue:r})=>r()||Q}:void 0,{header:"Problem count",size:200,accessorKey:"count",cell:({getValue:r})=>r()||0,sortDescFirst:!0}].filter(R),[n,s,l,t]),y=b(()=>Object.entries(i.teams).sort((r,o)=>o[1]-r[1]),[i.teams]);return e.createElement(V,null,e.createElement(x,{icon:e.createElement(K,null),iconPosition:"left",variant:"ghost",size:"large",to:`${u}scorecard`},"Back to dashboard"),e.createElement("h1",null,"Rule ",d),e.createElement(j,null,e.createElement(S,null,e.createElement(w,null,"Rule status"),e.createElement(F,null,e.createElement("div",null,e.createElement(v,null,m),e.createElement("br",null),"APIs"),e.createElement("div",null,e.createElement(C,null,e.createElement(v,{style:{textAlign:"right"}},m-a-c),e.createElement(k,{severity:"Pass"})),e.createElement(C,null,e.createElement(v,{style:{textAlign:"right"}},a),e.createElement(k,{severity:"Warn"})),e.createElement(C,null,e.createElement(v,{style:{textAlign:"right"}},c),e.createElement(k,{severity:"Error"}))))),e.createElement(S,null,e.createElement(w,null,"Problems by level"),e.createElement(W,null,Object.entries(E).map(([r,o])=>e.createElement(B,{key:r},e.createElement("span",null,r),e.createElement(se,{chunks:[{share:o.errors/g*100,colorVariable:"--scorecard-color-error"},{share:o.warnings/g*100,colorVariable:"--scorecard-color-warning"}]}),e.createElement(ce,null,o.errors+o.warnings))))),e.createElement(S,null,e.createElement(w,null,`Problems by ${l}`),e.createElement(W,null,y.slice(0,4).map(([r,o])=>e.createElement(B,{key:r},e.createElement("span",{style:{flex:1,textAlign:"left"}},r),e.createElement(v,null,o)))))),e.createElement(A,{columns:L,data:f,sortBy:[{id:"title",desc:!1}],subRowKey:"problems",slug:d}))}function ze(p){const{slug:u,api:d,teamLabel:i,catalogSlug:n}=p,{api:s}=d||{},{scorecard:l,isLoading:f}=ae(`/${u}`),m=l?.levels||{},[a,c]=G(Object.keys(m)[0]),E=b(()=>s?.publishedAt instanceof Date?s?.publishedAt.toLocaleDateString():s?.publishedAt,[s]);_(()=>{if(l){const t=l.levels||{};c(Object.keys(t)[0])}},[l]);const g=b(()=>{if(!l?.levels)return{};const t={};for(const h of Object.keys(l.levels)){const L=l.levels[h].problems.reduce((y,r)=>(y[r.ruleId]||(y[r.ruleId]=[]),y[r.ruleId].push(r),y),{});t[h]=Object.entries(L).map(([y,r])=>({ruleId:y,problems:[...r.filter(o=>o.severity==="error"),...r.filter(o=>o.severity==="warn")],problemsCount:r.length,status:{errorsCount:r.filter(o=>o.severity==="error").length,warningsCount:r.filter(o=>o.severity==="warn").length}}))}return t},[l?.levels]);return f?e.createElement(U,{justifyContent:"center",mt:"2em"},e.createElement(N,null)):l?e.createElement(V,null,e.createElement(x,{icon:e.createElement(K,null),iconPosition:"left",variant:"ghost",size:"large",to:`${n}scorecard`},"Back to dashboard"),e.createElement("h1",null,s?.title||u),e.createElement(ee,null,E&&e.createElement(e.Fragment,null,"Published at: ",new Date().toLocaleString(void 0,{timeZoneName:"short"}),e.createElement("br",null)),e.createElement(P,{to:u,external:!0},"Documentation")),e.createElement(j,null,e.createElement(S,null,e.createElement(le,null,e.createElement("span",null,"Scorecard level"),e.createElement(M,{level:l.scorecardLevel,colorVariable:z(l.scorecardLevelIdx,Object.keys(m).length)})),e.createElement(F,null,e.createElement("div",null,"Compliance by level"),e.createElement("div",null,Object.entries(l.levels).map(([t,h])=>e.createElement(C,{key:t},e.createElement(v,{style:{width:"100px",textAlign:"right"}},t),e.createElement($,{errors:h.errors,warnings:h.warnings})))))),e.createElement(J,{title:"Rules compliance",levels:Object.entries(l.levels).map(([t,h])=>({errors:h.uniqueErrors,warnings:h.uniqueWarnings,total:p.rulesPerLevel[t].length,name:t}))}),e.createElement(S,null,e.createElement(w,null,i),e.createElement(v,{style:{fontWeight:"normal"}},s?.team))),e.createElement(re,{style:{justifyContent:"flex-start"},"data-component-name":"Scorecard/ModeSwitcherTabs"},Object.keys(l.levels).map(t=>e.createElement(te,{"data-component-name":"Scorecard/ModeSwitcherTab",key:t,isActive:a===t,onClick:()=>c(t)},e.createElement(C,null,e.createElement("span",null,t)," ",e.createElement($,{errors:l.levels[t].errors,warnings:l.levels[t].warnings}))))),Object.keys(m).map(t=>e.createElement(ne,{key:t,isActive:a===t},e.createElement(oe,{title:t,data:g[t]})))):e.createElement("div",null,"Scorecard not found")}export{Te as ApiListView,ze as ApiPage,oe as ApiView,Ke as RuleView,Ie as RulesView,De as TeamsView};
1
+ import*as e from"react";import{useCallback as H,useMemo as b,useState as G,useEffect as _}from"react";import{useLocation as T}from"react-router";import{Flex as U}from"@redocly/portal-legacy-ui";import{Button as x}from"@redocly/theme/components/Button/Button";import{AddIcon as I}from"@redocly/theme/icons/AddIcon/AddIcon";import{SubtractIcon as K}from"@redocly/theme/icons/SubtractIcon/SubtractIcon";import{ArrowLeftIcon as D}from"@redocly/theme/icons/ArrowLeftIcon/ArrowLeftIcon";import{getScorecardColorVariable as z,withoutPathPrefix as O}from"@redocly/theme/core/utils";import{Link as w}from"../../../../client/app/Link";import J from"../../../../client/app/CircularProgress";import{isDefined as R}from"../../../../utils/guards/is-defined.js";import{removeLeadingSlash as N}from"../../../../utils/url/remove-leading-slash.js";import{StatusByLevelWidget as Q}from"./StatusByLevelWidget";import{OTHER_TEAMS_LABEL as X,NON_CONFORMANT as Y}from"./utils";import{LevelIndicator as Z}from"./LevelIndicator";import{AppPageWrapper as V,CardValue as v,CardsWrapper as j,CatalogDescription as ee,ModeSwitcherTab as te,ModeSwitcherTabs as re,CardRow as B,ProblemsByStatusCardBody as W,ScoreCardStatusCardBody as F,TableWrap as ne,LevelComplianceCardTitle as le,ContentWithDotWrap as C,ScorecardCard as A,ScorecardCardTitle as L,LinkButton as ae}from"./index.styles";import{ApiLevel as M,InstanceStatus as k,LevelStatus as $,RuleStatus as q}from"./components";import{Grid as S}from"./Grid/Grid";import{useDetailedScorecard as se}from"./useDetailedScorecard";import{Gauge as ce,GaugeValue as oe}from"./Gauge";function Ie(p){const u=T(),{data:d,levelNames:i,hasPublishedAt:n,hasTeam:s,teamLabel:l}=p,f=H((a,o,E)=>{const g=a.getValue(E)?new Date(a.getValue(E)).getTime():0,t=o.getValue(E)?new Date(o.getValue(E)).getTime():0;return g>t?1:-1},[]),m=b(()=>[{id:"title",header:"API",accessorKey:"api.title",size:200,cell:({getValue:a,row:o})=>e.createElement(w,{to:O(u.pathname)+"/apis/"+encodeURIComponent(N(o.original.api.link))},a())},n?{header:"Published at",accessorKey:"api.publishedAt",sortingFn:f,cell:({getValue:a})=>{const o=a();return o?new Date(o).toLocaleDateString():"-"}}:void 0,s?{header:l,accessorKey:"api.team"}:void 0,{id:"level",header:"Level",accessorKey:"scorecard.scorecardLevel",cell:({getValue:a,row:o})=>e.createElement(M,{level:a(),colorVariable:z(o.original?.scorecard.scorecardLevelIdx,i.length+1)})},...i.map(a=>({id:a,header:`${a}`,accessorKey:"scorecard.levels",cell:({getValue:o,row:E})=>{const g=o(),t=E.original.api.link;return g?.[a]?e.createElement(Z,{key:t,uniqueErrors:g[a].uniqueErrors,uniqueWarnings:g[a].uniqueWarnings,id:t}):null}}))].filter(R),[f,i,u.pathname,n,s,l]);return e.createElement(S,{columns:m,data:d,sortBy:[{id:"title",desc:!1}]})}function Ke(p){const u=T(),{data:d}=p,i=b(()=>[{header:"Rules",accessorKey:"ruleId",cell:({getValue:n})=>e.createElement(w,{to:O(u.pathname)+"/rules/"+encodeURIComponent(n())},n())},{id:"status",header:"Status",accessorKey:"status",size:200,cell:({row:n})=>e.createElement(q,{errors:n.original.errorApisCount,warnings:n.original.warningApisCount})},{header:"Problem APIs",size:200,accessorKey:"apis",cell:({getValue:n})=>n().length,sortDescFirst:!0},{header:"Problem count",size:200,accessorKey:"count",sortDescFirst:!0}],[u.pathname]);return e.createElement(S,{columns:i,data:d,sortBy:[{id:"status",desc:!0}]})}function De(p){const{data:u,levelNames:d,filters:i,setActiveTab:n,teamLabel:s,teamProperty:l}=p,f=b(()=>[{id:"team",header:`API ${s}`,accessorKey:"team",size:200,cell:({getValue:m})=>e.createElement(ae,{onClick:()=>{n("apis"),i.find(a=>a.property===l)?.selectOption(m())}},m())},...[Y,...d].map(m=>({id:m,header:`${m}`,accessorFn:a=>a.levels[m]?.apis}))],[i,d,n,s,l]);return e.createElement(S,{columns:f,data:u,sortBy:[{id:"team",desc:!1}],groupHeaderTitle:"APIs by level"})}function ie(p){const{data:u,title:d}=p,i=b(()=>[{id:"expand",maxSize:40,size:40,header:()=>null,enableSorting:!1,cell:({row:n})=>n.getCanExpand()?e.createElement(x,{onClick:n.getToggleExpandedHandler(),variant:"text",size:"medium",icon:n.getIsExpanded()?e.createElement(K,null):e.createElement(I,null)}):null},{header:"Rules",accessorKey:"ruleId",cell:({getValue:n,row:s})=>s.getCanExpand()?e.createElement("span",{onClick:s.getToggleExpandedHandler()},n()):null},{header:"Status",accessorKey:"status",size:200,cell:({getValue:n})=>{const s=n();return e.createElement(q,{errors:s?.errorsCount,warnings:s?.warningsCount})},enableSorting:!1},{header:"Problem count",accessorKey:"problemsCount",size:200,sortDescFirst:!0}],[]);return e.createElement(S,{columns:i,data:u,sortBy:[{id:"ruleId",desc:!1}],empty:e.createElement(e.Fragment,null,"\u2705 This API is compliant with ",e.createElement("strong",null,d)," level rules"),subRowKey:"problems"})}function ze(p){const{catalogSlug:u,slug:d,data:i,hasTeam:n,hasPublishedAt:s,teamLabel:l}=p,{apis:f,apisCount:m,warningApisCount:a,errorApisCount:o,levels:E,count:g}=i,t=f.length===0,h=t?void 0:{id:"expand",maxSize:40,size:40,header:()=>null,enableSorting:!1,cell:({row:r})=>r.getCanExpand()?e.createElement(x,{onClick:r.getToggleExpandedHandler(),variant:"text",size:"medium",icon:r.getIsExpanded()?e.createElement(K,null):e.createElement(I,null)}):null},P=b(()=>[h,{header:"API",accessorKey:"title"},s?{header:"Published at",accessorKey:"publishedAt",cell:({getValue:r})=>{const c=r();return c?new Date(c).toLocaleDateString():"-"}}:void 0,n?{header:l,accessorKey:"team",cell:({getValue:r})=>r()||X}:void 0,{header:"Problem count",size:200,accessorKey:"count",cell:({getValue:r})=>r()||0,sortDescFirst:!0}].filter(R),[n,s,l,t]),y=b(()=>Object.entries(i.teams).sort((r,c)=>c[1]-r[1]),[i.teams]);return e.createElement(V,null,e.createElement(x,{icon:e.createElement(D,null),iconPosition:"left",variant:"ghost",size:"large",to:`${u}scorecard`},"Back to dashboard"),e.createElement("h1",null,"Rule ",d),e.createElement(j,null,e.createElement(A,null,e.createElement(L,null,"Rule status"),e.createElement(F,null,e.createElement("div",null,e.createElement(v,null,m),e.createElement("br",null),"APIs"),e.createElement("div",null,e.createElement(C,null,e.createElement(v,{style:{textAlign:"right"}},m-a-o),e.createElement(k,{severity:"Pass"})),e.createElement(C,null,e.createElement(v,{style:{textAlign:"right"}},a),e.createElement(k,{severity:"Warn"})),e.createElement(C,null,e.createElement(v,{style:{textAlign:"right"}},o),e.createElement(k,{severity:"Error"}))))),e.createElement(A,null,e.createElement(L,null,"Problems by level"),e.createElement(W,null,Object.entries(E).map(([r,c])=>e.createElement(B,{key:r},e.createElement("span",null,r),e.createElement(ce,{chunks:[{share:c.errors/g*100,colorVariable:"--scorecard-color-error"},{share:c.warnings/g*100,colorVariable:"--scorecard-color-warning"}]}),e.createElement(oe,null,c.errors+c.warnings))))),e.createElement(A,null,e.createElement(L,null,`Problems by ${l}`),e.createElement(W,null,y.slice(0,4).map(([r,c])=>e.createElement(B,{key:r},e.createElement("span",{style:{flex:1,textAlign:"left"}},r),e.createElement(v,null,c)))))),e.createElement(S,{columns:P,data:f,sortBy:[{id:"title",desc:!1}],subRowKey:"problems",slug:d}))}function Oe(p){const{slug:u,api:d,teamLabel:i,catalogSlug:n}=p,{api:s}=d||{},{scorecard:l,isLoading:f}=se(`/${u}`),m=l?.levels||{},[a,o]=G(Object.keys(m)[0]),E=b(()=>s?.publishedAt instanceof Date?s?.publishedAt.toLocaleDateString():s?.publishedAt,[s]);_(()=>{if(l){const t=l.levels||{};o(Object.keys(t)[0])}},[l]);const g=b(()=>{if(!l?.levels)return{};const t={};for(const h of Object.keys(l.levels)){const P=l.levels[h].problems.reduce((y,r)=>(y[r.ruleId]||(y[r.ruleId]=[]),y[r.ruleId].push(r),y),{});t[h]=Object.entries(P).map(([y,r])=>({ruleId:y,problems:[...r.filter(c=>c.severity==="error"),...r.filter(c=>c.severity==="warn")],problemsCount:r.length,status:{errorsCount:r.filter(c=>c.severity==="error").length,warningsCount:r.filter(c=>c.severity==="warn").length}}))}return t},[l?.levels]);return f?e.createElement(U,{justifyContent:"center",mt:"2em"},e.createElement(J,null)):l?e.createElement(V,null,e.createElement(x,{icon:e.createElement(D,null),iconPosition:"left",variant:"ghost",size:"large",to:`${n}scorecard`},"Back to dashboard"),e.createElement("h1",null,s?.title||u),e.createElement(ee,null,E&&e.createElement(e.Fragment,null,"Published at: ",E,e.createElement("br",null)),e.createElement(w,{to:u,external:!0},"Documentation")),e.createElement(j,null,e.createElement(A,null,e.createElement(le,null,e.createElement("span",null,"Scorecard level"),e.createElement(M,{level:l.scorecardLevel,colorVariable:z(l.scorecardLevelIdx,Object.keys(m).length)})),e.createElement(F,null,e.createElement("div",null,"Compliance by level"),e.createElement("div",null,Object.entries(l.levels).map(([t,h])=>e.createElement(C,{key:t},e.createElement(v,{style:{width:"100px",textAlign:"right"}},t),e.createElement($,{errors:h.errors,warnings:h.warnings})))))),e.createElement(Q,{title:"Rules compliance",levels:Object.entries(l.levels).map(([t,h])=>({errors:h.uniqueErrors,warnings:h.uniqueWarnings,total:p.rulesPerLevel[t].length,name:t}))}),e.createElement(A,null,e.createElement(L,null,i),e.createElement(v,{style:{fontWeight:"normal"}},s?.team))),e.createElement(re,{style:{justifyContent:"flex-start"},"data-component-name":"Scorecard/ModeSwitcherTabs"},Object.keys(l.levels).map(t=>e.createElement(te,{"data-component-name":"Scorecard/ModeSwitcherTab",key:t,isActive:a===t,onClick:()=>o(t)},e.createElement(C,null,e.createElement("span",null,t)," ",e.createElement($,{errors:l.levels[t].errors,warnings:l.levels[t].warnings}))))),Object.keys(m).map(t=>e.createElement(ne,{key:t,isActive:a===t},e.createElement(ie,{title:t,data:g[t]})))):e.createElement("div",null,"Scorecard not found")}export{Ie as ApiListView,Oe as ApiPage,ie as ApiView,ze as RuleView,Ke as RulesView,De as TeamsView};
@@ -1 +1,2 @@
1
- import{readFile as R,readdir as F,appendFile as I}from"node:fs/promises";import h from"node:path";import{existsSync as C}from"node:fs";import{SEARCH_GROUP_FACET_FIELD as S,SEARCH_PRODUCT_FIELD as v,SEARCH_VERSION_FIELD as w}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as $,SEARCH_DATA_EXPORT_FOLDER as D,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as O}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as j}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as N}from"../../../../config/env-config.js";import{ensureDir as m}from"../../../../utils/index.js";import{FlexSearchIndex as b}from"./search-index.js";class J{#e=new Map;#s;#t=0;async initIndexSchema(t){this.#s={document:{id:"id",tag:"tags",index:$},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#o(t,o){const i=this.#e.get(t);if(i)return i.find(s=>s.id===o)}#i(t,o){let i=this.#o(t,o);return i||(i=new b(o,this.#s),this.#e.set(t,[...this.#e.get(t)??[],i])),i}async addDocuments(t,o){if(t.length){const{group:i,locale:s,outDir:c}=o,n=this.#i(s,i);for(const r of t)n.add(r),N.isBuildMode&&(this.#t++,this.#t>=O&&await this.exportDocuments(c))}}getIndexesSize(){return this.#e.size}async search(t,o,i){return await j("com.redocly.search.performed",async s=>{s?.setAttribute("id","searchQueryId"),s?.setAttribute("object","searchQuery"),s?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:c,locale:n,filter:r,loadMore:a}=t,l=this.#e.get(n)??[];let f=[],d="",x=["v:default"];if(s?.setAttribute("locale",n),r)for(const e of r)e.field===S?f=[...f,...e.values]:e.field===v?d=`p:${e.values[0]}`:e.field===w&&e.values.length&&e.values.length===2&&(x=[...x,`v:${e.values[0]}:${e.values[1]}`]);const g={auth:o,query:c,offset:0,SEARCH_GROUP_FACET_FIELD:S,product:d,versions:x},p=[];let u={facets:{},documents:{}};if(a){const e=this.#o(n,a.groupKey);e&&p.push(e.search({...g,offset:a.offset}))}else for(const e of l)f&&f.length?f.includes(e.id)&&p.push(e.search(g)):p.push(e.search(g));const _=await Promise.all(p),A=_.some(e=>e.hasCoveringHit);for(const e of _)if(!(A&&!e.hasCoveringHit)){u.documents={...u.documents,...e.documents};for(const[y,E]of Object.entries(e.facets))u.facets[y]?u.facets[y]=[...u.facets[y],...E]:u.facets[y]=E}return u})}async exportDocuments(t){const o='{"documents":[',i=m(h.join(t,D));for(const[s,c]of this.#e){const n=m(h.join(i,s));for(const r of c){const a=Array.from(r.documents);if(a.length===0)continue;const l=m(h.join(n,`${r.id}.json`)),f=!C(l),d=JSON.stringify(a).substring(1).slice(0,-1),x=f?o+d:","+d;await I(l,x,{encoding:"utf8"}),r.clearDocuments()}}this.#t=0}async exportIndexes(t){const o=m(h.join(t,D));for(const[i,s]of this.#e){const c=m(h.join(o,i));for(const n of s){const r=m(h.join(c,`${n.id}.json`)),a={};await n.export((f,d)=>{a[f]=d});const l=`],"index":${JSON.stringify(a)}}`;await I(r,l,{encoding:"utf8"})}}this.#e.clear()}async import(t){const o=`${t}/${D}`;if(!C(o))return;const i=await F(o);for(const s of i){const c=await F(`${o}/${s}`);for(const n of c){const r=`${o}/${s}/${n}`,a=JSON.parse(await R(r,"utf-8")),l=h.parse(n).name;await this.#i(s,l).import(a)}}}countFacets(t,o,i){const s={};for(const[c,n]of i)s[c]=n.values.map(r=>({value:r,count:0,isCounterVisible:!1}));return s}cleanupFacetValues(t){}}export{J as FlexSearch};
1
+ import{readdir as S,appendFile as A}from"node:fs/promises";import l from"node:path";import{createReadStream as v,existsSync as w}from"node:fs";import{createInterface as O}from"node:readline";import{SEARCH_GROUP_FACET_FIELD as C,SEARCH_PRODUCT_FIELD as N,SEARCH_VERSION_FIELD as j}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as H,SEARCH_DATA_EXPORT_FOLDER as g,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as L}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as T}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as M}from"../../../../config/env-config.js";import{ensureDir as u}from"../../../../utils/index.js";import{FlexSearchIndex as b}from"./search-index.js";const F=".jsonl";function R(m){return`${JSON.stringify(m)}
2
+ `}async function*P(m){const t=O({input:v(m,{encoding:"utf8"}),crlfDelay:1/0});for await(const s of t)s&&(yield JSON.parse(s))}class K{#e=new Map;#s;#t=0;async initIndexSchema(t){this.#s={document:{id:"id",tag:"tags",index:H},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#i(t,s){const n=this.#e.get(t);if(n)return n.find(i=>i.id===s)}#n(t,s){let n=this.#i(t,s);return n||(n=new b(s,this.#s),this.#e.set(t,[...this.#e.get(t)??[],n])),n}async addDocuments(t,s){if(t.length){const{group:n,locale:i,outDir:c}=s,o=this.#n(i,n);for(const r of t)o.add(r),M.isBuildMode&&(this.#t++,this.#t>=L&&await this.exportDocuments(c))}}getIndexesSize(){return this.#e.size}async search(t,s,n){return await T("com.redocly.search.performed",async i=>{i?.setAttribute("id","searchQueryId"),i?.setAttribute("object","searchQuery"),i?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:c,locale:o,filter:r,loadMore:a}=t,d=this.#e.get(o)??[];let h=[],D="",y=["v:default"];if(i?.setAttribute("locale",o),r)for(const e of r)e.field===C?h=[...h,...e.values]:e.field===N?D=`p:${e.values[0]}`:e.field===j&&e.values.length&&e.values.length===2&&(y=[...y,`v:${e.values[0]}:${e.values[1]}`]);const _={auth:s,query:c,offset:0,SEARCH_GROUP_FACET_FIELD:C,product:D,versions:y},x=[];let f={facets:{},documents:{}};if(a){const e=this.#i(o,a.groupKey);e&&x.push(e.search({..._,offset:a.offset}))}else for(const e of d)h&&h.length?h.includes(e.id)&&x.push(e.search(_)):x.push(e.search(_));const E=await Promise.all(x),$=E.some(e=>e.hasCoveringHit);for(const e of E)if(!($&&!e.hasCoveringHit)){f.documents={...f.documents,...e.documents};for(const[p,I]of Object.entries(e.facets))f.facets[p]?f.facets[p]=[...f.facets[p],...I]:f.facets[p]=I}return f})}async exportDocuments(t){const s=u(l.join(t,g));for(const[n,i]of this.#e){const c=u(l.join(s,n));for(const o of i){const r=Array.from(o.documents,d=>R({document:d}));if(r.length===0)continue;const a=u(l.join(c,`${o.id}${F}`));await A(a,r.join(""),{encoding:"utf8"}),o.clearDocuments()}}this.#t=0}async exportIndexes(t){const s=u(l.join(t,g));for(const[n,i]of this.#e){const c=u(l.join(s,n));for(const o of i){const r=u(l.join(c,`${o.id}${F}`));await o.export((a,d)=>A(r,R({index:[String(a),d]}),{encoding:"utf8"}))}}this.#e.clear()}async import(t){const s=`${t}/${g}`;if(!w(s))return;const n=await S(s);for(const i of n){const c=await S(`${s}/${i}`);for(const o of c){const r=`${s}/${i}/${o}`,a=l.parse(o).name;await this.#n(i,a).import(P(r))}}}countFacets(t,s,n){const i={};for(const[c,o]of n)i[c]=o.values.map(r=>({value:r,count:0,isCounterVisible:!1}));return i}cleanupFacetValues(t){}}export{K as FlexSearch};
@@ -1,5 +1,5 @@
1
1
  import type { ExportHandler, IndexOptionsForDocumentSearch } from 'flexsearch';
2
- import type { FlexSearchData, IndexedSearchDocument, SearchIndex, SearchParameters, SearchDocument } from '../../../../types';
2
+ import type { FlexSearchDataEntry, IndexedSearchDocument, SearchIndex, SearchParameters, SearchDocument } from '../../../../types';
3
3
  import type { SearchResponse } from '../../../../../types/index.js';
4
4
  /** One group's results plus whether any of them holds every query word in a single value. */
5
5
  export type IndexSearchResponse = SearchResponse & {
@@ -13,7 +13,7 @@ export declare class FlexSearchIndex implements SearchIndex {
13
13
  get documentsCount(): number;
14
14
  clearDocuments(): void;
15
15
  export(handler: ExportHandler<string | IndexedSearchDocument>): Promise<void>;
16
- import(searchData: FlexSearchData): Promise<void>;
16
+ import(entries: AsyncIterable<FlexSearchDataEntry>): Promise<void>;
17
17
  add(document: SearchDocument): void;
18
18
  search(params: SearchParameters): Promise<IndexSearchResponse>;
19
19
  }
@@ -1 +1 @@
1
- import L from"flexsearch";import{REDOCLY_TEAMS_RBAC as A}from"@redocly/config";import{DISABLE_DEEP_LINK_IF_FIELDS_EXIST as R,SEARCH_LIMIT as D}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as b}from"../../../../telemetry/helpers/trace-step.js";import{highlightTextForSearch as u}from"../../../../utils/search/highlight-text-for-search.js";function v(S){const{name:e,description:t,place:r,path:o,deepLink:s}=S,i=s?.indexOf("#")??-1;return{name:e,description:t,place:r,...o&&{path:o},...s&&{deepLink:i>=0?s.slice(i+1):s}}}class C{#e;#t=new Map;#s=1;id;constructor(e,t){this.id=e,this.#e=new L.Document(t)}get documents(){return this.#t.entries()}get documentsCount(){return this.#s}clearDocuments(){this.#t.clear()}async export(e){await this.#e.export(e)}async import(e){const{documents:t,index:r}=e;this.#t.clear();for(const[o,s]of t)this.#t.set(o,s);for(const[o,s]of Object.entries(r))await this.#e.import(o,s)}add(e){const t={...e,tags:e.tags??[],[A]:e[A],...e.parameters&&{parameters:e.parameters.map(v)}};this.#t.set(this.#s,t),this.#e.add(this.#s,t),this.#s++}async search(e){return await b("com.redocly.search.performed",async t=>{t?.setAttribute("id","searchQueryId"),t?.setAttribute("object","searchQuery"),t?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:r,offset:o,auth:s,product:i,versions:n}=e,c=[],l=s.teams,p={limit:D,offset:o};let h=new Map,m=await this.#e.searchAsync(r,{...p,tag:l});if(i){const a=await this.#e.searchAsync(r,{...p,tag:i});m=this.#a(m,a),t?.setAttribute("product",i)}if(n&&n.length){const a=await this.#e.searchAsync(r,{...p,tag:n});m=this.#a(m,a),t?.setAttribute("versions",n.join(","))}for(const a of m)for(const d of a.result){const f=h.get(d)?.fields||[];h.set(d,{fields:a.field?[...f,a.field]:[...f]})}const x=this.#r(r),g=[];for(const[a,d]of h.entries()){const f=this.#t.get(a);f&&!this.#h(f,n)&&g.push({document:f,fields:d.fields,score:this.#l(x,f)})}const I=g.filter(a=>a.score>=x.length),y=I.length?I:g;y.sort((a,d)=>d.score-a.score);for(const a of y.slice(0,D))c.push({document:this.#n(a.document,r,a.fields),highlight:this.#c(a.document,r,a.fields)});return{documents:{[this.id]:c},facets:{},hasCoveringHit:I.length>0}})}#n(e,t,r){return this.#f(e,t,r)}#c(e,t,r){const o={};let s=!1;for(const i of r)if(i==="path")o.path=e.path?e.path.map(n=>u(t,n)):[];else if(i.includes("parameters")){if(!s){const n=i.split(":")[1],c=this.#o(t,n,e.parameters);c&&(o.parameters=[{name:u(t,c.name),description:u(t,c.description),place:u(t,c.place),path:c.path?c.path.map(l=>u(t,l)):[]}],s=!0)}}else o[i]=u(t,e[i]);return o}#r(e){return[...new Set(e.toLowerCase().split(/\s+/g).filter(Boolean))]}#i(e,t){const r=t.toLowerCase().replace(/\s+/g," "),o=e.filter(i=>r.includes(i)).length;let s=0;for(let i=1;i<e.length;i++)r.includes(`${e[i-1]} ${e[i]}`)&&s++;return o+s/e.length}#l(e,t){let r=0;const o=s=>{if(s==null)return;const i=this.#i(e,String(s));i>r&&(r=i)};o(t.title),o(t.text),o(t.httpPath),o(t.path?.join(" "));for(const s of t.parameters??[])o([s.name,s.description,s.place].filter(Boolean).join(" "));return r}#o(e,t,r){const o=this.#r(e);let s,i=0;for(const n of r??[]){const c=n[t],l=(Array.isArray(c)?c:[c]).filter(h=>h!=null).map(h=>String(h)).join(" "),p=this.#i(o,l);p>i&&(i=p,s=n)}return s}#a(e,t){const r=[];for(const o of e){const s=[];for(const i of t)for(const n of o.result){const c=i.result.find(l=>l===n);c&&s.push(c)}s.length&&r.push({result:s,field:o.field})}return r}#h(e,t){return!!(t&&t.length&&e.isDefaultVersion&&e.versionFolderId&&e.version&&t.some(r=>r.includes(e.versionFolderId??""))&&!t.some(r=>r.includes(e.version??"")))}#f(e,t,r){for(const s of R)if(r.some(i=>i===s))return e;let o;for(const s of r)if(s.includes("parameters")){const i=s.split(":")[1],n=this.#o(t,i,e.parameters);if(n){o=n.deepLink;break}}return o?{...e,url:`${e.url}#${o}`}:e}}export{C as FlexSearchIndex};
1
+ import _ from"flexsearch";import{REDOCLY_TEAMS_RBAC as L}from"@redocly/config";import{DISABLE_DEEP_LINK_IF_FIELDS_EXIST as C,SEARCH_LIMIT as R}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as b}from"../../../../telemetry/helpers/trace-step.js";import{highlightTextForSearch as m,markMatchedValue as D}from"../../../../utils/search/highlight-text-for-search.js";import{MIN_QUERY_WORD_LENGTH as M,containsQueryWord as S,matchableQueryWords as j}from"../../../../utils/search/text-match.js";function k(I){const{name:e,description:t,place:s,path:i,deepLink:r,example:n,enum:a}=I,o=r?.indexOf("#")??-1;return{name:e,description:t,place:s,...i&&{path:i},...r&&{deepLink:o>=0?r.slice(o+1):r},example:n,enum:a}}class T{#t;#e=new Map;#s=1;id;constructor(e,t){this.id=e,this.#t=new _.Document(t)}get documents(){return this.#e.entries()}get documentsCount(){return this.#s}clearDocuments(){this.#e.clear()}async export(e){await this.#t.export(e)}async import(e){this.#e.clear();for await(const t of e)if("document"in t){const[s,i]=t.document;this.#e.set(s,i)}else{const[s,i]=t.index;await this.#t.import(s,i)}}add(e){const t={...e,tags:e.tags??[],[L]:e[L],...e.parameters&&{parameters:e.parameters.map(k)}};this.#e.set(this.#s,t),this.#t.add(this.#s,t),this.#s++}async search(e){return await b("com.redocly.search.performed",async t=>{t?.setAttribute("id","searchQueryId"),t?.setAttribute("object","searchQuery"),t?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:s,offset:i,auth:r,product:n,versions:a}=e,o=[],l=r.teams,p={limit:R,offset:i},c=this.#r(s);if(!c.length&&s.trim())return{documents:{[this.id]:[]},facets:{},hasCoveringHit:!1};let d=new Map,g=await this.#t.searchAsync(s,{...p,tag:l});if(n){const h=await this.#t.searchAsync(s,{...p,tag:n});g=this.#a(g,h),t?.setAttribute("product",n)}if(a&&a.length){const h=await this.#t.searchAsync(s,{...p,tag:a});g=this.#a(g,h),t?.setAttribute("versions",a.join(","))}for(const h of g)for(const u of h.result){const f=d.get(u)?.fields||[];d.set(u,{fields:h.field?[...f,h.field]:[...f]})}!i&&c.length&&!d.size&&(d=this.#l(c,l,n,a));const x=[];for(const[h,u]of d.entries()){const f=this.#e.get(h);f&&!this.#d(f,a)&&x.push({document:f,fields:u.fields,score:this.#m(c,f)})}const y=x.filter(h=>h.score>=c.length),A=y.length?y:x;A.sort((h,u)=>u.score-h.score);for(const h of A.slice(0,R))o.push({document:this.#o(h.document,s,h.fields),highlight:this.#h(h.document,s,h.fields)});return{documents:{[this.id]:o},facets:{},hasCoveringHit:y.length>0}})}#o(e,t,s){return this.#g(e,t,s)}#h(e,t,s){const i={};let r=!1;for(const n of s)if(n==="path")i.path=e.path?e.path.map(a=>m(t,a)):[];else if(n.includes("parameters")){if(!r){const a=n.split(":")[1],o=this.#n(t,a,e.parameters);o&&(i.parameters=[{name:m(t,o.name),description:m(t,o.description),place:m(t,o.place),path:o.path?o.path.map(l=>m(t,l)):[],...this.#c(t,o)}],r=!0)}}else n!=="httpMethod"&&(i[n]=m(t,e[n]));return i}#c(e,t){return{enum:D(e,(t.enum??[]).join(", ")),example:D(e,t.example??"")}}#r(e){return j(e)}#l(e,t,s,i){const r=new Map;if(!e.length)return r;for(const[n,a]of this.#e)this.#p(a,t,s,i)&&this.#f(e,a)&&r.set(n,{fields:this.#u(e,a)});return r}#f(e,t){const s=i=>{if(i==null)return!1;const r=(Array.isArray(i)?i.join(" "):String(i)).toLowerCase();return!!r&&e.every(n=>S(r,n))};return s(t.title)||s(t.text)||s(t.httpPath)||s(t.path)?!0:(t.parameters??[]).some(i=>s(i.name)||s(i.description)||s(i.example)||s(i.enum))}#p(e,t,s,i){const r=new Set(e.tags??[]);return!(t.length&&!t.some(n=>r.has(n))||s&&!r.has(s)||i&&i.length&&!i.some(n=>r.has(n)))}#u(e,t){const s=r=>{if(r==null)return!1;const n=(Array.isArray(r)?r.join(" "):String(r)).toLowerCase();return e.some(a=>S(n,a))},i=[];s(t.title)&&i.push("title"),s(t.text)&&i.push("text"),s(t.path)&&i.push("path"),t.httpMethod&&e.some(r=>r.length>=M&&t.httpMethod?.toLowerCase().startsWith(r))&&i.push("httpMethod"),s(t.httpPath)&&i.push("httpPath");for(const r of["name","description","path","example","enum"])t.parameters?.some(n=>s(n[r]))&&i.push(`parameters[]:${r}`);return i}#i(e,t){const s=t.toLowerCase().replace(/\s+/g," "),i=e.filter(n=>S(s,n)).length;let r=0;for(let n=1;n<e.length;n++)s.includes(`${e[n-1]} ${e[n]}`)&&r++;return i+r/e.length}#m(e,t){let s=0;const i=r=>{if(r==null)return;const n=this.#i(e,String(r));n>s&&(s=n)};if(i(t.title),i(t.text),i(t.httpPath),i(t.path?.join(" ")),t.httpMethod){const r=t.httpMethod.toLowerCase(),n=e.filter(a=>a.length>=M&&r.startsWith(a)).length;n>s&&(s=n)}for(const r of t.parameters??[])i([r.name,r.description,r.place,r.example,r.enum?.join(" ")].filter(Boolean).join(" "));return s}#n(e,t,s){const i=this.#r(e);let r,n=0;for(const a of s??[]){const o=a[t],l=(Array.isArray(o)?o:[o]).filter(c=>c!=null).map(c=>String(c)).join(" "),p=this.#i(i,l);p>n&&(n=p,r=a)}return r}#a(e,t){const s=[];for(const i of e){const r=[];for(const n of t)for(const a of i.result){const o=n.result.find(l=>l===a);o&&r.push(o)}r.length&&s.push({result:r,field:i.field})}return s}#d(e,t){return!!(t&&t.length&&e.isDefaultVersion&&e.versionFolderId&&e.version&&t.some(s=>s.includes(e.versionFolderId??""))&&!t.some(s=>s.includes(e.version??"")))}#g(e,t,s){for(const r of C)if(s.some(n=>n===r))return e;let i;for(const r of s)if(r.includes("parameters")){const n=r.split(":")[1],a=this.#n(t,n,e.parameters);if(a){i=a.deepLink;break}}return i?{...e,url:`${e.url}#${i}`}:e}}export{T as FlexSearchIndex};
@@ -5,7 +5,7 @@ import d from"picomatch";import{dirname as T,resolve as $}from"node:path";import
5
5
  `),s.details&&t.push(`${s.details}
6
6
 
7
7
  `),s.sections.forEach(o=>{if(!o.llmstxts.length){g.warn(`llms.txt: No links found for section "${o.title}". Please check the includeFiles/excludeFiles patterns.`);return}t.push(`## ${o.title}
8
- `),o.description?t.push(`${o.description.replace(/\n+$/,"")}
8
+ `),o.description?t.push(`${o.description.replace(/(?<!\n)\n+$/,"")}
9
9
 
10
10
  `):t.push(`
11
11
  `),o.llmstxts.forEach(c=>{t.push(` - ${M({title:c.title,description:c.description,slug:I(c.slug),siteUrl:l})}`)}),t.push(`
@@ -1,3 +1,7 @@
1
- import{writeFileSync as tt}from"node:fs";import*as u from"path";import{removeMarkdocTags as et}from"../../../markdoc/helpers/remove-markdoc-tags.js";import{withoutHash as ot}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as rt,CONFIG_FILE_NAME as K}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as at}from"../../constants/common.js";import{findDeepFirst as M}from"../../../utils/tree/find-deep-first.js";import{isDefined as X}from"../../../utils/guards/is-defined.js";import{partition as it}from"../../../utils/array/partition.js";import{collectPropValueDeep as N}from"../../../utils/tree/collect-prop-value-deep.js";import{envConfig as nt}from"../../config/env-config.js";import{isLocalLink as st}from"../../../utils/path/is-local-link.js";import{normalizeRouteSlug as Y}from"../../../utils/path/normalize-route-slug.js";import{slash as lt}from"../../../utils/path/slash.js";import{parsePathVersions as ct}from"../../../utils/path/parse-path-versions.js";import{reporter as k}from"../../tools/notifiers/reporter.js";import{logger as B}from"../../tools/notifiers/logger.js";import{sha1 as ft}from"../../utils/crypto/sha1.js";import{collectItemsLinkedToSidebars as dt,resolveItems as J}from"../nav-utils.js";import{getExcludedFromLinkCheckerPatterns as ut,getSidebarReferences as mt,hasCircularDependency as gt}from"./utils.js";import{getLocaleFromRelativePath as pt}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as ht}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as St}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as yt}from"../../../cli/telemetry/helpers/trace-step.js";import{isPathIgnored as Ft}from"../../utils/paths.js";const It=180,bt=170,Dt=10;async function Jt({contentDir:f}){return{id:"sidebars",async afterRoutesCreated(o,i){await yt("com.redocly.build.plugin.sidebars",async()=>{const{cache:p,fs:d}=i,b=o.getConfig(),D=new Map,P=new Set,x=[E,...d.localeFolders],$=o.getGlobalData()[St]||{},j=new Map;let R=d.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!Ft(t,b.ignore??[])&&t);const G=await mt(i,f,R),Q=it(R.filter(t=>!G.has(t)),t=>{const l=ct(t);return l?`@versioned/${l.versionFolderPath}\0${l.filePathInVersion}`:t}),_=ut(b),Z=await dt(b?.navbar,o,i,{navFile:K,excludedFromLinkCheckerPatterns:_});let C;const T=gt(G);T&&Array.isArray(T)&&await k.panicOnBuildContentError(`Sidebar references have circular dependency. Please check your sidebar files.
2
- Circular dependency chain: ${T.reverse().join(" -> ")}
3
- `);for(const t of Q){const l=(await Promise.all(t.map(async n=>{const e=(await p.load(n,"yaml")).data;if(!Array.isArray(e)){await k.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',n,d,n,typeof e);return}return{items:e,sidebarRelativePath:n,locale:pt(n)}}))).filter(X),a=(await A(l))?.firstLink;C||(C=a)}const H=Object.entries(b?.catalogClassic??{});for(const t of x){for(const[e,c]of H)await z(e,c,t);const l={},a=new Set,n=o.getAllRoutesForLocale(t);for(const e of n)if(W(e)&&e.fsPath&&!a.has(e.fsPath)){a.add(e.fsPath);let s=u.posix.dirname(e.fsPath);const h=u.parse(s).root;do l[s]=(l[s]||0)+1,s=u.dirname(s);while(s&&s!="."&&h!=s)}for(const e of n){if(D.has(e.slug))continue;const c=W(e),s=u.dirname(e.fsPath),h=l[s]===1,m=vt(e.baseSlug||e.slug);c&&h?await A([{items:[{directory:s}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}]):e.getSidebar!==void 0&&await A([{items:[{page:e.fsPath}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}])}for(const[e,c]of H)await z(e,c,t,!0)}if(R.length===0)for(const t of x){B.verbose("Creating default sidebar");const l=t===E,a=`sidebars.yaml${l?"":"_"+t}`,n=l?"":`${d.localizationFolder}/${t}`,e=(await A([{items:[{directory:`./${n}`}],sidebarRelativePath:a,locale:t,ignoredRoutes:P}]))?.firstLink;C||(C=e)}if(!o.getRouteBySlug("/")&&!o.getConfig().redirects?.["/"]){const l=o.getAllRoutes().find(n=>!ht(n.slug)),a=C?C.link:l?.baseSlug??null;if(a){const n=ot(a);o.addRedirect("/",{to:n,type:302}),B.info("Creating default redirect for index page => %s",n)}}const U=nt.REDOCLY_METADATA_OUTPUT_FOLDER;U&&(B.info("Writing catalog data..."),tt(u.join(U,at),JSON.stringify(Object.fromEntries(j.entries()))));function W(t){return P.has(t.slug)||$[t.fsPath]}async function A(t){if(t.length===0)return;const a=(await Promise.all(t.map(async({items:m,locale:I,sidebarRelativePath:g,ignoredRoutes:L})=>{const r=await J(m,u.dirname(u.join(f,g)),o,i,{locale:I,ignoredRoutes:L,navFile:g,excludedFromLinkCheckerPatterns:_});if(!r){await k.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",g);return}return r}))).flat().filter(X),n=N(a,"routeSlug"),e=t[0].sidebarRelativePath,c=q(e),s=new Set;for(const m of n){const I=o.getRouteBySlug(m)?.fsPath??"",g=$[I];g&&(Array.from(s).find(r=>r.key===g.key&&r.version===g.version)||s.add(g)),o.addRouteSharedData(m,"sidebar",c),D.set(Y(m),a)}const h=s.size===1?Array.from(s)[0]:void 0;return await o.createSharedData(c,{relatedNavbarItem:Z?.get(e),items:a,catalogEntity:h?{key:h.key,version:h.version}:void 0}),{firstLink:M(a,m=>!!m.link),resolved:a}}async function z(t,l,a,n=!1){const e=structuredClone(l);a&&a!==E&&e.items.forEach(r=>{r.directory=u.posix.join(d.localizationFolder||"",a,r.directory||"")});let c=await J(e.items,f,o,i,{groupCustomSidebars:!0,locale:a,navFile:K,excludedFromLinkCheckerPatterns:_});if(!c){await k.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}Ct(c);const s=a===E?"":"/"+a.toLowerCase(),h=a===E?"":`-${a}`,m=Y(u.posix.join(s,e.slug));if(n)for(const r of c){const S=M(r.items||[],F=>!!F.routeSlug);if(!S?.routeSlug)continue;const y=D.get(S.routeSlug);if(!y)continue;const O=N(y,"routeSlug"),w="current-catalog-info-"+r.routeSlug+h,v={catalog:{label:e.title,titleTranslationKey:e.titleTranslationKey,link:m,icon:e?.icon},item:{label:r.metadata?.title,link:r.link,icon:r.icon}};await o.createSharedData(w,v);for(const F of O)o.addRouteSharedData(F,"current-catalog-info",w),P.add(F);const V=M(y,F=>!!F.link&&!F.external&&st(F.link)&&(!r.version||F.version===r.version));V&&(r.sidebar=[{...V,items:void 0}])}const I={},g=new Set;for(const r of c){if(!(r.routeSlug||r.sidebar?.[0]?.routeSlug)||!r.fsPath||g.has(r.fsPath))continue;g.add(r.fsPath);const y=u.dirname(r.fsPath);I[y]=(I[y]||0)+1}if(n){const r=await o.createSharedData("catalog-"+t+h,c.flatMap(S=>{const y=u.dirname(S.fsPath??""),O=I[y]===1,w=v=>({...v,fsPath:O?y:v.fsPath??""});return S.type==="group"&&S.items?.every(v=>v.type==="group")?(S.items||[]).map(w):w(S)}));o.addRouteSharedData(m,"catalog",r),Pt(a,c,j,I)}const L=N(c,"routeSlug");for(const r of L)P.add(r)}})}}}function Pt(f,o,i,p){if(f===E)for(const d of o){const b=d.routeSlug||d.sidebar?.[0]?.routeSlug;if(!b||!d.fsPath)continue;const D=u.dirname(d.fsPath),P=p[D]===1;i.set(b,{rootFileFsPath:d.fsPath,fsPath:P?D:d.fsPath,metadata:d.metadata||{},title:d.metadata?.title||d.label||"Untitled",version:d.version||"latest"})}}function Ct(f){const o=i=>{typeof i.metadata?.description=="string"&&(i.metadata={...i.metadata,description:et(i.metadata.description)})};for(const i of f)if(i.routeSlug)o(i);else for(const p of i.items||[])o(p)}function q(f){return rt+lt(f)}async function qt(f,o,i){const p=u.posix.join(u.dirname(f),o);return await i.exists(p)?q(p):(await k.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",f,i,f,o),null)}function vt(f){const o=f.replaceAll("/","_");if(o.length>It){const i=o.slice(0,bt),p=ft(f).slice(0,Dt).replaceAll("/","_");return i+p}else return o}export{qt as resolveSidebarId,Jt as sidebarsPlugin,Ct as stripMarkdocFromDescriptions};
1
+ import{writeFileSync as at}from"node:fs";import*as g from"path";import{removeMarkdocTags as nt}from"../../../markdoc/helpers/remove-markdoc-tags.js";import{withoutHash as it}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as st,CONFIG_FILE_NAME as Y}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as lt}from"../../constants/common.js";import{findDeepFirst as B}from"../../../utils/tree/find-deep-first.js";import{isDefined as M}from"../../../utils/guards/is-defined.js";import{partition as ct}from"../../../utils/array/partition.js";import{collectPropValueDeep as N}from"../../../utils/tree/collect-prop-value-deep.js";import{envConfig as ft}from"../../config/env-config.js";import{isLocalLink as ut}from"../../../utils/path/is-local-link.js";import{normalizeRouteSlug as J}from"../../../utils/path/normalize-route-slug.js";import{slash as dt}from"../../../utils/path/slash.js";import{parsePathVersions as mt}from"../../../utils/path/parse-path-versions.js";import{reporter as I}from"../../tools/notifiers/reporter.js";import{logger as $}from"../../tools/notifiers/logger.js";import{sha1 as gt}from"../../utils/crypto/sha1.js";import{getCatalogSharedDataId as pt}from"../../utils/catalog-classic/get-catalog-shared-data-id.js";import{collectItemsLinkedToSidebars as ht,resolveItems as q}from"../nav-utils.js";import{getExcludedFromLinkCheckerPatterns as yt,getSidebarReferences as St,hasCircularDependency as bt}from"./utils.js";import{collectTabRoutes as vt,findDuplicateRoutes as It,hasTabs as Dt,resolveTabs as Ft,tabsAsGroups as Ct,validateTabs as wt}from"./tabs.js";import{getLocaleFromRelativePath as Pt}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as Et}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as Rt}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as At}from"../../../cli/telemetry/helpers/trace-step.js";import{isPathIgnored as kt}from"../../utils/paths.js";const Lt=180,Tt=170,_t=10;async function ce({contentDir:u}){return{id:"sidebars",async afterRoutesCreated(a,c){await At("com.redocly.build.plugin.sidebars",async()=>{const{cache:h,fs:d}=c,D=a.getConfig(),F=new Map,C=new Set,G=[E,...d.localeFolders],x=a.getGlobalData()[Rt]||{},j=new Map;let L=d.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!kt(t,D.ignore??[])&&t);const H=await St(c,u,L),Z=ct(L.filter(t=>!H.has(t)),t=>{const i=mt(t);return i?`@versioned/${i.versionFolderPath}\0${i.filePathInVersion}`:t}),T=yt(D),tt=await ht(D?.navbar,a,c,{navFile:Y,excludedFromLinkCheckerPatterns:T});let w;const _=bt(H);_&&Array.isArray(_)&&await I.panicOnBuildContentError(`Sidebar references have circular dependency. Please check your sidebar files.
2
+ Circular dependency chain: ${_.reverse().join(" -> ")}
3
+ `);for(const t of Z){const i=(await Promise.all(t.map(async r=>{const e=(await h.load(r,"yaml")).data;if(!Array.isArray(e)){await I.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',r,d,r,typeof e);return}return{items:e,sidebarRelativePath:r,locale:Pt(r)}}))).filter(M),o=(await A(i))?.firstLink;w||(w=o)}const U=Object.entries(D?.catalogClassic??{});for(const t of G){for(const[e,s]of U)await K(e,s,t);const i={},o=new Set,r=a.getAllRoutesForLocale(t);for(const e of r)if(z(e)&&e.fsPath&&!o.has(e.fsPath)){o.add(e.fsPath);let l=g.posix.dirname(e.fsPath);const f=g.parse(l).root;do i[l]=(i[l]||0)+1,l=g.dirname(l);while(l&&l!="."&&f!=l)}for(const e of r){if(F.has(e.slug))continue;const s=z(e),l=g.dirname(e.fsPath),f=i[l]===1,m=Mt(e.baseSlug||e.slug);s&&f?await A([{items:[{directory:l}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}]):e.getSidebar!==void 0&&await A([{items:[{page:e.fsPath}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}])}for(const[e,s]of U)await K(e,s,t,!0)}if(L.length===0)for(const t of G){$.verbose("Creating default sidebar");const i=t===E,o=`sidebars.yaml${i?"":"_"+t}`,r=i?"":`${d.localizationFolder}/${t}`,e=(await A([{items:[{directory:`./${r}`}],sidebarRelativePath:o,locale:t,ignoredRoutes:C}]))?.firstLink;w||(w=e)}if(!a.getRouteBySlug("/")&&!a.getConfig().redirects?.["/"]){const i=a.getAllRoutes().find(r=>!Et(r.slug)),o=w?w.link:i?.baseSlug??null;if(o){const r=it(o);a.addRedirect("/",{to:r,type:302}),$.info("Creating default redirect for index page => %s",r)}}const W=ft.REDOCLY_METADATA_OUTPUT_FOLDER;W&&($.info("Writing catalog data..."),at(g.join(W,lt),JSON.stringify(Object.fromEntries(j.entries()))));function z(t){return C.has(t.slug)||x[t.fsPath]}async function A(t){if(t.length===0)return;const i=t.map(({items:e})=>Dt(e)),o=i.some(Boolean);if(o&&!i.every(Boolean)){await I.panicOnBuildContentError("Versioned copies of %rp must either all use navigation tabs or none of them",t[0].sidebarRelativePath);return}const r=o?await ot(t):await et(t);if(r)return rt(t[0].sidebarRelativePath,r)}async function et(t){const o=(await Promise.all(t.map(async({items:r,locale:e,sidebarRelativePath:s,ignoredRoutes:l})=>{const{fromDir:f,resolveOptions:m}=V(s,e,l),p=await q(r,f,a,c,m);if(!p){await I.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",s);return}return p}))).flat().filter(M);return{routeOwners:N(o,"routeSlug").map(r=>({routeSlug:r,items:o})),sharedData:{items:o},navItems:o}}async function ot(t){const i=t[0].sidebarRelativePath,r=(await Promise.all(t.map(async({items:l,locale:f,sidebarRelativePath:m,ignoredRoutes:p})=>{const y=wt(l);if(y.length){await I.panicOnBuildContentError(`Invalid navigation tabs in %rp:
4
+ - ${y.join(`
5
+ - `)}`,m);return}const{fromDir:k,resolveOptions:n}=V(m,f,p);return Ft(l,k,a,c,n)}))).flat().filter(M),e=vt(r),s=It(e);if(s.length){await I.panicOnBuildContentError(`Navigation tabs conflict in %rp. A route can belong to one tab only:
6
+ - ${s.map(({routeSlug:l,owners:f})=>`${l} is claimed by ${f.map(m=>`"${m}"`).join(" and ")}`).join(`
7
+ - `)}`,i);return}return{routeOwners:e,sharedData:{items:[],tabs:r},navItems:Ct(r)}}function V(t,i,o){return{fromDir:g.dirname(g.join(u,t)),resolveOptions:{locale:i,ignoredRoutes:o,navFile:t,excludedFromLinkCheckerPatterns:T}}}async function rt(t,{routeOwners:i,sharedData:o,navItems:r}){const e=Q(t),s=new Set;for(const{routeSlug:f,items:m}of i){const p=a.getRouteBySlug(f)?.fsPath??"",y=x[p];y&&(Array.from(s).find(n=>n.key===y.key&&n.version===y.version)||s.add(y)),a.addRouteSharedData(f,"sidebar",e),F.set(J(f),m)}const l=s.size===1?Array.from(s)[0]:void 0;return await a.createSharedData(e,{relatedNavbarItem:tt?.get(t),...o,catalogEntity:l?{key:l.key,version:l.version}:void 0}),{firstLink:B(r,f=>!!f.link),resolved:r}}async function K(t,i,o,r=!1){const e=structuredClone(i);o&&o!==E&&e.items.forEach(n=>{n.directory=g.posix.join(d.localizationFolder||"",o,n.directory||"")});let s=await q(e.items,u,a,c,{groupCustomSidebars:!0,locale:o,navFile:Y,excludedFromLinkCheckerPatterns:T});if(!s){await I.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}Bt(s);const l=o===E?"":"/"+o.toLowerCase(),f=o===E?"":`-${o}`,m=J(g.posix.join(l,e.slug));if(r)for(const n of s){const S=B(n.items||[],v=>!!v.routeSlug);if(!S?.routeSlug)continue;const b=F.get(S.routeSlug);if(!b)continue;const O=N(b,"routeSlug"),R="current-catalog-info-"+n.routeSlug+f,P={catalog:{label:e.title,titleTranslationKey:e.titleTranslationKey,link:m,icon:e?.icon},item:{label:n.metadata?.title,link:n.link,icon:n.icon}};await a.createSharedData(R,P);for(const v of O)a.addRouteSharedData(v,"current-catalog-info",R),C.add(v);const X=B(b,v=>!!v.link&&!v.external&&ut(v.link)&&(!n.version||v.version===n.version));X&&(n.sidebar=[{...X,items:void 0}])}const p={},y=new Set;for(const n of s){if(!(n.routeSlug||n.sidebar?.[0]?.routeSlug)||!n.fsPath||y.has(n.fsPath))continue;y.add(n.fsPath);const b=g.dirname(n.fsPath);p[b]=(p[b]||0)+1}if(r){const n=await a.createSharedData(pt(t,f),s.flatMap(S=>{const b=g.dirname(S.fsPath??""),O=p[b]===1,R=P=>({...P,fsPath:O?b:P.fsPath??""});return S.type==="group"&&S.items?.every(P=>P.type==="group")?(S.items||[]).map(R):R(S)}));a.addRouteSharedData(m,"catalog",n),Ot(o,s,j,p)}const k=N(s,"routeSlug");for(const n of k)C.add(n)}})}}}function Ot(u,a,c,h){if(u===E)for(const d of a){const D=d.routeSlug||d.sidebar?.[0]?.routeSlug;if(!D||!d.fsPath)continue;const F=g.dirname(d.fsPath),C=h[F]===1;c.set(D,{rootFileFsPath:d.fsPath,fsPath:C?F:d.fsPath,metadata:d.metadata||{},title:d.metadata?.title||d.label||"Untitled",version:d.version||"latest"})}}function Bt(u){const a=c=>{typeof c.metadata?.description=="string"&&(c.metadata={...c.metadata,description:nt(c.metadata.description)})};for(const c of u)if(c.routeSlug)a(c);else for(const h of c.items||[])a(h)}function Q(u){return st+dt(u)}async function fe(u,a,c){const h=g.posix.join(g.dirname(u),a);return await c.exists(h)?Q(h):(await I.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",u,c,u,a),null)}function Mt(u){const a=u.replaceAll("/","_");if(a.length>Lt){const c=a.slice(0,Tt),h=gt(u).slice(0,_t).replaceAll("/","_");return c+h}else return a}export{fe as resolveSidebarId,ce as sidebarsPlugin,Bt as stripMarkdocFromDescriptions};
@@ -0,0 +1,19 @@
1
+ import type { NavItem, ResolvedNavItem, ResolvedTab } from '@redocly/config';
2
+ import type { LifecycleContext, ResolveItemsOptions } from '../../types';
3
+ import type { ResolveLinkContext } from '../nav-utils';
4
+ export type TabRoute = {
5
+ routeSlug: string;
6
+ owner: string;
7
+ items: ResolvedNavItem[];
8
+ };
9
+ export declare function hasTabs(items: NavItem[] | undefined): boolean;
10
+ export declare function makeTabId(index: number, label: string): string;
11
+ export declare function validateTabs(sidebarItems: NavItem[]): string[];
12
+ export declare function resolveTabs(items: NavItem[], fromDir: string, actions: ResolveLinkContext, context: LifecycleContext, options: ResolveItemsOptions): Promise<ResolvedTab[]>;
13
+ export declare function collectTabRoutes(tabs: ResolvedTab[]): TabRoute[];
14
+ export declare function findDuplicateRoutes(routes: TabRoute[]): Array<{
15
+ routeSlug: string;
16
+ owners: string[];
17
+ }>;
18
+ export declare function tabsAsGroups(tabs: ResolvedTab[]): ResolvedNavItem[];
19
+ //# sourceMappingURL=tabs.d.ts.map
@@ -0,0 +1 @@
1
+ import{REDOCLY_ROUTE_RBAC as p,REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{collectPropValueDeep as v}from"../../../utils/tree/collect-prop-value-deep.js";import{isDefined as T}from"../../../utils/guards/is-defined.js";import{resolveItem as $,resolveItems as w}from"../nav-utils.js";function F(n){return Array.isArray(n)&&n.some(b)}function I(n,e){const a=e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|(?<!-)-+$/g,"");return`${n}-${a||"tab"}`}function x(n){const e=[],a=n.filter(o=>!b(o));a.length&&e.push(`when a sidebar uses tabs, every top-level entry must be a tab; found ${a.length} other entr${a.length===1?"y":"ies"}: ${JSON.stringify(a)}`);for(const{tab:o,page:i,menu:r,items:f,$ref:t,directory:l,group:s,href:m}of n.filter(b)){const u=`tab "${o}"`;if(r!==void 0&&!Array.isArray(r)){e.push(`${u} "menu" must be a list of entries`);continue}i?.includes("#")&&e.push(`${u} page must not contain a heading anchor`),r&&f?e.push(`${u} cannot have both "menu" and "items"`):r&&i?e.push(`${u} has "menu" and cannot also have "page"`):!r&&!i&&e.push(`${u} needs "page" or "menu"`),(t||l||s||m)&&e.push(`${u} accepts only "page", "items", "menu" and "rbac"; move "$ref"/"directory"/"group"/"href" into "items"`),r?.length===0&&e.push(`${u} has an empty "menu"`),r?.forEach((d,y)=>{const h=`menu entry ${y+1} of ${u}`;d?.page||e.push(`${h} needs "page"`),d?.page?.includes("#")&&e.push(`${h} page must not contain a heading anchor`)});const g=[...r??[],...f??[]];v(g,"tab").length&&e.push(`${u} contains a nested "tab"; tabs are only allowed at the top level`),v(g,"menu").length&&e.push(`${u} contains a nested "menu"; "menu" is only allowed directly on a tab`)}return e}async function C(n,e,a,o,i){const r=[];for(const[f,t]of n.filter(b).entries()){const l=I(f,t.tab);if(t.menu){const g=(await Promise.all(t.menu.map((y,h)=>A(y,l,h,e,a,o,i)))).filter(T),d=t.icon?S(await $({group:t.tab,icon:t.icon,items:[]},e,a,o,i)):void 0;r.push({type:"tab",tabId:l,label:t.tab,labelTranslationKey:t.tabTranslationKey,menu:g,icon:d?.icon,srcSet:d?.srcSet,[c]:t.rbac});continue}const s=S(await $({group:t.tab,rbac:t.rbac,page:t.page,icon:t.icon,items:[]},e,a,o,i)),m=s?.routeSlug?a.getRouteBySlug(s.routeSlug):void 0,u=await w(t.items,e,a,o,i)??[];r.push({type:"tab",tabId:l,label:t.tab,labelTranslationKey:t.tabTranslationKey,link:s?.link,routeSlug:s?.routeSlug,fsPath:s?.fsPath,icon:s?.icon,srcSet:s?.srcSet,items:[...s?.items??[],...u],...k(m?.versions,s),[c]:t.rbac??s?.[c],[p]:s?.[p]})}return r}function M(n){return n.flatMap(e=>e.menu?e.menu.flatMap(a=>R(`${e.label} > ${a.label}`,a.routeSlug,a.items)):R(e.label,e.routeSlug,e.items??[]))}function N(n){const e=new Map;for(const{routeSlug:a,owner:o}of n){const i=a.split("#")[0],r=e.get(i)??new Set;r.add(o),e.set(i,r)}return[...e.entries()].filter(([,a])=>a.size>1).map(([a,o])=>({routeSlug:a,owners:[...o]}))}function O(n){return n.map(e=>({type:"group",label:e.label,labelTranslationKey:e.labelTranslationKey,link:e.link,routeSlug:e.routeSlug,fsPath:e.fsPath,version:e.version,isDefault:e.isDefault,versionFolderId:e.versionFolderId,items:e.menu??e.items??[],[c]:e[c],[p]:e[p]}))}function b(n){return typeof n?.tab=="string"}async function A(n,e,a,o,i,r,f){const t=S(await $({...n,group:n.label||n.page,items:[]},o,i,r,f));if(!t?.link)return;const l=t.routeSlug?i.getRouteBySlug(t.routeSlug):void 0,s=n.label||await l?.getNavText?.()||t.link,m=await w(n.items,o,i,r,f)??[],u=[...t.items??[],...m];return{type:"link",tabId:`${e}/${I(a,s)}`,label:s,labelTranslationKey:n.labelTranslationKey,link:t.link,routeSlug:t.routeSlug,fsPath:t.fsPath,metadata:t.metadata,icon:t.icon,srcSet:t.srcSet,badges:t.badges,items:u,...k(l?.versions,t),[c]:n.rbac??l?.[c]??t[c],[p]:t[p]}}function S(n){const e=Array.isArray(n)?n[0]:n;return e?.type==="group"?e:void 0}function k(n,e){const a=n?.find(o=>o.active);return a?{version:a.version,isDefault:a.default,versionFolderId:a.folderId}:e?.version===void 0?{}:{version:e.version,isDefault:e.isDefault,versionFolderId:e.versionFolderId}}function R(n,e,a){return[e,...v(a,"routeSlug")].filter(T).map(o=>({routeSlug:o,owner:n,items:a}))}export{M as collectTabRoutes,N as findDuplicateRoutes,F as hasTabs,I as makeTabId,C as resolveTabs,O as tabsAsGroups,x as validateTabs};
@@ -1 +1 @@
1
- import{DEFAULT_SSO_IDP_TITLE as A}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as I}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as C}from"../../tools/notifiers/logger.js";const O="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function S(T){return{id:"sso",async processContent(i){await I("com.redocly.build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&C.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=O,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n};t&&(p.login_idps=t);const m={oidc:{title:A,type:"OIDC",configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid","offline"],authorizationRequestCustomParams:p,audience:"{{ process.env.ORGANIZATION_ID }}",introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{S as ssoPlugin};
1
+ import{AuthProviderType as A}from"@redocly/config";import{DEFAULT_SSO_IDP_TITLE as I}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as C}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as O}from"../../tools/notifiers/logger.js";const T="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function U(h){return{id:"sso",async processContent(i){await C("com.redocly.build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&O.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=T,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n};t&&(p.login_idps=t);const m={oidc:{title:I,type:A.OIDC,configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid","offline"],authorizationRequestCustomParams:p,audience:["{{ process.env.ORGANIZATION_ID }}"],introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{U as ssoPlugin};
@@ -1 +1 @@
1
- import{pathToFileURL as z}from"url";import{HelmetProvider as G}from"@dr.pogodin/react-helmet";import{renderToString as l}from"react-dom/server";import{StaticRouterProvider as J,createStaticHandler as K,createStaticRouter as Q}from"react-router";import r from"react";import{readFile as V}from"fs/promises";import{join as W}from"path";import{withPathPrefix as m,getLocaleFromPathname as X,withoutPathPrefix as Y,removeTrailingSlash as Z,getSafeClassName as tt}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as et}from"../../utils/path/slash.js";import{reporter as rt}from"../tools/notifiers/reporter.js";import{envConfig as p}from"../config/env-config.js";import{slug as ot}from"../../utils/slugger.js";import{shouldForwardProp as st}from"../../utils/should-forward-prop.js";import{htmlTemplate as nt}from"./template.js";import{detectColorSchemaScript as at,generatePreloadPageData as it,generatePreloadSharedData as ct}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as lt}from"./get-sitemap-link-tag.js";let g="";async function mt(t){return p.isRuntimeMode?await import("../../client/server-entry.js"):await import(z(`${et(t)}/server-entry.js`)+"?"+new Date)}async function Lt(t){if(!p.isRuntimeMode){const e=rt.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:u,App:R,routes:w,ServerStyleSheet:E,StyleSheetManager:C,ErrorDetails:P,initL10n:D}=await mt(t.serverOutDir),{page:h,store:{globalData:S,hasSitemap:y},sharedData:v,ssrHref:b}=t,d=S?.l10n,i=X(Y(h.slug),d?.defaultLocale,d?.locales),f=t.page.request?.url||"http://localhost/";await u.prepare({...h,slug:Z(new URL(f).pathname)},v,S,i),await D(i);const c=new E,{query:M,dataRoutes:x}=K([{Component:R,path:m("*"),children:w}]),s=await M(new Request(f));if(s instanceof Response)throw s;const B=Q(x,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=l(r.createElement(G,{context:e},r.createElement(C,{sheet:c.instance,shouldForwardProp:st},r.createElement(J,{router:B,context:s})))),L=y?lt():"",a=e.helmet,j=a?.title.toString()||"",k=t.store.globalData?.logo?.favicon,o=t.store.config,_=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${m("/app-data.json")}" />`,F=it(t.page.slug),H=ct(t.page.sharedDataIds),U=at(o),A=t.page.product?.name?tt(`product-${ot(t.page.product.name)}`):"",N=t.store.ssr.headTags.join(""),$=t.store.ssr.postBodyTags.join(""),I=t.store.ssr.preBodyTags.join(""),O=`<link rel="stylesheet" href="${m(T)}/browser-entry.css" />`;!p.isDevelopMode&&!g&&(g=`<style>${await V(W(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const q={bodyHtml:n,linkTags:o.linkTags+c.getStyleTags()+(a?.link.toString()||""),title:j,favicon:k,headScriptTags:L+U+o.headScriptTags+N+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[_,F,...H],postBodyScriptTags:o.postBodyScriptTags+$,preBodyScriptTags:o.preBodyScriptTags||""+I,lang:i,productClass:A,runtimeCss:g||O};return{html:nt(q),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:l(r.createElement(P,{error:e})),statusCode:500,error:e}}finally{c.seal(),u.clear()}}function jt(t){return l(r.createElement(r.Fragment,null,...t))}export{Lt as render,jt as renderComponents};
1
+ import{pathToFileURL as J}from"url";import{HelmetProvider as K}from"@dr.pogodin/react-helmet";import{renderToString as m}from"react-dom/server";import{StaticRouterProvider as Q,createStaticHandler as V,createStaticRouter as W}from"react-router";import r from"react";import{readFile as X}from"fs/promises";import{join as Y}from"path";import{withPathPrefix as p,getLocaleFromPathname as Z,withoutPathPrefix as tt,removeTrailingSlash as et,getSafeClassName as rt}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as ot}from"../../utils/path/slash.js";import{reporter as st}from"../tools/notifiers/reporter.js";import{envConfig as g}from"../config/env-config.js";import{slug as nt}from"../../utils/slugger.js";import{shouldForwardProp as at}from"../../utils/should-forward-prop.js";import{htmlTemplate as it}from"./template.js";import{detectColorSchemaScript as ct,generatePreloadPageData as lt,generatePreloadSharedData as mt}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as pt}from"./get-sitemap-link-tag.js";let u="";async function gt(t){return g.isRuntimeMode?await import("../../client/server-entry.js"):await import(J(`${ot(t)}/server-entry.js`)+"?"+new Date)}async function kt(t){if(!g.isRuntimeMode){const e=st.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:h,App:C,routes:R,ServerStyleSheet:w,StyleSheetManager:E,ErrorDetails:P,L10nContext:D,createSsrL10nContext:y}=await gt(t.serverOutDir),{page:S,store:{globalData:d,hasSitemap:v},sharedData:x,ssrHref:b}=t,i=d?.l10n,c=Z(tt(S.slug),i?.defaultLocale,i?.locales),f=t.page.request?.url||"http://localhost/";await h.prepare({...S,slug:et(new URL(f).pathname)},x,d,c);const L=await y(i,c),l=new w,{query:M,dataRoutes:B}=V([{Component:C,path:p("*"),children:R}]),s=await M(new Request(f));if(s instanceof Response)throw s;const j=W(B,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=m(r.createElement(D.Provider,{value:L},r.createElement(K,{context:e},r.createElement(E,{sheet:l.instance,shouldForwardProp:at},r.createElement(Q,{router:j,context:s}))))),k=v?pt():"",a=e.helmet,_=a?.title.toString()||"",F=t.store.globalData?.logo?.favicon,o=t.store.config,H=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${p("/app-data.json")}" />`,U=lt(t.page.slug),A=mt(t.page.sharedDataIds),N=ct(o),$=t.page.product?.name?rt(`product-${nt(t.page.product.name)}`):"",I=t.store.ssr.headTags.join(""),O=t.store.ssr.postBodyTags.join(""),q=t.store.ssr.preBodyTags.join(""),z=`<link rel="stylesheet" href="${p(T)}/browser-entry.css" />`;!g.isDevelopMode&&!u&&(u=`<style>${await X(Y(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const G={bodyHtml:n,linkTags:o.linkTags+l.getStyleTags()+(a?.link.toString()||""),title:_,favicon:F,headScriptTags:k+N+o.headScriptTags+I+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[H,U,...A],postBodyScriptTags:o.postBodyScriptTags+O,preBodyScriptTags:o.preBodyScriptTags||""+q,lang:c,productClass:$,runtimeCss:u||z};return{html:it(G),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:m(r.createElement(P,{error:e})),statusCode:500,error:e}}finally{l.seal(),h.clear()}}function _t(t){return m(r.createElement(r.Fragment,null,...t))}export{kt as render,_t as renderComponents};
@@ -59,6 +59,8 @@ export declare class Store {
59
59
  pagePropsGetters: Map<string, string>;
60
60
  listeners: Map<string, Set<(...args: any[]) => void>>;
61
61
  globalData: GlobalData;
62
+ /** Whether `POST /authorize` mints dev sessions: set by `realm develop` (unless `--no-dev-login`) and `realm build --devLogin`. */
63
+ devLogin: boolean;
62
64
  config: WithRequired<RedoclyConfig, 'redirects'> & ComputedRedoclyConfig;
63
65
  serverMode: boolean;
64
66
  serverOutDir: string;