@redocly/realm 0.129.2 → 0.130.0-custom.2

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 (464) hide show
  1. package/CHANGELOG.md +392 -83
  2. package/dist/bin.d.ts +1 -0
  3. package/dist/bin.js +1 -1
  4. package/dist/cli/develop.js +1 -1
  5. package/dist/cli/eject/resolveEjectParams.js +1 -1
  6. package/dist/cli/prepare/copy-env-files.js +1 -1
  7. package/dist/cli/prepare/index.js +1 -1
  8. package/dist/cli/stats/collectors/openapi.d.ts +3 -0
  9. package/dist/cli/stats/collectors/openapi.js +1 -0
  10. package/dist/cli/stats/index.d.ts +7 -0
  11. package/dist/cli/stats/index.js +1 -0
  12. package/dist/cli/stats/options.d.ts +3 -0
  13. package/dist/cli/stats/options.js +1 -0
  14. package/dist/cli/telemetry/index.d.ts +2 -2
  15. package/dist/cli/telemetry/index.js +1 -1
  16. package/dist/client/App.js +1 -1
  17. package/dist/client/ErrorBoundary.js +1 -1
  18. package/dist/client/app/Sidebar/RequestAccessButton.js +2 -2
  19. package/dist/client/app/Sidebar/Sidebar.js +2 -2
  20. package/dist/client/app/Sidebar/helpers/filter-out-versioned-items.d.ts +23 -0
  21. package/dist/client/app/Sidebar/helpers/filter-out-versioned-items.js +1 -0
  22. package/dist/client/app/Sidebar/useSidebarItems.d.ts +2 -2
  23. package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
  24. package/dist/client/app/hooks/catalog/useCatalogClassic.d.ts +1 -1
  25. package/dist/client/app/hooks/catalog/useCatalogClassic.js +1 -1
  26. package/dist/client/app/hooks/catalog/useCatalogFilter.js +1 -1
  27. package/dist/client/app/hooks/catalog/useCatalogViewMode.js +1 -1
  28. package/dist/client/app/hooks/catalog/useSearchTracker.js +1 -1
  29. package/dist/client/app/hooks/codeHighlight/useCodeHighlight.js +1 -1
  30. package/dist/client/app/hooks/usePageTimeTracker.js +1 -1
  31. package/dist/client/app/hooks/useRouteChangeTracker.js +1 -1
  32. package/dist/client/app/hooks/useTelemetry.d.ts +2 -2
  33. package/dist/client/app/pages/DevLogin/DevLogin.js +1 -1
  34. package/dist/client/app/search/message-handlers.d.ts +29 -0
  35. package/dist/client/app/search/message-handlers.js +1 -0
  36. package/dist/client/app/search/sse-parser.d.ts +10 -0
  37. package/dist/client/app/search/sse-parser.js +2 -0
  38. package/dist/client/app/search/useAiSearch.d.ts +9 -11
  39. package/dist/client/app/search/useAiSearch.js +1 -1
  40. package/dist/client/app/search/useSearch.js +1 -1
  41. package/dist/client/app/telemetry/index.d.ts +11 -1
  42. package/dist/client/app/telemetry/index.js +1 -1
  43. package/dist/client/browser-entry.js +5 -5
  44. package/dist/client/constants/ai-search.d.ts +30 -0
  45. package/dist/client/constants/ai-search.js +1 -0
  46. package/dist/client/constants/index.d.ts +2 -0
  47. package/dist/client/constants/index.js +1 -0
  48. package/dist/client/providers/hooks.js +1 -1
  49. package/dist/client/runtime/loader.js +1 -1
  50. package/dist/client/types/ai-search.d.ts +73 -0
  51. package/dist/client/types/ai-search.js +0 -0
  52. package/dist/client/types/index.d.ts +1 -0
  53. package/dist/config/env-config.d.ts +17 -0
  54. package/dist/config/env-config.js +1 -0
  55. package/dist/config/env-schema.d.ts +242 -0
  56. package/dist/config/env-schema.js +3 -0
  57. package/dist/config/env-schemas/api-urls.d.ts +24 -0
  58. package/dist/config/env-schemas/api-urls.js +1 -0
  59. package/dist/config/env-schemas/auth.d.ts +42 -0
  60. package/dist/config/env-schemas/auth.js +1 -0
  61. package/dist/config/env-schemas/catalog.d.ts +12 -0
  62. package/dist/config/env-schemas/catalog.js +1 -0
  63. package/dist/config/env-schemas/database.d.ts +15 -0
  64. package/dist/config/env-schemas/database.js +1 -0
  65. package/dist/config/env-schemas/environment-detection.d.ts +24 -0
  66. package/dist/config/env-schemas/environment-detection.js +1 -0
  67. package/dist/config/env-schemas/feature-flags.d.ts +24 -0
  68. package/dist/config/env-schemas/feature-flags.js +1 -0
  69. package/dist/config/env-schemas/organization-project.d.ts +27 -0
  70. package/dist/config/env-schemas/organization-project.js +1 -0
  71. package/dist/config/env-schemas/scorecards.d.ts +12 -0
  72. package/dist/config/env-schemas/scorecards.js +1 -0
  73. package/dist/config/env-schemas/search.d.ts +21 -0
  74. package/dist/config/env-schemas/search.js +1 -0
  75. package/dist/config/env-schemas/server-config.d.ts +51 -0
  76. package/dist/config/env-schemas/server-config.js +1 -0
  77. package/dist/config/env-schemas/site.d.ts +12 -0
  78. package/dist/config/env-schemas/site.js +1 -0
  79. package/dist/config/env-schemas/ssr.d.ts +18 -0
  80. package/dist/config/env-schemas/ssr.js +1 -0
  81. package/dist/config/env-schemas/telemetry.d.ts +15 -0
  82. package/dist/config/env-schemas/telemetry.js +1 -0
  83. package/dist/config/env-schemas/test.d.ts +22 -0
  84. package/dist/config/env-schemas/test.js +1 -0
  85. package/dist/constants/common.d.ts +4 -2
  86. package/dist/constants/common.js +1 -1
  87. package/dist/constants/l10n/langs/ar.js +1 -1
  88. package/dist/constants/l10n/langs/de.js +1 -1
  89. package/dist/constants/l10n/langs/en.js +1 -1
  90. package/dist/constants/l10n/langs/es.js +1 -1
  91. package/dist/constants/l10n/langs/fr.js +1 -1
  92. package/dist/constants/l10n/langs/hi.js +1 -1
  93. package/dist/constants/l10n/langs/it.js +1 -1
  94. package/dist/constants/l10n/langs/ja.js +1 -1
  95. package/dist/constants/l10n/langs/ko.js +1 -1
  96. package/dist/constants/l10n/langs/pl.js +1 -1
  97. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  98. package/dist/constants/l10n/langs/pt.js +1 -1
  99. package/dist/constants/l10n/langs/ru.js +1 -1
  100. package/dist/constants/l10n/langs/uk.js +1 -1
  101. package/dist/constants/l10n/langs/zh.js +1 -1
  102. package/dist/server/api-routes/execute-api-route.js +1 -1
  103. package/dist/server/api-routes/import-api-routes-handlers.js +1 -1
  104. package/dist/server/api-routes/run-api-routes-worker.js +1 -1
  105. package/dist/server/constants/common.js +1 -1
  106. package/dist/server/constants/plugins/catalog-entities.d.ts +1 -0
  107. package/dist/server/constants/plugins/catalog-entities.js +1 -1
  108. package/dist/server/entitlements/entitlements-provider.js +1 -1
  109. package/dist/server/esbuild/esbuild-logger.js +2 -2
  110. package/dist/server/esbuild/esbuild.js +3 -3
  111. package/dist/server/esbuild/plugins/assets-resolver.js +1 -1
  112. package/dist/server/esbuild/plugins/esbuild-compile-resolver.js +1 -1
  113. package/dist/server/esbuild/plugins/styled-components-ssr.js +1 -1
  114. package/dist/server/fs/cache.js +1 -1
  115. package/dist/server/fs/content-fs.d.ts +1 -0
  116. package/dist/server/fs/content-fs.js +1 -1
  117. package/dist/server/fs/last-modified-tracker.js +1 -1
  118. package/dist/server/fs/utils/is-loader-cache-enabled.js +1 -1
  119. package/dist/server/node-bundle-entry.js +1 -1
  120. package/dist/server/persistence/kv/repositories/kv-remote-repository.d.ts +1 -0
  121. package/dist/server/persistence/kv/repositories/kv-remote-repository.js +2 -1
  122. package/dist/server/persistence/kv/services/kv-service.js +1 -1
  123. package/dist/server/plugins/analytics/adobe/index.js +1 -1
  124. package/dist/server/plugins/analytics/amplitude/index.js +1 -1
  125. package/dist/server/plugins/analytics/fullstory/index.js +1 -1
  126. package/dist/server/plugins/analytics/ga/index.js +1 -1
  127. package/dist/server/plugins/analytics/gtm/browser-hooks.js +1 -1
  128. package/dist/server/plugins/analytics/gtm/index.js +1 -1
  129. package/dist/server/plugins/analytics/heap/index.js +1 -1
  130. package/dist/server/plugins/analytics/rudderstack/index.js +1 -1
  131. package/dist/server/plugins/analytics/segment/index.js +1 -1
  132. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.js +3 -3
  133. package/dist/server/plugins/asyncapi-docs/get-server-props.js +1 -1
  134. package/dist/server/plugins/asyncapi-docs/index.js +1 -1
  135. package/dist/server/plugins/asyncapi-docs/search/schema-processor.js +1 -1
  136. package/dist/server/plugins/asyncapi-docs/search/search-resolver.js +1 -1
  137. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.js +1 -1
  138. package/dist/server/plugins/asyncapi-docs/template/AsyncApiDocs.d.ts +2 -1
  139. package/dist/server/plugins/asyncapi-docs/template/AsyncApiDocs.js +9 -3
  140. package/dist/server/plugins/catalog-classic/get-server-props.d.ts +8 -3
  141. package/dist/server/plugins/catalog-classic/get-server-props.js +1 -1
  142. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +38 -64
  143. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
  144. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-attributes-db-record.d.ts +8 -0
  145. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-attributes-db-record.js +1 -0
  146. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-db-record.d.ts +2 -1
  147. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-read-model.js +1 -1
  148. package/dist/server/plugins/catalog-entities/database/mappers/{create-entity-relation.d.ts → create-entity-relation-read-model.d.ts} +2 -2
  149. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation-read-model.js +1 -0
  150. package/dist/server/plugins/catalog-entities/database/mappers/map-entity-relation-row.js +1 -1
  151. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +27 -0
  152. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -0
  153. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.d.ts +36 -0
  154. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +1 -0
  155. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.d.ts +15 -4
  156. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.js +38 -27
  157. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.d.ts +36 -9
  158. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +37 -21
  159. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +41 -42
  160. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.js +1 -1
  161. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.d.ts +3 -1
  162. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
  163. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.d.ts +7 -1
  164. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.js +1 -1
  165. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.d.ts +5 -9
  166. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +1 -1
  167. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-entities-exclusion-filter.d.ts +13 -0
  168. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-entities-exclusion-filter.js +1 -0
  169. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.d.ts +31 -0
  170. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.js +9 -0
  171. package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.d.ts +34 -0
  172. package/dist/server/plugins/catalog-entities/database/repositories/utils/create-merged-entity-fields-for-select.js +13 -0
  173. package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.d.ts +23 -0
  174. package/dist/server/plugins/catalog-entities/database/repositories/utils/normalize-revision-flags.js +1 -0
  175. package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.d.ts +78 -0
  176. package/dist/server/plugins/catalog-entities/database/repositories/utils/semantic-version-sort.js +34 -0
  177. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
  178. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
  179. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.d.ts +6 -4
  180. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
  181. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +2 -2
  182. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.d.ts +1 -1
  183. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
  184. package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
  185. package/dist/server/plugins/catalog-entities/get-server-props.js +1 -1
  186. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  187. package/dist/server/plugins/catalog-entities/schemas/database-schemas.d.ts +3 -0
  188. package/dist/server/plugins/catalog-entities/schemas/database-schemas.js +1 -1
  189. package/dist/server/plugins/catalog-entities/schemas/dto-schemas.d.ts +15 -1
  190. package/dist/server/plugins/catalog-entities/schemas/dto-schemas.js +1 -1
  191. package/dist/server/plugins/catalog-entities/schemas/read-model-schemas.d.ts +26 -164
  192. package/dist/server/plugins/catalog-entities/schemas/read-model-schemas.js +0 -1
  193. package/dist/server/plugins/catalog-entities/types/extractors.d.ts +4 -4
  194. package/dist/server/plugins/catalog-entities/types/openapi.d.ts +11 -0
  195. package/dist/server/plugins/catalog-entities/types/openapi.js +0 -0
  196. package/dist/server/plugins/catalog-entities/types/params.d.ts +6 -0
  197. package/dist/server/plugins/catalog-entities/types/params.js +0 -0
  198. package/dist/server/plugins/catalog-entities/utils/ajv-validator.js +1 -1
  199. package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.js +1 -1
  200. package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.d.ts +11 -0
  201. package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.js +1 -0
  202. package/dist/server/plugins/config-parser/index.js +1 -1
  203. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
  204. package/dist/server/plugins/config-parser/loaders/nearest-redocly-config-loader.js +1 -1
  205. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
  206. package/dist/server/plugins/default-theme/index.js +1 -1
  207. package/dist/server/plugins/entitlements/index.js +1 -1
  208. package/dist/server/plugins/graphql-docs/graphql-doc-loader.js +1 -1
  209. package/dist/server/plugins/graphql-docs/index.js +1 -1
  210. package/dist/server/plugins/graphql-docs/search/search-resolver.js +1 -1
  211. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +6 -2
  212. package/dist/server/plugins/lifecycle.js +2 -2
  213. package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
  214. package/dist/server/plugins/markdown/compiler.d.ts +1 -0
  215. package/dist/server/plugins/markdown/compiler.js +1 -1
  216. package/dist/server/plugins/markdown/index.js +1 -1
  217. package/dist/server/plugins/markdown/is-partial.d.ts +1 -1
  218. package/dist/server/plugins/markdown/is-partial.js +1 -1
  219. package/dist/server/plugins/markdown/markdoc/import-user-tags.js +1 -1
  220. package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.js +1 -1
  221. package/dist/server/plugins/markdown/markdoc/resolve-raw-partials.d.ts +1 -1
  222. package/dist/server/plugins/markdown/markdoc/resolve-raw-partials.js +2 -2
  223. package/dist/server/plugins/markdown/markdown-static-data-loader.js +1 -1
  224. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  225. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +54 -0
  226. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +1 -0
  227. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +9 -8
  228. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
  229. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +9 -8
  230. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
  231. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +9 -8
  232. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
  233. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +9 -8
  234. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
  235. package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +7 -13
  236. package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
  237. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +9 -6
  238. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.js +1 -1
  239. package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +9 -2
  240. package/dist/server/plugins/mcp/docs-mcp/tools/search.js +1 -1
  241. package/dist/server/plugins/mcp/docs-mcp/tools/utils.d.ts +2 -1
  242. package/dist/server/plugins/mcp/docs-mcp/tools/utils.js +6 -6
  243. package/dist/server/plugins/mcp/docs-mcp/tools/whoami.d.ts +9 -2
  244. package/dist/server/plugins/mcp/docs-mcp/tools/whoami.js +1 -1
  245. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  246. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  247. package/dist/server/plugins/mcp/handlers/handle-mcp-request.d.ts +5 -0
  248. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -0
  249. package/dist/server/plugins/mcp/handlers/mcp-request-handler.d.ts +0 -1
  250. package/dist/server/plugins/mcp/handlers/mcp-request-handler.js +1 -1
  251. package/dist/server/plugins/mcp/servers/base-server.js +1 -1
  252. package/dist/server/plugins/mcp/types.d.ts +40 -0
  253. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +3 -0
  254. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -0
  255. package/dist/server/plugins/nav-utils.d.ts +1 -1
  256. package/dist/server/plugins/nav-utils.js +1 -1
  257. package/dist/server/plugins/openapi-docs/decorators.d.ts +3 -0
  258. package/dist/server/plugins/openapi-docs/decorators.js +1 -1
  259. package/dist/server/plugins/openapi-docs/get-server-props-custom-fields.d.ts +2 -4
  260. package/dist/server/plugins/openapi-docs/get-server-props-custom-fields.js +1 -1
  261. package/dist/server/plugins/openapi-docs/get-server-props.js +1 -1
  262. package/dist/server/plugins/openapi-docs/index.js +1 -1
  263. package/dist/server/plugins/openapi-docs/load-definition.d.ts +1 -0
  264. package/dist/server/plugins/openapi-docs/load-definition.js +3 -3
  265. package/dist/server/plugins/openapi-docs/openrpc-converter.d.ts +2 -0
  266. package/dist/server/plugins/openapi-docs/openrpc-converter.js +1 -0
  267. package/dist/server/plugins/openapi-docs/search/search-resolver.js +1 -1
  268. package/dist/server/plugins/openapi-docs/search-indexer.js +1 -1
  269. package/dist/server/plugins/openapi-docs/store-definition-bundles.js +1 -1
  270. package/dist/server/plugins/openapi-docs/template/OpenAPIDocs.js +8 -4
  271. package/dist/server/plugins/openapi-docs/template/helpers.d.ts +2 -2
  272. package/dist/server/plugins/openapi-docs/template/helpers.js +3 -3
  273. package/dist/server/plugins/openapi-docs/utils.d.ts +1 -0
  274. package/dist/server/plugins/scorecard-classic/compute-scorecard.d.ts +2 -1
  275. package/dist/server/plugins/scorecard-classic/compute-scorecard.js +4 -4
  276. package/dist/server/plugins/scorecard-classic/get-scorecard-config.d.ts +2 -1
  277. package/dist/server/plugins/scorecard-classic/index.js +1 -1
  278. package/dist/server/plugins/scorecard-classic/lint.d.ts +1 -1
  279. package/dist/server/plugins/scorecard-classic/lint.js +1 -1
  280. package/dist/server/plugins/scorecard-classic/loaders/scorecard-config.js +1 -1
  281. package/dist/server/plugins/scorecard-classic/loaders/scorecard.d.ts +6 -4
  282. package/dist/server/plugins/scorecard-classic/loaders/scorecard.js +1 -1
  283. package/dist/server/plugins/scorecard-classic/shared-utils.d.ts +1 -1
  284. package/dist/server/plugins/scorecard-classic/shared-utils.js +1 -1
  285. package/dist/server/plugins/scorecard-classic/template/Grid/Grid.d.ts +2 -1
  286. package/dist/server/plugins/scorecard-classic/template/Grid/Grid.js +3 -3
  287. package/dist/server/plugins/scorecard-classic/template/LevelIndicator.d.ts +1 -0
  288. package/dist/server/plugins/scorecard-classic/template/LevelIndicator.js +4 -4
  289. package/dist/server/plugins/scorecard-classic/template/components.js +1 -1
  290. package/dist/server/plugins/scorecard-classic/template/index.styles.d.ts +1 -0
  291. package/dist/server/plugins/scorecard-classic/template/index.styles.js +93 -19
  292. package/dist/server/plugins/scorecard-classic/template/index.types.d.ts +5 -1
  293. package/dist/server/plugins/scorecard-classic/template/useData.js +1 -1
  294. package/dist/server/plugins/scorecard-classic/template/views.js +1 -1
  295. package/dist/server/plugins/scorecard-classic/types.d.ts +5 -3
  296. package/dist/server/plugins/scorecard-classic/types.js +1 -1
  297. package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.d.ts +12 -0
  298. package/dist/server/plugins/scorecards/database/repositories/local/scorecards-config-local-repository.js +1 -0
  299. package/dist/server/plugins/scorecards/database/scorecards-config-service.d.ts +11 -0
  300. package/dist/server/plugins/scorecards/database/scorecards-config-service.js +1 -0
  301. package/dist/server/plugins/scorecards/plugin.js +1 -1
  302. package/dist/server/plugins/scorecards/workers/run-scorecards-worker.d.ts +2 -1
  303. package/dist/server/plugins/scorecards/workers/run-scorecards-worker.js +1 -1
  304. package/dist/server/plugins/scorecards/workers/scorecards.d.ts +1 -12
  305. package/dist/server/plugins/scorecards/workers/scorecards.js +1 -1
  306. package/dist/server/plugins/search/ai-indexer/prepare-ai-search-documents.js +1 -1
  307. package/dist/server/plugins/search/documents/search-documents.js +1 -1
  308. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  309. package/dist/server/plugins/search/engines/typesense/index.js +1 -1
  310. package/dist/server/plugins/search/index.js +1 -1
  311. package/dist/server/plugins/search/llmstxt/index.js +5 -5
  312. package/dist/server/plugins/search/utils.js +2 -2
  313. package/dist/server/plugins/sidebars/index.d.ts +0 -2
  314. package/dist/server/plugins/sidebars/index.js +3 -3
  315. package/dist/server/plugins/sso/index.js +1 -1
  316. package/dist/server/providers/database/base-repository.d.ts +1 -0
  317. package/dist/server/providers/database/base-repository.js +1 -1
  318. package/dist/server/providers/database/database-connection-factory.js +1 -1
  319. package/dist/server/providers/database/database-initialization-strategy.js +1 -1
  320. package/dist/server/providers/database/database-preconnect-service.js +1 -1
  321. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0005_catalog-relations-constraint-fix.sql +2 -0
  322. package/dist/server/providers/database/databases/catalog-sqlite/migrations/0006_add-catalog-entitities-attributes-table.sql +11 -0
  323. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0005_snapshot.json +393 -0
  324. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/0006_snapshot.json +458 -0
  325. package/dist/server/providers/database/databases/catalog-sqlite/migrations/meta/_journal.json +14 -0
  326. package/dist/server/providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.d.ts +143 -0
  327. package/dist/server/providers/database/databases/catalog-sqlite/schemas/entities-attributes-table.js +1 -0
  328. package/dist/server/providers/database/databases/catalog-sqlite/schemas/entities-relations-table.js +1 -1
  329. package/dist/server/providers/database/databases/main-sqlite/migrations/0006_change-scorecards-config-timestamps-field-types.sql +19 -0
  330. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/0006_snapshot.json +261 -0
  331. package/dist/server/providers/database/databases/main-sqlite/migrations/meta/_journal.json +7 -0
  332. package/dist/server/providers/database/databases/main-sqlite/schemas/scorecards-config-table.d.ts +24 -18
  333. package/dist/server/providers/database/databases/main-sqlite/schemas/scorecards-config-table.js +1 -1
  334. package/dist/server/providers/database/databases/sqld-sqlite/drizzle.config.js +1 -1
  335. package/dist/server/providers/database/databases/sqld-sqlite/migrations/0007_catalog-relations-constraint-fix.sql +2 -0
  336. package/dist/server/providers/database/databases/sqld-sqlite/migrations/0008_add-catalog-entitities-attributes-table.sql +11 -0
  337. package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/0007_snapshot.json +833 -0
  338. package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/0008_snapshot.json +898 -0
  339. package/dist/server/providers/database/databases/sqld-sqlite/migrations/meta/_journal.json +14 -0
  340. package/dist/server/providers/database/pagination/entities-to-filter.d.ts +15 -0
  341. package/dist/server/providers/database/pagination/entities-to-filter.js +1 -0
  342. package/dist/server/providers/database/pagination/utils/index.d.ts +4 -0
  343. package/dist/server/providers/database/pagination/utils/index.js +1 -1
  344. package/dist/server/providers/database/pagination/utils/is-nested-condition.d.ts +16 -0
  345. package/dist/server/providers/database/pagination/utils/is-nested-condition.js +1 -0
  346. package/dist/server/providers/database/pagination/utils/is-simple-condition.d.ts +18 -0
  347. package/dist/server/providers/database/pagination/utils/is-simple-condition.js +1 -0
  348. package/dist/server/providers/database/pagination/utils/map-operator.d.ts +10 -0
  349. package/dist/server/providers/database/pagination/utils/map-operator.js +1 -0
  350. package/dist/server/providers/database/pagination/utils/transform-condition.d.ts +12 -0
  351. package/dist/server/providers/database/pagination/utils/transform-condition.js +1 -0
  352. package/dist/server/providers/database/sqld-not-running-error.d.ts +5 -0
  353. package/dist/server/providers/database/sqld-not-running-error.js +1 -0
  354. package/dist/server/ssr/render.js +1 -1
  355. package/dist/server/ssr/server-side-props/get-server-props-from-user-handler.js +1 -1
  356. package/dist/server/ssr/utils.js +8 -8
  357. package/dist/server/store.d.ts +14 -6
  358. package/dist/server/store.js +1 -1
  359. package/dist/server/telemetry/index.js +1 -1
  360. package/dist/server/tools/notifiers/formatter.js +3 -3
  361. package/dist/server/tools/notifiers/helpers/colors.js +1 -1
  362. package/dist/server/tools/notifiers/logger.js +2 -2
  363. package/dist/server/tools/notifiers/reporter.js +9 -9
  364. package/dist/server/tools/notifiers/terminal-manager.js +4 -4
  365. package/dist/server/types/plugins/common.d.ts +7 -1
  366. package/dist/server/types/plugins/markdown.d.ts +2 -0
  367. package/dist/server/types/plugins/scorecards.d.ts +30 -0
  368. package/dist/server/types/plugins/scorecards.js +0 -0
  369. package/dist/server/utils/envs/get-api-route-allowed-env-variables.js +1 -1
  370. package/dist/server/utils/envs/load-env-variables.d.ts +1 -1
  371. package/dist/server/utils/envs/load-env-variables.js +1 -1
  372. package/dist/server/utils/envs/sanitize-branch-name.d.ts +6 -0
  373. package/dist/server/utils/envs/sanitize-branch-name.js +1 -0
  374. package/dist/server/utils/globs.js +1 -1
  375. package/dist/server/utils/is-catalog-entities-enabled.js +1 -1
  376. package/dist/server/utils/is-scorecards-enabled.js +1 -1
  377. package/dist/server/utils/lifecycle-hooks.js +1 -1
  378. package/dist/server/utils/rbac.d.ts +76 -7
  379. package/dist/server/utils/rbac.js +1 -1
  380. package/dist/server/utils/report-all-errors.js +1 -1
  381. package/dist/server/utils/set-execution-mode.d.ts +5 -0
  382. package/dist/server/utils/set-execution-mode.js +1 -0
  383. package/dist/server/utils/time/with-timestamp.d.ts +42 -10
  384. package/dist/server/utils/time/with-timestamp.js +1 -1
  385. package/dist/server/version.js +1 -1
  386. package/dist/server/web-server/auth.js +3 -3
  387. package/dist/server/web-server/dev-server.js +1 -1
  388. package/dist/server/web-server/handle-api-route-request.js +1 -1
  389. package/dist/server/web-server/http.js +2 -2
  390. package/dist/server/web-server/middleware/apiKeyMiddleware.js +1 -1
  391. package/dist/server/web-server/middleware/catalogAuthMiddleware.d.ts +4 -6
  392. package/dist/server/web-server/middleware/catalogAuthMiddleware.js +1 -1
  393. package/dist/server/web-server/middleware/corsMiddleware.js +1 -1
  394. package/dist/server/web-server/middleware/dynamic-middleware/dynamic-middleware.js +1 -1
  395. package/dist/server/web-server/middleware/idleTimeoutMiddleware.js +1 -1
  396. package/dist/server/web-server/routes/ask-ai.js +1 -1
  397. package/dist/server/web-server/routes/auth.js +1 -1
  398. package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
  399. package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
  400. package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
  401. package/dist/server/web-server/routes/catalog/catalog.js +1 -1
  402. package/dist/server/web-server/routes/catalog/dto/read-entity-dto.d.ts +3 -0
  403. package/dist/server/web-server/routes/catalog/dto/read-entity-dto.js +0 -0
  404. package/dist/server/web-server/routes/catalog/helpers/create-entity-relation-update-schema.d.ts +43 -0
  405. package/dist/server/web-server/routes/catalog/helpers/create-entity-relation-update-schema.js +1 -0
  406. package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.d.ts +6823 -0
  407. package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.js +1 -0
  408. package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.d.ts +1102 -0
  409. package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.js +1 -0
  410. package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.d.ts +10 -0
  411. package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.js +1 -0
  412. package/dist/server/web-server/routes/catalog/mappers/map-entity-read-model-schema-to-entity-read-dto.d.ts +4 -0
  413. package/dist/server/web-server/routes/catalog/mappers/map-entity-read-model-schema-to-entity-read-dto.js +1 -0
  414. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entities.d.ts +4 -0
  415. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entities.js +1 -0
  416. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity-update-data.d.ts +4 -0
  417. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity-update-data.js +1 -0
  418. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity.d.ts +4 -0
  419. package/dist/server/web-server/routes/catalog/parsers/entities/parse-entity.js +1 -0
  420. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entities-relations.d.ts +13 -0
  421. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entities-relations.js +1 -0
  422. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation-update-data.d.ts +13 -0
  423. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation-update-data.js +1 -0
  424. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation.d.ts +13 -0
  425. package/dist/server/web-server/routes/catalog/parsers/relations/parse-entity-relation.js +1 -0
  426. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  427. package/dist/server/web-server/routes/error.js +1 -1
  428. package/dist/server/web-server/routes/helpers/get-current-rbac-teams.d.ts +3 -0
  429. package/dist/server/web-server/routes/helpers/get-current-rbac-teams.js +1 -0
  430. package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.d.ts +11 -0
  431. package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.js +1 -0
  432. package/dist/server/web-server/routes/index.js +1 -1
  433. package/dist/server/web-server/routes/info.js +1 -1
  434. package/dist/server/web-server/routes/mcp-oauth.js +1 -1
  435. package/dist/server/web-server/routes/otel/otel.js +1 -1
  436. package/dist/server/web-server/routes/page-data.js +1 -1
  437. package/dist/server/web-server/routes/path-prefix-redirect.js +1 -1
  438. package/dist/server/web-server/utils.d.ts +2 -2
  439. package/dist/server/workers/mcp-tool-worker-pool.d.ts +4 -0
  440. package/dist/server/workers/mcp-tool-worker-pool.js +1 -0
  441. package/dist/server/workers/mcp-tool-worker.d.ts +2 -0
  442. package/dist/server/workers/mcp-tool-worker.js +1 -0
  443. package/dist/server/workers/types.d.ts +7 -1
  444. package/dist/server/workers/worker-pool.js +1 -1
  445. package/package.json +21 -23
  446. package/dist/server/plugins/catalog-entities/database/mappers/create-entity-relation.js +0 -1
  447. package/dist/server/plugins/catalog-entities/entities/validate-entity.d.ts +0 -6
  448. package/dist/server/plugins/catalog-entities/entities/validate-entity.js +0 -1
  449. package/dist/server/plugins/mcp/workers/run-api-routes-worker.d.ts +0 -5
  450. package/dist/server/plugins/mcp/workers/run-api-routes-worker.js +0 -1
  451. package/dist/server/utils/envs/is-build-mode.d.ts +0 -2
  452. package/dist/server/utils/envs/is-build-mode.js +0 -1
  453. package/dist/server/utils/envs/is-develop-mode.d.ts +0 -7
  454. package/dist/server/utils/envs/is-develop-mode.js +0 -1
  455. package/dist/server/utils/envs/is-production-mode.d.ts +0 -10
  456. package/dist/server/utils/envs/is-production-mode.js +0 -1
  457. package/dist/server/workers/mcp-worker-pool.d.ts +0 -4
  458. package/dist/server/workers/mcp-worker-pool.js +0 -1
  459. package/dist/utils/env/is-local-development.d.ts +0 -13
  460. package/dist/utils/env/is-local-development.js +0 -1
  461. package/dist/utils/env/is-production.d.ts +0 -13
  462. package/dist/utils/env/is-production.js +0 -1
  463. package/dist/utils/env/is-web-view.d.ts +0 -14
  464. package/dist/utils/env/is-web-view.js +0 -1
@@ -15,7 +15,11 @@ export type Problem = {
15
15
  };
16
16
  export type Levels = keyof ScorecardData['levels'];
17
17
  export type RuleProblem = {
18
- apis: CatalogItem[];
18
+ apis: Record<string, CatalogItem & {
19
+ count: number;
20
+ problems: ProblemSummary[];
21
+ severity: 'error' | 'warning';
22
+ }>;
19
23
  ruleId: string;
20
24
  count: number;
21
25
  status: number;
@@ -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 U,useCallback as G}from"react";import{useProcessScorecard as K}from"@redocly/theme/ext/process-scorecard";import{isDefined as Q}from"../../../../utils/guards/is-defined.js";import{useCatalogClassic as X}from"../../../../client/app/hooks";import{usePageSharedData as M}from"../../../../client/providers/page-data/hooks";import{NON_CONFORMANT as v,OTHER_TEAMS_LABEL as Y}from"./utils";function j(b,d){return b[d]||Object.entries(b).find(([y])=>d.startsWith(y))?.[1]}function oe(b){const{catalogConfig:d,scorecardConfig:y,scorecardInfo:I}=b.pageProps,C=M("catalog"),h=C.some(e=>e.metadata?.publishedAt||e.metadata?.createdAt),{processScorecard:E,processInfo:k}=K(),u=p(()=>k(I),[I,k]),S=y.teamMetadataProperty?.label||"Team",f=y.teamMetadataProperty?.property||"team",g=y.teamMetadataProperty?.default,A=C.some(e=>e.metadata?.[f]||e.metadata?.owner),B=p(()=>({...d,filters:[{title:"Scorecard level",property:"scorecardLevel",options:[v,...u.levelNames],type:"checkboxes"},h?{title:"Published date",property:"publishedAt",type:"date-range"}:void 0,A&&!d.filters?.find(e=>e.property===f)?{title:S,property:f,type:"select",...g&&{missingCategoryName:g}}:void 0,...d.filters||[]].filter(Q)}),[d,A,h,S,g,f,u.levelNames]),T=M("scorecard"),D=C.filter(e=>e.metadata?.type==="openapi"&&!!j(T,e.link||"")),{filterTerm:V,setFilterTerm:z,groups:P,filters:R}=X({...B,separateVersions:!0},D,!0),m=p(()=>P.flatMap(e=>e.items).map(e=>({api:{...e,publishedAt:e.publishedAt||e.createdAt,team:e[f]||e.owner},scorecard:E(j(T,e.link),e)})).filter(e=>e.scorecard),[JSON.stringify(P),T,f]),w=u.levelNames,W=p(()=>{const e={total:m.length,levels:{}};return[v,...w].forEach(s=>{e.levels[s]=m.filter(r=>r.scorecard?.scorecardLevel===s).length}),e},[m,w]),N=p(()=>w.map(e=>{const s={error:new Set,warn:new Set},r={errors:0,warnings:0};for(const t of m){if(!t.scorecard)continue;const o=t.scorecard.levels[e];if(o){r.errors+=o.errors||0,r.warnings+=o.warnings||0;for(const a of o.problems)s[a.severity]?.add(a.ruleId)}}return{name:e,count:r,uniqueCount:{errors:s.error.size,warnings:s.warn.size}}}),[m,w]),x=p(()=>N.reduce((e,s)=>e+s.count.errors+s.count.warnings,0),[N]),F=p(()=>{const e={};for(const s of u.rules)e[s]={count:0,apis:{},ruleId:s,status:0,apisCount:0,warningApisCount:0,errorApisCount:0,teams:{},levels:u.levelNames.reduce((r,t)=>(r[t]={warnings:0,errors:0},r),{})};for(const s of m){if(!s.scorecard)continue;const{scorecard:r,api:t}=s,o=new Set;for(const a of Object.keys(r?.levels||{})){const l=r.levels[a];for(const c of l?.problems||[]){const n=c.ruleId;if(o.has(n))continue;e[n]=e[n]||{count:0,warningApisCount:0,errorApisCount:0,apis:{},ruleId:n,status:0,apisCount:0,levels:{},teams:{}},e[n].count++,typeof t.team=="string"&&(e[n].teams[t.team]=(e[n].teams[t.team]||0)+1),e[n].levels[a]=e[n].levels[a]||{warnings:0,errors:0},c.severity==="error"?(e[n].levels[a].errors++,e[n].errorApisCount++):(e[n].levels[a].warnings++,e[n].warningApisCount++);const O=e[n].apis[t.link];O?(O.count++,O.problems.push(c)):(e[n].apis[t.link]={...t,count:1,severity:c.severity,problems:[c]},c.severity==="error"?e[n].errorApisCount++:e[n].warningApisCount++,e[n].apisCount++,e[n].status=1)}for(const c of l?.problems||[])o.add(c.ruleId)}}return Object.values(e).sort((s,r)=>{let t=s.ruleId,o=r.ruleId;return t<o?-1:t>o?1:0})},[m,u.levelNames,u.rules]),[i,L]=U({property:"below",direction:"desc"}),_=G(e=>{i.property===e?L(s=>({...s,direction:s.direction==="asc"?"desc":"asc"})):L({property:e,direction:"asc"})},[i]),{sortedStatsByTeam:H,statsByTeam:q}=p(()=>{const e={},s={};for(const r of m){if(!r.scorecard)continue;const{api:t}=r,o=t.team?String(t.team):g||Y;if(!o)continue;e[o]=e[o]||{team:o,below:0,minimum:0,highest:0,levels:{}};const a=s[o]=s[o]||{};for(const l of[v,...u.levelNames]){e[o].levels[l]=e[o].levels[l]||{errors:0,warnings:0,uniqueErrors:0,uniqueWarnings:0,apis:0},a[l]=a[l]||{error:new Set,warn:new Set},e[o].levels[l].errors+=r.scorecard?.levels[l]?.errors||0,e[o].levels[l].warnings+=r.scorecard?.levels[l]?.warnings||0,e[o].levels[l].apis+=r.scorecard.scorecardLevel===l?1:0;for(const c of r.scorecard?.levels[l]?.problems||[])a[l][c.severity]?.add(c.ruleId)}}for(const r of Object.keys(e))for(const t of Object.keys(e[r].levels))e[r].levels[t].uniqueErrors=s[r][t].error.size,e[r].levels[t].uniqueWarnings=s[r][t].warn.size;return{sortedStatsByTeam:Object.values(e).sort((r,t)=>{let o=r[i.property],a=t[i.property];return["team","below","minimum","highest"].includes(i.property)||(o=r.levels[i.property].errors*1e3+r.levels[i.property].warnings,a=t.levels[i.property].errors*1e3+t.levels[i.property].warnings),o<a?i.direction==="asc"?-1:1:o>a?i.direction==="asc"?1:-1:0}),statsByTeam:e}},[m,u.levelNames,i.direction,i.property,g]),J=p(()=>Object.values(q).sort((e,s)=>s.levels[v].apis-e.levels[v].apis).filter(e=>e.levels[v].apis>0),[q]);return{apis:m,summary:W,problemsByStatus:N,totalProblems:x,problemsByRule:F,sortedStatsByTeam:H,handleSortRulesTeams:_,nonConformantByTeam:J,filterTerm:V,setFilterTerm:z,groups:P,filters:R,scorecardInfo:u,catalogConfig:B,hasTeam:A,hasPublishedAt:h,teamLabel:S,teamProperty:f}}export{oe 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-dom";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 _,useMemo as b,useState as U,useEffect as Z}from"react";import{useLocation as K}from"react-router-dom";import{Flex as J}from"@redocly/portal-legacy-ui";import{Button as w}from"@redocly/theme/components/Button/Button";import{AddIcon as V}from"@redocly/theme/icons/AddIcon/AddIcon";import{SubtractIcon as O}from"@redocly/theme/icons/SubtractIcon/SubtractIcon";import{ArrowLeftIcon as R}from"@redocly/theme/icons/ArrowLeftIcon/ArrowLeftIcon";import{useProcessScorecard as N}from"@redocly/theme/ext/process-scorecard";import{getScorecardColorVariable as z,withoutPathPrefix as I}from"@redocly/theme/core/utils";import{Link as T}from"../../../../client/app/Link";import Q from"../../../../client/app/CircularProgress";import{isDefined as W}from"../../../../utils/guards/is-defined.js";import{removeLeadingSlash as X}from"../../../../utils/url/remove-leading-slash.js";import{StatusByLevelWidget as Y}from"./StatusByLevelWidget";import{OTHER_TEAMS_LABEL as ee,NON_CONFORMANT as te}from"./utils";import{LevelIndicator as re}from"./LevelIndicator";import{AppPageWrapper as j,CardValue as S,CardsWrapper as B,CatalogDescription as ne,ModeSwitcherTab as ae,ModeSwitcherTabs as le,CardRow as F,ProblemsByStatusCardBody as q,ScoreCardStatusCardBody as M,TableWrap as se,LevelComplianceCardTitle as ce,ContentWithDotWrap as A,ScorecardCard as x,ScorecardCardTitle as L}from"./index.styles";import{ApiLevel as $,InstanceStatus as D,LevelStatus as H,RuleStatus as G}from"./components";import{Grid as P}from"./Grid/Grid";import{useDetailedScorecard as oe}from"./useDetailedScorecard";import{Gauge as ie,GaugeValue as ue}from"./Gauge";function Oe(g){const u=K(),{data:m,levelNames:i,hasPublishedAt:r,hasTeam:s,teamLabel:p}=g,y=_((t,a,d)=>{const o=t.getValue(d)?new Date(t.getValue(d)).getTime():0,f=a.getValue(d)?new Date(a.getValue(d)).getTime():0;return o>f?1:-1},[]),E=b(()=>[{id:"title",header:"API",accessorKey:"api.title",size:200,cell:({getValue:t,row:a})=>e.createElement(T,{to:I(u.pathname)+"/apis/"+encodeURIComponent(X(a.original.api.link))},t()," ",a.original.api.version)},r?{header:"Published at",accessorKey:"api.publishedAt",sortingFn:y,cell:({getValue:t})=>{const a=t();return a?new Date(a).toLocaleDateString():"-"}}:void 0,s?{header:p,accessorKey:"api.team"}:void 0,{id:"level",header:"Level",accessorKey:"scorecard.scorecardLevel",cell:({getValue:t,row:a})=>e.createElement($,{level:t(),colorVariable:z(a.original?.scorecard.scorecardLevelIdx,i.length+1)})},...i.map(t=>({id:t,header:`${t}`,accessorKey:"scorecard.levels",sortingFn:(a,d,o)=>{const f=a.getValue(o)[o].uniqueErrors,v=d.getValue(o)[o].uniqueErrors,n=a.getValue(o)[o].uniqueWarnings,h=d.getValue(o)[o].uniqueWarnings;return f===v?n-h:f-v},cell:({getValue:a,row:{original:d}})=>{const o=a(),f=d.api.link;return o?.[t]?e.createElement(re,{key:f,uniqueErrors:o[t].uniqueErrors,uniqueWarnings:o[t].uniqueWarnings,customDisplay:o[t].customDisplay,id:f}):null}}))].filter(W),[y,i,u.pathname,r,s,p]);return e.createElement(P,{columns:E,data:m,sortBy:[{id:"title",desc:!1}]})}function Re(g){const u=K(),{data:m}=g,i=b(()=>[{header:"Rules",accessorKey:"ruleId",cell:({getValue:r})=>e.createElement(T,{to:I(u.pathname)+"/rules/"+encodeURIComponent(r())},r())},{id:"status",header:"Status",accessorKey:"status",size:200,cell:({row:r})=>e.createElement(G,{errors:r.original.errorApisCount,warnings:r.original.warningApisCount})},{header:"Problem APIs",width:200,accessorKey:"apisCount",cell:({getValue:r})=>r(),sortDescFirst:!0},{header:"Problem count",size:200,accessorKey:"count",sortDescFirst:!0}],[u.pathname]);return e.createElement(P,{columns:i,data:m,virtualized:!1,sortBy:[{id:"status",desc:!0}]})}function ze(g){const{data:u,levelNames:m,filters:i,setActiveTab:r,teamLabel:s,teamProperty:p}=g,y=b(()=>[{id:"team",header:`API ${s}`,accessorKey:"team",size:200,cell:({getValue:E})=>e.createElement("a",{href:"#",onClick:t=>{t.preventDefault(),r("apis"),i.find(a=>a.property===p)?.selectOption(E())}},E())},...[te,...m].map(E=>({id:E,header:`${E}`,accessorFn:t=>t.levels[E]?.apis}))],[i,m,r,s,p]);return e.createElement(P,{columns:y,data:u,sortBy:[{id:"team",desc:!1}],groupHeaderTitle:"APIs by level"})}function me(g){const{data:u,title:m}=g,i=b(()=>[{id:"expand",maxSize:40,size:40,header:()=>null,enableSorting:!1,cell:({row:r})=>r.getCanExpand()?e.createElement(w,{onClick:r.getToggleExpandedHandler(),variant:"text",size:"medium",icon:r.getIsExpanded()?e.createElement(O,null):e.createElement(V,null)}):null},{header:"Rules",accessorKey:"ruleId",cell:({getValue:r,row:s})=>s.getCanExpand()?e.createElement("span",{onClick:s.getToggleExpandedHandler()},r()):null},{header:"Status",accessorKey:"status",size:200,cell:({getValue:r})=>{const s=r();return e.createElement(G,{errors:s?.errorsCount,warnings:s?.warningsCount})},enableSorting:!1},{header:"Problem count",accessorKey:"problemsCount",size:200,sortDescFirst:!0}],[]);return e.createElement(P,{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,m)," level rules"),subRowKey:"problems"})}function Ie(g){const{catalogSlug:u,slug:m,data:i,hasTeam:r,hasPublishedAt:s,teamLabel:p}=g,{apis:y,apisCount:E,warningApisCount:t,errorApisCount:a,levels:d,count:o}=i,f=b(()=>Object.values(y),[y]),v=f.length===0,n=v?void 0:{id:"expand",maxSize:40,size:40,header:()=>null,enableSorting:!1,cell:({row:l})=>l.getCanExpand()?e.createElement(w,{onClick:l.getToggleExpandedHandler(),variant:"text",size:"medium",icon:l.getIsExpanded()?e.createElement(O,null):e.createElement(V,null)}):null},h=b(()=>[n,{header:"API",accessorKey:"title"},s?{header:"Published at",accessorKey:"publishedAt",cell:({getValue:l})=>{const c=l();return c?new Date(c).toLocaleDateString():"-"}}:void 0,r?{header:p,accessorKey:"team",cell:({getValue:l})=>l()||ee}:void 0,{header:"Problem count",size:200,accessorKey:"count",cell:({getValue:l})=>l()||0,sortDescFirst:!0}].filter(W),[r,s,p,v]),k=b(()=>Object.entries(i.teams).sort((l,c)=>c[1]-l[1]),[i.teams]);return e.createElement(j,null,e.createElement(w,{icon:e.createElement(R,null),iconPosition:"left",variant:"ghost",size:"large",to:`${u}scorecard`},"Back to dashboard"),e.createElement("h1",null,"Rule ",m),e.createElement(B,null,e.createElement(x,null,e.createElement(L,null,"Rule status"),e.createElement(M,null,e.createElement("div",null,e.createElement(S,null,E),e.createElement("br",null),"APIs"),e.createElement("div",null,e.createElement(A,null,e.createElement(S,{style:{textAlign:"right"}},E-t-a),e.createElement(D,{severity:"Pass"})),e.createElement(A,null,e.createElement(S,{style:{textAlign:"right"}},t),e.createElement(D,{severity:"Warn"})),e.createElement(A,null,e.createElement(S,{style:{textAlign:"right"}},a),e.createElement(D,{severity:"Error"}))))),e.createElement(x,null,e.createElement(L,null,"Problems by level"),e.createElement(q,null,Object.entries(d).map(([l,c])=>e.createElement(F,{key:l},e.createElement("span",null,l),e.createElement(ie,{chunks:[{share:c.errors/o*100,colorVariable:"--scorecard-color-error"},{share:c.warnings/o*100,colorVariable:"--scorecard-color-warning"}]}),e.createElement(ue,null,c.errors+c.warnings))))),e.createElement(x,null,e.createElement(L,null,`Problems by ${p}`),e.createElement(q,null,k.slice(0,4).map(([l,c])=>e.createElement(F,{key:l},e.createElement("span",{style:{flex:1,textAlign:"left"}},l),e.createElement(S,null,c)))))),e.createElement(P,{columns:h,data:f,sortBy:[{id:"title",desc:!1}],subRowKey:"problems",slug:m}))}function We(g){const{slug:u,api:m,teamLabel:i,catalogSlug:r}=g,{api:s}=m||{},{scorecard:p,isLoading:y}=oe(`/${u}`),{processScorecard:E}=N(),t=p&&E(p,m.api),a=t?.levels||{},[d,o]=U(Object.keys(a)[0]),f=b(()=>s?.publishedAt instanceof Date?s?.publishedAt.toLocaleDateString():s?.publishedAt,[s]);Z(()=>{if(t){const n=t.levels||{};o(Object.keys(n)[0])}},[p]);const v=b(()=>{if(!t?.levels)return{};const n={};for(const h of Object.keys(t.levels)){const k=t.levels[h].problems.reduce((l,c)=>(l[c.ruleId]||(l[c.ruleId]=[]),l[c.ruleId].push(c),l),{});n[h]=Object.entries(k).map(([l,c])=>({ruleId:l,problems:[...c.filter(C=>C.severity==="error"),...c.filter(C=>C.severity==="warn")],problemsCount:c.length,status:{errorsCount:c.filter(C=>C.severity==="error").length,warningsCount:c.filter(C=>C.severity==="warn").length}}))}return n},[t?.levels]);return y?e.createElement(J,{justifyContent:"center",mt:"2em"},e.createElement(Q,null)):t?e.createElement(j,null,e.createElement(w,{icon:e.createElement(R,null),iconPosition:"left",variant:"ghost",size:"large",to:`${r}scorecard`},"Back to dashboard"),e.createElement("h1",null,s?.title||u),e.createElement(ne,null,f&&e.createElement(e.Fragment,null,"Published at: ",new Date().toLocaleString(void 0,{timeZoneName:"short"}),e.createElement("br",null)),e.createElement(T,{to:s?.link,external:!0},"Documentation")),e.createElement(B,null,e.createElement(x,null,e.createElement(ce,null,e.createElement("span",null,"Scorecard level"),e.createElement($,{level:t.scorecardLevel,colorVariable:z(t.scorecardLevelIdx,Object.keys(a).length)})),e.createElement(M,null,e.createElement("div",null,"Compliance by level"),e.createElement("div",null,Object.entries(t.levels).map(([n,h])=>e.createElement(A,{key:n},e.createElement(S,{style:{width:"100px",textAlign:"right"}},n),e.createElement(H,{errors:h.errors,warnings:h.warnings})))))),e.createElement(Y,{title:"Rules compliance",levels:Object.entries(t.levels).map(([n,h])=>({errors:h.uniqueErrors,warnings:h.uniqueWarnings,total:g.rulesPerLevel[n].length,name:n}))}),e.createElement(x,null,e.createElement(L,null,i),e.createElement(S,{style:{fontWeight:"normal"}},s?.team))),e.createElement(le,{style:{justifyContent:"flex-start"},"data-component-name":"Scorecard/ModeSwitcherTabs"},Object.keys(t.levels).map(n=>e.createElement(ae,{"data-component-name":"Scorecard/ModeSwitcherTab",key:n,isActive:d===n,onClick:()=>o(n)},e.createElement(A,null,e.createElement("span",null,n)," ",e.createElement(H,{errors:t.levels[n].errors,warnings:t.levels[n].warnings}))))),Object.keys(a).map(n=>e.createElement(se,{key:n,isActive:d===n},e.createElement(me,{title:n,data:v[n]})))):e.createElement("div",null,"Scorecard not found")}export{Oe as ApiListView,We as ApiPage,me as ApiView,Ie as RuleView,Re as RulesView,ze as TeamsView};
@@ -1,9 +1,9 @@
1
1
  import type { NormalizedProblem } from '@redocly/openapi-core';
2
2
  import type { ProblemWithCodeframe } from './lint';
3
3
  export declare enum ScorecardStatus {
4
- BelowMinimum = "Below minimum",
5
- Highest = "Highest",
6
- Minimum = "Minimum"
4
+ BelowMinimum = "BELOW_MINIMUM",
5
+ Highest = "HIGHEST",
6
+ Minimum = "MINIMUM"
7
7
  }
8
8
  export type ProblemSummary = Pick<NormalizedProblem, 'ruleId' | 'severity'>;
9
9
  export type ScorecardLevel = {
@@ -25,6 +25,8 @@ export type ScorecardData = {
25
25
  relativePath: string;
26
26
  title?: string;
27
27
  version?: string;
28
+ hash: string;
29
+ detailsChunkPath?: string;
28
30
  };
29
31
  export type DetailedScorecardData = Omit<ScorecardData, 'levels'> & {
30
32
  levels: Record<string, DetailedScorecardLevel>;
@@ -1 +1 @@
1
- var m;(function(i){i.BelowMinimum="Below minimum",i.Highest="Highest",i.Minimum="Minimum"})(m||(m={}));export{m as ScorecardStatus};
1
+ var i;(function(M){M.BelowMinimum="BELOW_MINIMUM",M.Highest="HIGHEST",M.Minimum="MINIMUM"})(i||(i={}));export{i as ScorecardStatus};
@@ -0,0 +1,12 @@
1
+ import type { DatabaseClient } from '../../../../../providers/database/client.js';
2
+ import type { DatabaseScorecardsConfig, DatabaseScorecardsConfigDto } from '../../../../../providers/database/databases/main-sqlite/schemas/scorecards-config-table.js';
3
+ export declare class ScorecardsConfigLocalRepository {
4
+ #private;
5
+ constructor(db: DatabaseClient);
6
+ findActiveConfigByKey(key: string): Promise<DatabaseScorecardsConfig | null>;
7
+ findAllActiveConfigs(): Promise<DatabaseScorecardsConfig[]>;
8
+ insertConfig(config: DatabaseScorecardsConfigDto): Promise<DatabaseScorecardsConfig>;
9
+ updateConfigById(id: string, updates: Partial<Omit<DatabaseScorecardsConfigDto, 'id' | 'createdAt'>>): Promise<DatabaseScorecardsConfig>;
10
+ archiveConfigById(id: string, archivedAt: string): Promise<DatabaseScorecardsConfig>;
11
+ }
12
+ //# sourceMappingURL=scorecards-config-local-repository.d.ts.map
@@ -0,0 +1 @@
1
+ import{and as o,eq as n,isNull as s}from"drizzle-orm";import{scorecardsConfigTable as r}from"../../../../../providers/database/databases/main-sqlite/schemas/scorecards-config-table.js";class d{#e;constructor(e){this.#e=e}async findActiveConfigByKey(e){return(await this.#e.client.select().from(r).where(o(n(r.key,e),s(r.archivedAt))).limit(1))[0]??null}async findAllActiveConfigs(){return await this.#e.client.select().from(r).where(s(r.archivedAt))}async insertConfig(e){const t=await this.#e.client.insert(r).values(e).returning();if(!t[0])throw new Error(`Failed to insert scorecard config with key: ${e.key}`);return t[0]}async updateConfigById(e,t){const i=await this.#e.client.update(r).set(t).where(n(r.id,e)).returning();if(!i[0])throw new Error(`Failed to update scorecard config with id: ${e}`);return i[0]}async archiveConfigById(e,t){const i=await this.#e.client.update(r).set({archivedAt:t}).where(n(r.id,e)).returning();if(!i[0])throw new Error(`Failed to archive scorecard config with id: ${e}`);return i[0]}}export{d as ScorecardsConfigLocalRepository};
@@ -0,0 +1,11 @@
1
+ import type { ScorecardsConfig } from '@redocly/config';
2
+ import type { ServiceInstanceOptions } from '../../../providers/database/types.js';
3
+ import { DatabaseConnectionFactory } from '../../../providers/database/database-connection-factory.js';
4
+ import { BaseRepository } from '../../../providers/database/base-repository.js';
5
+ export declare class ScorecardsConfigService extends BaseRepository {
6
+ #private;
7
+ constructor(dbConnection: Awaited<ReturnType<typeof DatabaseConnectionFactory.create>>);
8
+ static getInstance(options: ServiceInstanceOptions): Promise<ScorecardsConfigService>;
9
+ syncConfig(scorecardsConfig: ScorecardsConfig, onConfigChange?: (key: string) => Promise<void>): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=scorecards-config-service.d.ts.map
@@ -0,0 +1 @@
1
+ import{ulid as g}from"ulid";import{logger as r}from"../../../tools/notifiers/logger.js";import{DatabaseConnectionFactory as l}from"../../../providers/database/database-connection-factory.js";import{BaseRepository as d}from"../../../providers/database/base-repository.js";import{shaHex as h}from"../../../utils/crypto/sha-hex.js";import{hasOptionsChanged as m}from"../../../plugins/catalog-entities/utils/has-options-changed.js";import{slug as y}from"../../../utils/slugger.js";import{withTimestamp as f}from"../../../utils/time/with-timestamp.js";import{ScorecardsConfigLocalRepository as p}from"./repositories/local/scorecards-config-local-repository.js";class o extends d{static#i;static#e;#t;constructor(t){if(!t)throw new Error("Database connection is required for ScorecardsConfigService");super(t),this.#t=new p(this.databaseClient)}static async getInstance(t){const i=m(o.#e,t);if(!o.#i||i){const n=await l.create("main-local",t);if(!n)throw new Error("Failed to create db connection for scorecards config service");o.#i=new o(n),o.#e=t}return o.#i}async syncConfig(t,i){const n=new Set;(!Array.isArray(t)||t.length===0)&&r.verbose("No scorecard configs to sync"),r.verbose(`Starting scorecard config sync for ${t.length} config(s)`);for(const s of t)try{const e=s.key;if(!/^[a-z0-9-]+$/i.test(e)){r.error(`Skipping invalid scorecard config item: key "${e}" does not match kebab-case format (letters, numbers, and dashes only)`,{scorecard:s});continue}n.add(e);const a=this.#s(s),c=await this.#t.findActiveConfigByKey(e);if(c){if(c.configHash===a){r.verbose(`Config "${e}" unchanged, skipping update`);continue}r.verbose(`Updating config "${e}"`),await this.#r(c.id,s,a)}else r.verbose(`Inserting new config "${e}"`),await this.#n(e,s,a);i&&await i(e)}catch(e){r.error("Error processing scorecard config item:",{error:e.message??e,scorecard:s})}await this.#o(n),r.verbose("Sync scorecard configuration: success")}#s(t){const i=JSON.stringify({entities:t.entities,levels:t.levels});return h(i)}async#n(t,i,n){await this.#t.insertConfig(f({id:`sc_${g()}`,key:t,slug:y(t),name:i.name,description:i.description??null,entitiesFilter:JSON.stringify(i.entities),levels:JSON.stringify(i.levels),configHash:n,archivedAt:null}))}async#r(t,i,n){const s=f({entitiesFilter:JSON.stringify(i.entities),levels:JSON.stringify(i.levels),configHash:n,archivedAt:null},{fields:["updatedAt"]});await this.#t.updateConfigById(t,s)}async#o(t){const i=await this.#t.findAllActiveConfigs(),n=new Date().toISOString();for(const s of i)if(!t.has(s.key)){r.verbose(`Archiving removed config "${s.key}"`);try{await this.#t.archiveConfigById(s.id,n)}catch(e){r.error(`Error archiving config item "${s.key}":`,e.message??e)}}}}export{o as ScorecardsConfigService};
@@ -1 +1 @@
1
- import{SCORECARDS_BASE_SLUG as a,SCORECARDS_TEMPLATE_ID as i}from"../../constants/plugins/scorecards.js";import{getTemplatePath as n}from"./utils/get-template-path.js";import{telemetryTraceStep as d}from"../../../cli/telemetry/helpers/trace-step.js";async function l(){return{id:"Scorecards",requiredEntitlements:["scorecards"],async processContent(e,r){await d("build.plugin.scorecards",async o=>{if(process.env.NEW_SCORECARDS_ENABLED!=="true")return;const t=(await r.getConfig()).scorecards;o?.setAttribute("config",JSON.stringify(t));const{logger:s}=r;s.info("Scorecards plugin started");const c=e.createTemplate(i,n("../template/index.js"));e.addRoute({duplicateInAllLocales:!0,slug:a,fsPath:"",templateId:c,excludeFromSidebar:!0,hasClientRoutes:!0,getNavText:()=>Promise.resolve("Scorecards"),getStaticData:async()=>({props:{scorecardsConfig:t}})}),s.info("Scorecards plugin finished")})}}}var S=l;export{S as default,l as scorecardsPlugin};
1
+ import{envConfig as c}from"../../../config/env-config.js";import{SCORECARDS_BASE_SLUG as i,SCORECARDS_TEMPLATE_ID as n}from"../../constants/plugins/scorecards.js";import{getTemplatePath as d}from"./utils/get-template-path.js";import{telemetryTraceStep as l}from"../../../cli/telemetry/helpers/trace-step.js";async function u(){return{id:"Scorecards",requiredEntitlements:["scorecards"],async processContent(e,r){await l("build.plugin.scorecards",async s=>{if(c.NEW_SCORECARDS_ENABLED!=="true")return;const t=(await r.getConfig()).scorecards;s?.setAttribute("config",JSON.stringify(t));const{logger:o}=r;o.info("Scorecards plugin started");const a=e.createTemplate(n,d("../template/index.js"));e.addRoute({duplicateInAllLocales:!0,slug:i,fsPath:"",templateId:a,excludeFromSidebar:!0,hasClientRoutes:!0,getNavText:()=>Promise.resolve("Scorecards"),getStaticData:async()=>({props:{scorecardsConfig:t}})}),o.info("Scorecards plugin finished")})}}}var C=u;export{C as default,u as scorecardsPlugin};
@@ -1,2 +1,3 @@
1
- export declare function runScorecardsWorker(baseDbDir: string): Promise<void>;
1
+ import type { ScorecardsConfig } from '@redocly/config';
2
+ export declare function runScorecardsWorker(baseDbDir: string, scorecardsConfig: ScorecardsConfig): Promise<void>;
2
3
  //# sourceMappingURL=run-scorecards-worker.d.ts.map
@@ -1 +1 @@
1
- import{SCORECARDS_WORKER_KEY as n,scorecardsWorker as i}from"../../../workers/scorecards-worker-pool.js";import{logger as r}from"../../../tools/notifiers/logger.js";const c=5;async function t(s,e){try{const o=await i.exec(n,[{baseDbDir:s,pollingIntervalMs:parseInt(process.env.SCORECARDS_POLLING_INTERVAL_MS||"3000",10)}]);return o.success?r.info(`${o.message}`):r.error(`Scorecards Worker error (attempt ${e}/${c}):`,o.error),Promise.resolve()}catch(o){r.error(`Scorecards Worker execution failed (attempt ${e}/${c}):`,o)}return e<c?(r.info(`Retrying Scorecards Worker (attempt ${e+1}/${c})...`),t(s,e+1)):(r.error(`All ${c} attempts failed. Scorecards Worker could not be started.`),Promise.resolve())}async function l(s){return r.info("Starting continuous Scorecards Worker..."),t(s,1)}export{l as runScorecardsWorker};
1
+ import{SCORECARDS_WORKER_KEY as f,scorecardsWorker as m}from"../../../workers/scorecards-worker-pool.js";import{logger as e}from"../../../tools/notifiers/logger.js";import{envConfig as u}from"../../../../config/env-config.js";const o=5;async function n(s){const{baseDbDir:c,scorecardsConfig:a,attempt:t}=s;try{const r=await m.exec(f,[{baseDbDir:c,scorecardsConfig:a,pollingIntervalMs:parseInt(u.SCORECARDS_POLLING_INTERVAL_MS||"3000",10)}]);if(r.success)return e.info(`${r.message}`),Promise.resolve();e.error(`Execute Scorecards Worker: failed (attempt ${t}/${o}): ${r.error}`)}catch(r){const i=r instanceof Error?r.message:String(r);e.error(`Execute Scorecards Worker: failed (attempt ${t}/${o}): ${i}`)}return t<o?(e.info(`Execute Scorecards Worker: retrying... (attempt ${t+1}/${o})`),n({baseDbDir:c,scorecardsConfig:a,attempt:t+1})):(e.error(`Execute Scorecards Worker: failed. Scorecards Worker could not be started after all ${o} attempts`),Promise.resolve())}async function p(s,c){return e.info("Start Scorecards Worker: executing..."),n({baseDbDir:s,scorecardsConfig:c,attempt:1})}export{p as runScorecardsWorker};
@@ -1,14 +1,3 @@
1
- export type ScorecardsWorkerParams = {
2
- baseDbDir: string;
3
- pollingIntervalMs?: number;
4
- };
5
- export type ScorecardsWorkerResponse = {
6
- success: true;
7
- message: string;
8
- } | {
9
- success: false;
10
- message: string;
11
- error: string;
12
- };
1
+ import type { ScorecardsWorkerParams, ScorecardsWorkerResponse } from '../../../types/plugins/scorecards.js';
13
2
  export declare function startScorecardsWorker(params: ScorecardsWorkerParams): Promise<ScorecardsWorkerResponse>;
14
3
  //# sourceMappingURL=scorecards.d.ts.map
@@ -1 +1 @@
1
- import{logger as o}from"../../../tools/notifiers/logger.js";import{loadEnvVariables as l}from"../../../utils/envs/load-env-variables.js";import{CatalogEntitiesService as d}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";const u=3e3;async function y(s){try{const{baseDbDir:r,pollingIntervalMs:a=u}=s;l(r),o.verbose(`Initializing Scorecards Worker: polling interval ${a}ms (${a/1e3}s)`);const t=await d.getInstance({baseDbDir:r});return g(t,a),{success:!0,message:"Scorecards Worker started successfully"}}catch(r){const a=r instanceof Error?r.message:String(r);return o.error("Failed to start Scorecards Worker:",r),{success:!1,message:"Failed to start Scorecards Worker",error:a}}}async function g(s,r){let a=0,t=null;return t=setInterval(n,r),new Promise(()=>{});async function c(e){return e&&(await s.updateEntityScorecardsStatus(e.id,"CALCULATING"),await new Promise(i=>{setTimeout(async()=>{i()},1)}),await s.updateEntityScorecardsStatusIfCalculating(e.id,"UP_TO_DATE")?o.verbose(`Catalog Entity (${e.key}) scorecard evaluation completed successfully`):(await s.updateEntityScorecardsStatus(e.id,"OUTDATED"),o.verbose(`Catalog Entity (${e.key}) was updated during calculation, scorecard evaluation in not applicable anymore`))),Promise.resolve()}async function n(){try{a++;const e=await s.getOutdatedEntity();if(!e)return t||(o.verbose(`\u{1F50D} Resuming normal polling interval ${r}ms (${r/1e3}s)`),t=setInterval(n,r)),Promise.resolve();o.verbose(`\u{1F50D} Poll #${a} in Scorecards Worker: found Catalog Entity (${e.key}) for scorecard evaluation`),t&&(clearInterval(t),t=null,o.verbose(`\u{1F50D} Stopping normal polling while processing Catalog Entity (${e.key}) for scorecard evaluation`)),await c(e),await n()}catch(e){o.error("Error during poll in Scorecards Worker:",e),t||(t=setInterval(n,r))}}}export{y as startScorecardsWorker};
1
+ import{logger as o}from"../../../tools/notifiers/logger.js";import{loadEnvVariables as g}from"../../../utils/envs/load-env-variables.js";import{CatalogEntitiesService as S}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";import{ScorecardsConfigService as y}from"../../../plugins/scorecards/database/scorecards-config-service.js";import{transformEntitiesToFilter as v}from"../../../providers/database/pagination/entities-to-filter.js";const m=3e3;let c=null;async function C(i){try{const{baseDbDir:r,scorecardsConfig:t,pollingIntervalMs:a=m}=i;o.verbose(`Start Scorecards Worker: initializing (polling interval ${a}ms)`);const n=await y.getInstance({baseDbDir:r}),d=await S.getInstance({baseDbDir:r});await g(r);const s=p(t);return await E({scorecardsConfig:t,entitiesFilters:s,entitiesService:d,configService:n}),P({pollingIntervalMs:a,scorecardsConfig:t,entitiesFilters:s,entitiesService:d}),{success:!0,message:"Start Scorecards Worker: success"}}catch(r){return c&&(clearInterval(c),c=null),{success:!1,message:"Start Scorecards Worker: failed",error:r instanceof Error?r.message:String(r)}}}function p(i){const r={};for(const t of i)r[t.key]=v(t.entities);return r}async function E(i){const{configService:r,scorecardsConfig:t,entitiesFilters:a,entitiesService:n}=i,d=async s=>{await n.setEntitiesAsOutdated(a[s]),o.verbose(`Update entities as outdated: success (scorecard ${s})`)};try{await r.syncConfig(t,d),o.verbose("Sync scorecard configuration: success")}catch(s){const e=s instanceof Error?s.message:String(s);o.error(`Sync scorecard configuration: failed (${e})`)}}async function P(i){const{scorecardsConfig:r,pollingIntervalMs:t,entitiesFilters:a,entitiesService:n}=i;return c=setInterval(s,t),new Promise(()=>{});async function d(e,l){return await n.updateEntityScorecardsStatus(e.id,"CALCULATING"),await new Promise(u=>{setTimeout(async()=>{u()},1)}),await n.updateEntityScorecardsStatusIfCalculating(e.id,"UP_TO_DATE")?o.verbose(`Process entity scorecard: success (entity ${e.key}, scorecard ${l})`):(await n.updateEntityScorecardsStatus(e.id,"OUTDATED"),o.verbose(`Process entity scorecard: entity updated during calculation (entity ${e.key})`)),Promise.resolve()}async function s(){try{for(const e of r){const l=a[e.key];if(!l){o.warn(`Process scorecard: filter not found (scorecard ${e.key})`);continue}const f=await n.getOutdatedEntities(l);if(f.length===0){o.verbose(`Poll scorecards: no entities found for scorecard ${e.key}`);continue}o.verbose(`Poll scorecards: found ${f.length} entity(ies) for scorecard ${e.key}`),c&&(clearInterval(c),c=null,o.verbose(`Poll scorecards: stopped (processing ${f.length} entity(ies) for scorecard ${e.key})`));for(const u of f)await d(u,e.key)}c||(o.verbose(`Poll scorecards: resumed (interval ${t}ms)`),c=setInterval(s,t))}catch(e){const l=e instanceof Error?e.message:String(e);o.error(`Poll scorecards: failed (${l})`),c||(c=setInterval(s,t))}}}export{C as startScorecardsWorker};
@@ -1 +1 @@
1
- import p from"node:path";import{existsSync as b}from"node:fs";import{writeFile as x,access as v,rm as N,constants as X}from"fs/promises";import{REDOCLY_ROUTE_RBAC as S,REDOCLY_TEAMS_RBAC as D}from"@redocly/config";import $ from"picomatch";import{DEFAULT_LOCALE_PLACEHOLDER as _}from"../../../../constants/common.js";import{AI_INDEX_EXPORT_FOLDER as j}from"../../../constants/plugins/search.js";import{LLMS_TXT_FILE_NAME as k}from"../../../constants/common.js";import{isBuildMode as B}from"../../../utils/envs/is-build-mode.js";import{logger as a}from"../../../tools/notifiers/logger.js";import{shaHexShort as G}from"../../../utils/crypto/sha-hex-short.js";import{promiseMapLimit as M}from"../../../utils/async/promise-map-limit.js";import{ensureDir as A}from"../../../utils/fs.js";import{isResourcePubliclyAccessible as H,extractTeamsForSearch as U,getRbacTeamsForSearch as Y}from"../../../utils/rbac.js";import{validateLLMsTxtConfig as J,generateLLMsTxt as K,getLLMsTxtMdSlug as V}from"../llmstxt/index.js";const P=20,R="llms.txt:";async function pt(t,i,{aiSearchEnabled:e,llmstxtEnabled:r}){const s=p.join(t.outdir,k);if(!r){try{await v(s,X.W_OK),await N(s)}catch{}if(!e)return}e&&a.info("Preparing AI search documents..."),r&&a.info(`${R} Generating llms.txt files...`);const L=a.startTiming(),c=a.startTiming(),f=t.getGlobalConfig("seo"),l=f?.llmstxt,T=p.resolve(t.outdir,j),u=t.getConfig(),w=u.rbac??{},C=t.getAllRoutes(),F=u?.l10n?.defaultLocale||u?.i18n?.defaultLocale||_,O=(l?.excludeFiles||[]).map(o=>$(o)),d=[];if(await M(C,P,async o=>{if(o.excludeFromSearch)return;const y=await W(o,t),h=await q(o,y,i,t);if(h){if(r)for(const n of await h.getLLMsTxts()){if(O.some(m=>m(n.fsPath)))continue;const g=p.join(t.outdir,V(n.slug));A(g),await x(g,n.content),n.includeInLLMsTxt&&H(o,u)&&d.push(n)}if(e&&B()){const n=await h.getSearchDocuments();if(!n.length)return;const g=z(o,w),m=o.versions?.find(({active:I})=>I),E=m&&{folder:m.folderId,label:m.label,default:m.default};await Q(n,o.fsPath,g,T,F,E)}}}),e&&a.infoTime(c,"AI search documents prepared"),d.length)try{J(l);const o=await K(d,l,{title:f?.title,description:f?.description},i);A(s),await x(s,o),a.infoTime(L,`${R} files generated`)}catch(o){a.error(`${R} Failed to generate llms.txt file. ${o.message}`)}}async function W(t,i){return t.getStaticData?t.getStaticData(t,{...i,contentDir:i.contentDir,parseMarkdoc:(e,r,s)=>i.parseMarkdoc(e,r,s)}):{}}async function q(t,i,e,r){if(t.getAiDocumentsStore)return t.getAiDocumentsStore(t,{...i,[D]:t[D],[S]:t[S]},e,r)}function z(t,i){const e=U(t?.[D]);return e?.length?e:Y(t,i)}async function Q(t,i,e,r,s,L){await M(t,P,async c=>{const f=`${G(i+c.content)}.json`,l=A(p.join(r,f)),T=c.locale===_?s:c.locale;b(l)||await x(l,JSON.stringify({...c,rbacTeams:e||[],version:L,locale:T}),"utf-8")})}export{pt as prepareAiSearchDocuments};
1
+ import L from"node:path";import{existsSync as b}from"node:fs";import{writeFile as x,access as $,rm as N,constants as X}from"fs/promises";import{REDOCLY_ROUTE_RBAC as _,REDOCLY_TEAMS_RBAC as A}from"@redocly/config";import j from"picomatch";import{DEFAULT_LOCALE_PLACEHOLDER as M}from"../../../../constants/common.js";import{AI_INDEX_EXPORT_FOLDER as k}from"../../../constants/plugins/search.js";import{LLMS_TXT_FILE_NAME as B}from"../../../constants/common.js";import{envConfig as w}from"../../../../config/env-config.js";import{logger as a}from"../../../tools/notifiers/logger.js";import{shaHexShort as G}from"../../../utils/crypto/sha-hex-short.js";import{promiseMapLimit as C}from"../../../utils/async/promise-map-limit.js";import{ensureDir as R}from"../../../utils/fs.js";import{isResourcePubliclyAccessible as H,extractTeamsFromScopeItems as U,getRbacTeamsListForResource as Y}from"../../../utils/rbac.js";import{validateLLMsTxtConfig as J,generateLLMsTxt as K,getLLMsTxtMdSlug as V}from"../llmstxt/index.js";const P=20,S="llms.txt:";async function pt(t,i,{aiSearchEnabled:o,llmstxtEnabled:s}){const n=L.join(t.outdir,B);if(!s){try{await $(n,X.W_OK),await N(n)}catch{}if(!o)return}o&&a.info("Preparing AI search documents..."),s&&a.info(`${S} Generating llms.txt files...`);const d=a.startTiming(),c=a.startTiming(),f=t.getGlobalConfig("seo"),l=f?.llmstxt,T=L.resolve(t.outdir,k),u=t.getConfig(),F=u.rbac??{};let D=t.getAllRoutes();const I=u?.l10n?.defaultLocale||u?.i18n?.defaultLocale||M,y=(l?.excludeFiles||[]).map(e=>j(e)),h=[];if(w.isDevelopMode&&(D=D.slice(0,50)),await C(D,P,async e=>{if(e.excludeFromSearch)return;const E=await W(e,t);let g;try{g=await q(e,E,i,t)}catch(r){console.log(r),a.warn(`Error generating AI search documents for route ${e.slug}`)}if(g){if(s)for(const r of await g.getLLMsTxts()){if(y.some(m=>m(r.fsPath)))continue;const p=L.join(t.outdir,V(r.slug));R(p),await x(p,r.content),r.includeInLLMsTxt&&H(e,u)&&h.push(r)}if(o&&w.isBuildMode){const r=await g.getSearchDocuments();if(!r.length)return;const p=z(e,F),m=e.versions?.find(({active:v})=>v),O=m&&{folder:m.folderId,label:m.label,default:m.default};await Q(r,e.fsPath,p,T,I,O)}}}),o&&a.infoTime(c,"AI search documents prepared"),h.length)try{J(l);const e=await K(h,l,{title:f?.title,description:f?.description},i);R(n),await x(n,e),a.infoTime(d,`${S} files generated`)}catch(e){a.error(`${S} Failed to generate llms.txt file. ${e.message}`)}}async function W(t,i){return t.getStaticData?t.getStaticData(t,{...i,contentDir:i.contentDir,parseMarkdoc:(o,s,n)=>i.parseMarkdoc(o,s,n)}):{}}async function q(t,i,o,s){if(t.getAiDocumentsStore)return t.getAiDocumentsStore(t,{...i,[A]:t[A],[_]:t[_]},o,s)}function z(t,i){const o=U(t?.[A]);return o?.length?o:Y(t,i)}async function Q(t,i,o,s,n,d){await C(t,P,async c=>{const f=`${G(i+c.content)}.json`,l=R(L.join(s,f)),T=c.locale===M?n:c.locale;b(l)||await x(l,JSON.stringify({...c,rbacTeams:o||[],version:d,locale:T}),"utf-8")})}export{pt as prepareAiSearchDocuments};
@@ -1 +1 @@
1
- import{REDOCLY_ROUTE_RBAC as T,REDOCLY_TEAMS_RBAC as p}from"@redocly/config";import{existsSync as O}from"fs";import{rm as $}from"node:fs/promises";import{DEFAULT_LOCALE_PLACEHOLDER as y}from"../../../../constants/common.js";import{SEARCH_DATA_EXPORT_FOLDER as S}from"../../../constants/plugins/search.js";import{isBuildMode as A}from"../../../utils/envs/is-build-mode.js";import{logger as n}from"../../../tools/notifiers/logger.js";import{extractTeamsForSearch as M,getRbacTeamsForSearch as P}from"../../../utils/index.js";import{getSearchDocumentGroup as B}from"../utils.js";import{telemetry as I}from"../../../../cli/telemetry/index.js";import{telemetryTraceStep as _}from"../../../../cli/telemetry/helpers/trace-step.js";async function J(b,t,l){await _("build.plugin.search.prepare_search_documents",async()=>{n.info("Preparing search documents and create indexes..."),A()&&O(`${t.outdir}/${S}`)&&await $(`${t.outdir}/${S}`,{recursive:!0});const F=n.startTiming(),R=t.getConfig().rbac,v=[y,...b.localeFolders.map(a=>a.toLowerCase())];for(const a of v)await _("build.plugin.search.prepare_search_documents.locale",async s=>{const w=t.getAllRoutesForLocale(a);let g=0,h=0;for(const r of w){if(g++,r.excludeFromSearch)continue;const f=new Map,{product:m}=r,C=await r.getStaticData?.(r,{...t,contentDir:t.contentDir,parseMarkdoc:(c,e,u)=>t.parseMarkdoc(c,e,u)})||{},i=await r.getSearchDocuments?.(r,{...C,[p]:r[p],[T]:r[T]},t),o=r.versions?.find(c=>c.active),L=P(r,R??{});if(i){if(i&&i.length){h+=i.length;for(const c in i){let e=i[c];const u=M(e?.[p]),D=u?.length?u:L,x=e.tags||[];e={...e,...o&&{version:o.version,isDefaultVersion:o.default,versionFolderId:o.folderId},...m&&{product:m},rbacTeams:D,tags:[...x,...D,...o?o.default?["v:default"]:[`v:${o.folderId}:${o.version}`]:["v:default"],...m?[`p:${m.name}`]:[]],url:e.url&&(e.path&&e.path.length>1?e.url:e.url.split("#")[0])};const d=B(e.facets);if(d){const E=f.get(d)??[];f.set(d,[...E,e])}}}for(const[c,e]of f)await l.addDocuments(e,{locale:a,group:c,outDir:t.outdir})}}s?.setAttribute("locale",a),s?.setAttribute("totalDocuments",g),s?.setAttribute("totalSearchDocuments",h)});if(l.cleanupFacetValues(t),n.infoTime(F,"Search indexes created"),A()){n.info("Writing out search data...");const a=n.startTiming();await l.export(t.outdir);const s=n.infoTime(a,"Search data written");s&&I.sendTimingPerformedMessage(s)}})}export{J as prepareSearchDocuments};
1
+ import{REDOCLY_ROUTE_RBAC as R,REDOCLY_TEAMS_RBAC as D}from"@redocly/config";import{existsSync as y}from"fs";import{rm as O}from"node:fs/promises";import{DEFAULT_LOCALE_PLACEHOLDER as $}from"../../../../constants/common.js";import{SEARCH_DATA_EXPORT_FOLDER as S}from"../../../constants/plugins/search.js";import{envConfig as h}from"../../../../config/env-config.js";import{logger as c}from"../../../tools/notifiers/logger.js";import{extractTeamsFromScopeItems as P,getRbacTeamsListForResource as I}from"../../../utils/index.js";import{getSearchDocumentGroup as k}from"../utils.js";import{telemetry as B}from"../../../../cli/telemetry/index.js";import{telemetryTraceStep as v}from"../../../../cli/telemetry/helpers/trace-step.js";async function K(A,t,l){await v("build.plugin.search.prepare_search_documents",async()=>{c.info("Preparing search documents and create indexes..."),h.isBuildMode&&y(`${t.outdir}/${S}`)&&await O(`${t.outdir}/${S}`,{recursive:!0});const _=c.startTiming(),F=t.getConfig().rbac,C=[$,...A.localeFolders.map(a=>a.toLowerCase())];let f=1/0;h.isDevelopMode&&(f=50);let d=0;for(const a of C)await v("build.plugin.search.prepare_search_documents.locale",async s=>{const L=t.getAllRoutesForLocale(a);let T=0,w=0;for(const r of L){if(d>=f)break;if(d++,T++,r.excludeFromSearch)continue;const p=new Map,{product:n}=r,x=await r.getStaticData?.(r,{...t,contentDir:t.contentDir,parseMarkdoc:(e,i,u)=>t.parseMarkdoc(e,i,u)})||{},m=await r.getSearchDocuments?.(r,{...x,[D]:r[D],[R]:r[R]},t),o=r.versions?.find(e=>e.active),E=I(r,F??{});if(m){if(m&&m.length)for(let e of m){const i=P(e?.[D]),u=i?.length?i:E,M=e.tags||[];e={...e,...o&&{version:o.version,isDefaultVersion:o.default,versionFolderId:o.folderId},...n&&{product:n},rbacTeams:u,tags:[...M,...u,...o?o.default?["v:default"]:[`v:${o.folderId}:${o.version}`]:["v:default"],...n?[`p:${n.name}`]:[]],url:e.url&&(e.path&&e.path.length>1?e.url:e.url.split("#")[0])};const g=k(e.facets);if(g){const b=p.get(g)??[];b.push(e),p.set(g,b)}}if(d>=f)break;for(const[e,i]of p)await l.addDocuments(i,{locale:a,group:e,outDir:t.outdir})}}s?.setAttribute("locale",a),s?.setAttribute("totalDocuments",T),s?.setAttribute("totalSearchDocuments",w)});if(l.cleanupFacetValues(t),c.infoTime(_,"Search indexes created"),h.isBuildMode){c.info("Writing out search data...");const a=c.startTiming();await l.export(t.outdir);const s=c.infoTime(a,"Search data written");s&&B.sendTimingPerformedMessage(s)}})}export{K as prepareSearchDocuments};
@@ -1 +1 @@
1
- import{readFile as R,readdir as y,appendFile as E}from"node:fs/promises";import m from"node:path";import{existsSync as w}from"node:fs";import{SEARCH_GROUP_FACET_FIELD as F,SEARCH_PRODUCT_FIELD as C,SEARCH_VERSION_FIELD as $}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as A,SEARCH_DATA_EXPORT_FOLDER as _,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as O}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as v}from"../../../../telemetry/helpers/trace-step.js";import{isBuildMode as N}from"../../../../utils/envs/is-build-mode.js";import{ensureDir as h}from"../../../../utils/index.js";import{FlexSearchIndex as j}from"./search-index.js";class J{#e=new Map;#s;#t=0;async initIndexSchema(t){this.#s={document:{id:"id",tag:"tags",index:A},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#o(t,o){const e=this.#e.get(t);if(e)return e.find(n=>n.id===o)}#n(t,o){let e=this.#o(t,o);return e||(e=new j(o,this.#s),this.#e.set(t,[...this.#e.get(t)??[],e])),e}async addDocuments(t,o){if(t.length){const{group:e,locale:n,outDir:c}=o,i=this.#n(n,e);for(const a of t)i.add(a),N()&&(this.#t++,this.#t>=O&&await this.exportDocuments(c))}}getIndexesSize(){return this.#e.size}async search(t,o){return await v("search",async e=>{const{query:n,locale:c,filter:i,loadMore:a,auth:f}=t,l=this.#e.get(c)??[];let r=[],d="",x=["v:default"];if(e?.setAttribute("locale",c),i)for(const s of i)s.field===F?r=[...r,...s.values]:s.field===C?d=`p:${s.values[0]}`:s.field===$&&s.values.length&&s.values.length===2&&(x=[...x,`v:${s.values[0]}:${s.values[1]}`]);const g={auth:f,query:n,offset:0,SEARCH_GROUP_FACET_FIELD:F,product:d,versions:x},p=[];let u={facets:{},documents:{}};if(a){const s=this.#o(c,a.groupKey);s&&p.push(s.search({...g,offset:a.offset}))}else for(const s of l)r&&r.length?r.includes(s.id)&&p.push(s.search(g)):p.push(s.search(g));const I=await Promise.all(p);for(const s of I){u.documents={...u.documents,...s.documents};for(const[D,S]of Object.entries(s.facets))u.facets[D]?u.facets[D]=[...u.facets[D],...S]:u.facets[D]=S}return u})}async exportDocuments(t){const o='{"documents":[',e=h(m.join(t,_));for(const[n,c]of this.#e){const i=h(m.join(e,n));for(const a of c){const f=Array.from(a.documents);if(f.length===0)continue;const l=h(m.join(i,`${a.id}.json`)),r=!w(l),d=JSON.stringify(f).substring(1).slice(0,-1),x=r?o+d:","+d;await E(l,x,{encoding:"utf8"}),a.clearDocuments()}}this.#t=0}async exportIndexes(t){const o=h(m.join(t,_));for(const[e,n]of this.#e){const c=h(m.join(o,e));for(const i of n){const a=h(m.join(c,`${i.id}.json`)),f={};await i.export((r,d)=>{f[r]=d});const l=`],"index":${JSON.stringify(f)}}`;await E(a,l,{encoding:"utf8"})}}this.#e.clear()}async import(t){const o=`${t}/${_}`,e=await y(o);for(const n of e){const c=await y(`${o}/${n}`);for(const i of c){const a=`${o}/${n}/${i}`,f=JSON.parse(await R(a,"utf-8")),l=m.parse(i).name;await this.#n(n,l).import(f)}}}countFacets(t,o){const e={};for(const[n,c]of o)e[n]=c.values.map(i=>({value:i,count:0,isCounterVisible:!1}));return e}cleanupFacetValues(t){}}export{J as FlexSearch};
1
+ import{readFile as R,readdir as y,appendFile as E}from"node:fs/promises";import m from"node:path";import{existsSync as w}from"node:fs";import{SEARCH_GROUP_FACET_FIELD as F,SEARCH_PRODUCT_FIELD as C,SEARCH_VERSION_FIELD as $}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as A,SEARCH_DATA_EXPORT_FOLDER as _,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as O}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as v}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as N}from"../../../../../config/env-config.js";import{ensureDir as h}from"../../../../utils/index.js";import{FlexSearchIndex as j}from"./search-index.js";class J{#e=new Map;#s;#t=0;async initIndexSchema(t){this.#s={document:{id:"id",tag:"tags",index:A},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#o(t,o){const e=this.#e.get(t);if(e)return e.find(n=>n.id===o)}#n(t,o){let e=this.#o(t,o);return e||(e=new j(o,this.#s),this.#e.set(t,[...this.#e.get(t)??[],e])),e}async addDocuments(t,o){if(t.length){const{group:e,locale:n,outDir:c}=o,i=this.#n(n,e);for(const a of t)i.add(a),N.isBuildMode&&(this.#t++,this.#t>=O&&await this.exportDocuments(c))}}getIndexesSize(){return this.#e.size}async search(t,o){return await v("search",async e=>{const{query:n,locale:c,filter:i,loadMore:a,auth:f}=t,l=this.#e.get(c)??[];let r=[],d="",x=["v:default"];if(e?.setAttribute("locale",c),i)for(const s of i)s.field===F?r=[...r,...s.values]:s.field===C?d=`p:${s.values[0]}`:s.field===$&&s.values.length&&s.values.length===2&&(x=[...x,`v:${s.values[0]}:${s.values[1]}`]);const g={auth:f,query:n,offset:0,SEARCH_GROUP_FACET_FIELD:F,product:d,versions:x},p=[];let u={facets:{},documents:{}};if(a){const s=this.#o(c,a.groupKey);s&&p.push(s.search({...g,offset:a.offset}))}else for(const s of l)r&&r.length?r.includes(s.id)&&p.push(s.search(g)):p.push(s.search(g));const I=await Promise.all(p);for(const s of I){u.documents={...u.documents,...s.documents};for(const[D,S]of Object.entries(s.facets))u.facets[D]?u.facets[D]=[...u.facets[D],...S]:u.facets[D]=S}return u})}async exportDocuments(t){const o='{"documents":[',e=h(m.join(t,_));for(const[n,c]of this.#e){const i=h(m.join(e,n));for(const a of c){const f=Array.from(a.documents);if(f.length===0)continue;const l=h(m.join(i,`${a.id}.json`)),r=!w(l),d=JSON.stringify(f).substring(1).slice(0,-1),x=r?o+d:","+d;await E(l,x,{encoding:"utf8"}),a.clearDocuments()}}this.#t=0}async exportIndexes(t){const o=h(m.join(t,_));for(const[e,n]of this.#e){const c=h(m.join(o,e));for(const i of n){const a=h(m.join(c,`${i.id}.json`)),f={};await i.export((r,d)=>{f[r]=d});const l=`],"index":${JSON.stringify(f)}}`;await E(a,l,{encoding:"utf8"})}}this.#e.clear()}async import(t){const o=`${t}/${_}`,e=await y(o);for(const n of e){const c=await y(`${o}/${n}`);for(const i of c){const a=`${o}/${n}/${i}`,f=JSON.parse(await R(a,"utf-8")),l=m.parse(i).name;await this.#n(n,l).import(f)}}}countFacets(t,o){const e={};for(const[n,c]of o)e[n]=c.values.map(i=>({value:i,count:0,isCounterVisible:!1}));return e}cleanupFacetValues(t){}}export{J as FlexSearch};
@@ -1 +1 @@
1
- import{appendFile as A}from"node:fs/promises";import{existsSync as R}from"node:fs";import m from"node:path";import{Client as $}from"typesense";import{SEARCH_GROUP_FACET_FIELD as D,SEARCH_PRODUCT_FIELD as b,SEARCH_RBAC_FIELD as g,SEARCH_VERSION_FIELD as f}from"../../../../../constants/common.js";import{BASE_SEARCH_DOCUMENT as O,DEFAULT_ORGANIZATION_ID as v,DEFAULT_PROJECT_ID as P,DEFAULT_TYPESENSE_API_KEY as N,DEFAULT_TYPESENSE_API_URL as L,DISABLE_DEEP_LINK_IF_FIELDS_EXIST as C,HIGHLIGHTED_TEXT_MAX_LENGTH as I,SEARCH_DATA_EXPORT_FOLDER as F,SEARCH_DOCUMENT_METADATA_KEY as w,SEARCH_GROUP_LIMIT as k,SEARCH_MAX_FACET_VALUES as S,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as M}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as T}from"../../../../telemetry/helpers/trace-step.js";import{isBuildMode as j}from"../../../../utils/envs/is-build-mode.js";import{isDevelopMode as h}from"../../../../utils/envs/is-develop-mode.js";import{logger as x}from"../../../../tools/notifiers/logger.js";import{ensureDir as d}from"../../../../utils/index.js";class z{#e=null;#r="";#t=[{name:"title",type:"string",facet:!1,optional:!0},{name:"text",type:"string",facet:!1,optional:!0},{name:"path",type:"string[]",facet:!1,optional:!0},{name:"isAdditionalOperation",type:"bool",facet:!1,optional:!0},{name:"parameters",type:"object[]",facet:!1,optional:!0},{name:b,type:"string",facet:!0,optional:!0},{name:f,type:"object",facet:!0,optional:!0},{name:g,type:"string[]",facet:!0},{name:"metadata_curated",type:"auto",facet:!1,optional:!0},{name:"metadata_keywords_excludes",type:"auto",facet:!1,optional:!0},{name:"metadata_keywords_includes",type:"auto",facet:!1,optional:!0}];#s=new Map;#o={ORGANIZATION_ID:process.env.ORGANIZATION_ID||(h()?v:""),PROJECT_ID:process.env.PROJECT_ID||(h()?P:""),TYPESENSE_API_URL:process.env.TYPESENSE_API_URL||(h()?L:""),TYPESENSE_API_KEY:process.env.TYPESENSE_API_KEY||(h()?N:"")};constructor(){if(!j()){for(const[e,t]of Object.entries(this.#o))if(!t)throw new Error(`Cannot initialize search index. ${e} is not set`);this.#r=`${this.#o.ORGANIZATION_ID}_${this.#o.PROJECT_ID}_`,this.#e=new $({nodes:[{url:this.#o.TYPESENSE_API_URL}],apiKey:this.#o.TYPESENSE_API_KEY,connectionTimeoutSeconds:5})}}async initIndexSchema(e){this.#d(e),h()&&await this.#m()}async addDocuments(e,t){e.push(O);const{locale:i,outDir:r}=t,o=e.map(a=>{const s={...a},n=a[w];return n&&(n.curated&&(s.metadata_curated=n.curated),n.excludes&&(s.metadata_keywords_excludes=n.excludes),n.includes&&(s.metadata_keywords_includes=n.includes)),s});if(h()){if(o.length){await this.#p(i);try{const a=o.map(s=>({url:s.url,title:s.title,text:s.text,path:s.path,httpMethod:s.httpMethod,isAdditionalOperation:s.isAdditionalOperation,httpPath:s.httpPath,parameters:s.parameters,[b]:s.product?s.product.name:"",[g]:s.rbacTeams??[],[f]:s.version?{isDefault:s.isDefaultVersion,version:s.version,folderId:s.versionFolderId}:{isDefault:!0},...s.facets}));await this.#e?.collections(i).documents().import(a)}catch(a){if(a.importResults)for(const s of a.importResults)s.success===!1&&x.error(`Error adding document to collection: ${i}: ${s.error}`)}}}else{const a=this.#s.get(i)??[];this.#s.set(i,a.concat(o)),a.length+e.length>=M&&await this.exportDocuments(r)}}async search(e){return await T("search",async t=>{const{query:i,locale:r,filter:o,loadMore:a,auth:s}=e,n=h()?r:this.#c(r),l={collection:n,q:i||"*",query_by:this.#l(),max_facet_values:S};if(t?.setAttribute("collectionName",n),t?.setAttribute("locale",r),this.#e)if(a){const{groupKey:c,offset:u}=a,p={offset:u,filter_by:this.#i(s,o),facet_by:"*"};return t?.setAttribute("isLoadMore",!0),t?.setAttribute("filter",p.filter_by),this.#u(await this.#e.collections(n).documents().search({...l,...p}),c)}else{const c={group_by:this.#_(),group_limit:k,filter_by:this.#i(s,o)};t?.setAttribute("groups",c.group_by),t?.setAttribute("filter",c.filter_by);const u=[c,...this.#E(s,o)];return this.#f(await this.#e?.multiSearch.perform({searches:u},l),o)}else return{facets:{},documents:{}}})}#u(e,t){const i={facets:{},documents:{[t]:[]}};if(e.hits&&e.hits.length)for(const r of e.hits)i.documents[t].push({document:this.#n(r),highlight:this.#a(r)});return i}#f(e,t){const i={facets:{},documents:{}};for(const r of this.#y(t))i.documents[r]=[];if("results"in e)for(const r of e.results){if(r.facet_counts&&r.facet_counts.length)for(const o of r.facet_counts)i.facets[o.field_name]=o.counts.map(a=>({value:a.value,count:a.count}));if(r.grouped_hits&&r.grouped_hits.length)for(const o of r.grouped_hits){const a=o.group_key[0],s=[];for(const n of o.hits)s.push({document:this.#n(n),highlight:this.#a(n)});i.documents[a]=s}}return i}#n(e){return this.#h(e)}#a(e){const t={},i=[];for(const[r,o]of Object.entries(e.highlight??{}))if(Array.isArray(o)){if(r==="path"){const a=o,s=[];for(const n of a)s.push(n.snippet);t.path=s}else if(r==="parameters"){const a=o;for(const s of a){let n=!1;for(const[l,c]of Object.entries(s))if(l!=="deepLink")if(Array.isArray(c))for(const u of c)u.matched_tokens?.length&&(n=!0);else c.matched_tokens?.length&&(n=!0);if(n){const l={name:s.name?.snippet||"",description:s.description?.snippet||"",place:s.place?.snippet||"",path:s.path?.map(c=>c?.snippet)||[]};t.parameters=[l];break}}}}else t[r]=o.snippet,i.push(r);for(const[r,o]of Object.entries(e.document))!i.includes(r)&&typeof o=="string"&&(t[r]=o.length>I?`${o.substring(0,I)}...`:o);return t.parameters||(t.parameters=[]),t}#h(e){let t;const i=Object.keys(e.highlight);for(const o of C)if(i.some(a=>a===o))return e.document;const r=e.highlight.parameters;if(r){for(const o of r)for(const[a,s]of Object.entries(o))if(a!=="deepLink"){if(Array.isArray(s)){for(const n of s)if(n.matched_tokens?.length){t=o.deepLink.snippet;break}}else if(s.matched_tokens?.length){t=o.deepLink.snippet;break}}}if(t){const o=t.split("#")[1];return{...e.document,url:`${e.document.url}#${o}`}}return e.document}async exportDocuments(e){const t='{"documents":[',i=d(m.join(e,F));for(const[r,o]of this.#s){if(o.length===0)continue;const a=d(m.join(i,`${r}.json`)),s=!R(a),n=JSON.stringify(o).substring(1).slice(0,-1),l=s?t+n:","+n;await A(a,l,{encoding:"utf8"}),this.#s.set(r,[])}}async exportIndexes(e){const t=d(m.join(e,F));for(const i of this.#s.keys()){const r=d(m.join(t,`${i}.json`)),o=`],"schemaFields":${JSON.stringify(this.#t)}}`;await A(r,o,{encoding:"utf8"})}}async import(e){}async countFacets(e,t){return await T("search.facets",async i=>{const{locale:r,query:o,facetQuery:a,filter:s,field:n,auth:l}=e,c=h()?r:this.#c(r),u={q:o||"*",query_by:this.#l(),facet_by:"*",facet_query:this.#g(a,n),filter_by:this.#i(l,s,n),max_facet_values:S};if(i?.setAttribute("collectionName",c),i?.setAttribute("query",u.q),i?.setAttribute("facetQuery",u.facet_query),i?.setAttribute("filter",u.filter_by),this.#e){const p={},_=await this.#e.collections(c).documents().search(u);if(_.facet_counts&&_.facet_counts.length)for(const y of _.facet_counts)p[y.field_name]=y.counts.map(E=>({value:E.value,count:E.count,isCounterVisible:!!o||(s?.length||0)>0}));return p}else return{}})}#c(e){return`${this.#r}${e}`}async#p(e){const t=await this.#e?.collections().retrieve();t&&t.length&&t.find(i=>i.name===e)||await this.#e?.collections().create({name:e,fields:this.#t,enable_nested_fields:!0})}async#m(){const e=await this.#e?.collections().retrieve();for(const t of e??[])await this.#e?.collections(t.name).delete()}#d(e){for(const[t]of e)this.#t.find(i=>i.name===t)||this.#t.push({name:t,type:"string",facet:!0,optional:!0})}#l(){return this.#t.filter(e=>!e.facet&&!e.name.startsWith("metadata_")&&e.name!=="isAdditionalOperation").map(e=>e.name).join(",")}#_(){return this.#t.filter(e=>e.facet&&e.name===D).map(e=>e.name).join(",")}#i(e,t,i){const r=`${g}:[${e.teams.map(a=>`'${a}'`).join(", ")}]`;let o=`${f}.isDefault:true`;if(t&&t.length){const a=t.filter(n=>n.field!==i&&n.field!==f).map(n=>{const l=n.values.map(c=>`'${c}'`);return l.length?`${n.field}:[${l.join(", ")}]`:""}).join(" && "),s=t.find(n=>n.field===f);if(s&&s.values.length&&s.values.length===2){const n=s.values[0],l=s.values[1],c=`(${f}.folderId:! ${n} && ${f}.isDefault:true)`,u=`(${f}.folderId:${n} && ${f}.version:${l})`;o=`(${c} || ${u})`}return a?`${r} && ${a} && ${o}`:`${r} && ${o}`}else return`${r} && ${o}`}#g(e,t){return e&&t?`${t}:${e}`:""}#y(e){const t=[];if(e&&e.length)for(const i of e)i.field===D&&t.push(...i.values);return t}#E(e,t){const i=[],r=this.#t.filter(o=>o.facet);for(const o of r){const a={facet_by:o.name,filter_by:this.#i(e,t,o.name)};i.push(a)}return i}cleanupFacetValues(e){const t=e.getSearchFacets();t.forEach(i=>{i.values=[]}),e.setSearchFacets(t)}}export{z as Typesense};
1
+ import{appendFile as A}from"node:fs/promises";import{existsSync as v}from"node:fs";import m from"node:path";import{Client as R}from"typesense";import{SEARCH_GROUP_FACET_FIELD as D,SEARCH_PRODUCT_FIELD as b,SEARCH_RBAC_FIELD as g,SEARCH_VERSION_FIELD as h}from"../../../../../constants/common.js";import{BASE_SEARCH_DOCUMENT as $,DEFAULT_ORGANIZATION_ID as O,DEFAULT_PROJECT_ID as P,DEFAULT_TYPESENSE_API_KEY as N,DEFAULT_TYPESENSE_API_URL as L,DISABLE_DEEP_LINK_IF_FIELDS_EXIST as C,HIGHLIGHTED_TEXT_MAX_LENGTH as I,SEARCH_DATA_EXPORT_FOLDER as F,SEARCH_DOCUMENT_METADATA_KEY as M,SEARCH_GROUP_LIMIT as w,SEARCH_MAX_FACET_VALUES as S,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as k}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as T}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as u}from"../../../../../config/env-config.js";import{logger as j}from"../../../../tools/notifiers/logger.js";import{ensureDir as d}from"../../../../utils/index.js";class Q{#e=null;#r="";#t=[{name:"title",type:"string",facet:!1,optional:!0},{name:"text",type:"string",facet:!1,optional:!0},{name:"path",type:"string[]",facet:!1,optional:!0},{name:"isAdditionalOperation",type:"bool",facet:!1,optional:!0},{name:"parameters",type:"object[]",facet:!1,optional:!0},{name:b,type:"string",facet:!0,optional:!0},{name:h,type:"object",facet:!0,optional:!0},{name:g,type:"string[]",facet:!0},{name:"metadata_curated",type:"auto",facet:!1,optional:!0},{name:"metadata_keywords_excludes",type:"auto",facet:!1,optional:!0},{name:"metadata_keywords_includes",type:"auto",facet:!1,optional:!0}];#s=new Map;#o={ORGANIZATION_ID:u.ORGANIZATION_ID||(u.isDevelopMode?O:""),PROJECT_ID:u.PROJECT_ID||(u.isDevelopMode?P:""),TYPESENSE_API_URL:u.TYPESENSE_API_URL||(u.isDevelopMode?L:""),TYPESENSE_API_KEY:u.TYPESENSE_API_KEY||(u.isDevelopMode?N:"")};constructor(){if(!u.isBuildMode){for(const[e,t]of Object.entries(this.#o))if(!t)throw new Error(`Cannot initialize search index. ${e} is not set`);this.#r=`${this.#o.ORGANIZATION_ID}_${this.#o.PROJECT_ID}_`,this.#e=new R({nodes:[{url:this.#o.TYPESENSE_API_URL}],apiKey:this.#o.TYPESENSE_API_KEY,connectionTimeoutSeconds:5})}}async initIndexSchema(e){this.#d(e),u.isDevelopMode&&await this.#m()}async addDocuments(e,t){e.push($);const{locale:i,outDir:r}=t,o=e.map(n=>{const s={...n},a=n[M];return a&&(a.curated&&(s.metadata_curated=a.curated),a.excludes&&(s.metadata_keywords_excludes=a.excludes),a.includes&&(s.metadata_keywords_includes=a.includes)),s});if(u.isDevelopMode){if(o.length){await this.#p(i);try{const n=o.map(s=>({url:s.url,title:s.title,text:s.text,path:s.path,httpMethod:s.httpMethod,isAdditionalOperation:s.isAdditionalOperation,httpPath:s.httpPath,parameters:Array.isArray(s.parameters)?s.parameters.map(a=>({...a,enum:void 0})):[],[b]:s.product?s.product.name:"",[g]:s.rbacTeams??[],[h]:s.version?{isDefault:s.isDefaultVersion,version:s.version,folderId:s.versionFolderId}:{isDefault:!0},...s.facets}));await this.#e?.collections(i).documents().import(n)}catch(n){if(n.importResults)for(const s of n.importResults)s.success===!1&&j.error(`Error adding document to collection: ${i}: ${s.error}`)}}}else{const n=this.#s.get(i)??[];this.#s.set(i,n.concat(o)),n.length+e.length>=k&&await this.exportDocuments(r)}}async search(e){return await T("search",async t=>{const{query:i,locale:r,filter:o,loadMore:n,auth:s}=e,a=u.isDevelopMode?r:this.#c(r),l={collection:a,q:i||"*",query_by:this.#l(),max_facet_values:S};if(t?.setAttribute("collectionName",a),t?.setAttribute("locale",r),this.#e)if(n){const{groupKey:c,offset:f}=n,p={offset:f,filter_by:this.#i(s,o),facet_by:"*"};return t?.setAttribute("isLoadMore",!0),t?.setAttribute("filter",p.filter_by),this.#u(await this.#e.collections(a).documents().search({...l,...p}),c)}else{const c={group_by:this.#_(),group_limit:w,filter_by:this.#i(s,o)};t?.setAttribute("groups",c.group_by),t?.setAttribute("filter",c.filter_by);const f=[c,...this.#E(s,o)];return this.#f(await this.#e?.multiSearch.perform({searches:f},l),o)}else return{facets:{},documents:{}}})}#u(e,t){const i={facets:{},documents:{[t]:[]}};if(e.hits&&e.hits.length)for(const r of e.hits)i.documents[t].push({document:this.#a(r),highlight:this.#n(r)});return i}#f(e,t){const i={facets:{},documents:{}};for(const r of this.#y(t))i.documents[r]=[];if("results"in e)for(const r of e.results){if(r.facet_counts&&r.facet_counts.length)for(const o of r.facet_counts)i.facets[o.field_name]=o.counts.map(n=>({value:n.value,count:n.count}));if(r.grouped_hits&&r.grouped_hits.length)for(const o of r.grouped_hits){const n=o.group_key[0],s=[];for(const a of o.hits)s.push({document:this.#a(a),highlight:this.#n(a)});i.documents[n]=s}}return i}#a(e){return this.#h(e)}#n(e){const t={},i=[];for(const[r,o]of Object.entries(e.highlight??{}))if(Array.isArray(o)){if(r==="path"){const n=o,s=[];for(const a of n)s.push(a.snippet);t.path=s}else if(r==="parameters"){const n=o;for(const s of n){let a=!1;for(const[l,c]of Object.entries(s))if(l!=="deepLink")if(Array.isArray(c))for(const f of c)f.matched_tokens?.length&&(a=!0);else c.matched_tokens?.length&&(a=!0);if(a){const l={name:s.name?.snippet||"",description:s.description?.snippet||"",place:s.place?.snippet||"",path:s.path?.map(c=>c?.snippet)||[]};t.parameters=[l];break}}}}else t[r]=o.snippet,i.push(r);for(const[r,o]of Object.entries(e.document))!i.includes(r)&&typeof o=="string"&&(t[r]=o.length>I?`${o.substring(0,I)}...`:o);return t.parameters||(t.parameters=[]),t}#h(e){let t;const i=Object.keys(e.highlight);for(const o of C)if(i.some(n=>n===o))return e.document;const r=e.highlight.parameters;if(r){for(const o of r)for(const[n,s]of Object.entries(o))if(n!=="deepLink"){if(Array.isArray(s)){for(const a of s)if(a.matched_tokens?.length){t=o.deepLink.snippet;break}}else if(s.matched_tokens?.length){t=o.deepLink.snippet;break}}}if(t){const o=t.split("#")[1];return{...e.document,url:`${e.document.url}#${o}`}}return e.document}async exportDocuments(e){const t='{"documents":[',i=d(m.join(e,F));for(const[r,o]of this.#s){if(o.length===0)continue;const n=d(m.join(i,`${r}.json`)),s=!v(n),a=JSON.stringify(o).substring(1).slice(0,-1),l=s?t+a:","+a;await A(n,l,{encoding:"utf8"}),this.#s.set(r,[])}}async exportIndexes(e){const t=d(m.join(e,F));for(const i of this.#s.keys()){const r=d(m.join(t,`${i}.json`)),o=`],"schemaFields":${JSON.stringify(this.#t)}}`;await A(r,o,{encoding:"utf8"})}}async import(e){}async countFacets(e,t){return await T("search.facets",async i=>{const{locale:r,query:o,facetQuery:n,filter:s,field:a,auth:l}=e,c=u.isDevelopMode?r:this.#c(r),f={q:o||"*",query_by:this.#l(),facet_by:"*",facet_query:this.#g(n,a),filter_by:this.#i(l,s,a),max_facet_values:S};if(i?.setAttribute("collectionName",c),i?.setAttribute("query",f.q),i?.setAttribute("facetQuery",f.facet_query),i?.setAttribute("filter",f.filter_by),this.#e){const p={},_=await this.#e.collections(c).documents().search(f);if(_.facet_counts&&_.facet_counts.length)for(const y of _.facet_counts)p[y.field_name]=y.counts.map(E=>({value:E.value,count:E.count,isCounterVisible:!!o||(s?.length||0)>0}));return p}else return{}})}#c(e){return`${this.#r}${e}`}async#p(e){const t=await this.#e?.collections().retrieve();t&&t.length&&t.find(i=>i.name===e)||await this.#e?.collections().create({name:e,fields:this.#t,enable_nested_fields:!0})}async#m(){const e=await this.#e?.collections().retrieve();for(const t of e??[])await this.#e?.collections(t.name).delete()}#d(e){for(const[t]of e)this.#t.find(i=>i.name===t)||this.#t.push({name:t,type:"string",facet:!0,optional:!0})}#l(){return this.#t.filter(e=>!e.facet&&!e.name.startsWith("metadata_")&&e.name!=="isAdditionalOperation").map(e=>e.name).join(",")}#_(){return this.#t.filter(e=>e.facet&&e.name===D).map(e=>e.name).join(",")}#i(e,t,i){const r=`${g}:[${e.teams.map(n=>`'${n}'`).join(", ")}]`;let o=`${h}.isDefault:true`;if(t&&t.length){const n=t.filter(a=>a.field!==i&&a.field!==h).map(a=>{const l=a.values.map(c=>`'${c}'`);return l.length?`${a.field}:[${l.join(", ")}]`:""}).join(" && "),s=t.find(a=>a.field===h);if(s&&s.values.length&&s.values.length===2){const a=s.values[0],l=s.values[1],c=`(${h}.folderId:! ${a} && ${h}.isDefault:true)`,f=`(${h}.folderId:${a} && ${h}.version:${l})`;o=`(${c} || ${f})`}return n?`${r} && ${n} && ${o}`:`${r} && ${o}`}else return`${r} && ${o}`}#g(e,t){return e&&t?`${t}:${e}`:""}#y(e){const t=[];if(e&&e.length)for(const i of e)i.field===D&&t.push(...i.values);return t}#E(e,t){const i=[],r=this.#t.filter(o=>o.facet);for(const o of r){const n={facet_by:o.name,filter_by:this.#i(e,t,o.name)};i.push(n)}return i}cleanupFacetValues(e){const t=e.getSearchFacets();t.forEach(i=>{i.values=[]}),e.setSearchFacets(t)}}export{Q as Typesense};
@@ -1 +1 @@
1
- import{REDOCLY_TEAMS_RBAC as l}from"@redocly/config";import{DEFAULT_SEARCH_ENGINE as c}from"../../constants/plugins/search.js";import{isDevelopMode as p}from"../../utils/envs/is-develop-mode.js";import{logger as g}from"../../tools/notifiers/logger.js";import{reporter as E}from"../../tools/notifiers/reporter.js";import{prepareSearchDocuments as d}from"./documents/search-documents.js";import{SearchEngine as S}from"./engines/search-engine.js";import{prepareAiSearchDocuments as u}from"./ai-indexer/prepare-ai-search-documents.js";import{isAiSearchEnabled as b}from"./utils.js";import{telemetryTraceStep as D}from"../../../cli/telemetry/helpers/trace-step.js";async function N(){let e=!0;return{async afterRoutesCreated(a,i){(process.env.SEARCH_DEV_REINIT||e)&&await y(a,i),e=!1},id:"search"}}async function y(e,a){await D("build.plugin.search",async i=>{const r=e.getConfig();if(i?.setAttribute("config",JSON.stringify(r.search||{})),r.search?.hide){g.info("Search is disabled in the config, skipping");return}const o=r.search?.engine||c,s=p()?process.env.SEARCH_DEV_DEBUG?o:c:o,{l10n:f}=e.getGlobalData(),h=b(r),n=r.rbac?.features?.aiSearch;let t;try{t=new S(s,f)}catch(m){await E.panic(m);return}await t.initIndexSchema(e.getSearchFacets()),e.setSearchEngine(t),e.setGlobalData({searchFeatures:{advanced:{enabled:s!==c&&!r.search?.filters?.hide},ai:{enabled:h,[l]:n&&Object.keys(n).length?n:void 0}}}),await d(a.fs,e,t),await u(e,a,{aiSearchEnabled:h,llmstxtEnabled:r.seo?.llmstxt?.hide!==!0})})}export{N as searchPlugin};
1
+ import{REDOCLY_TEAMS_RBAC as d}from"@redocly/config";import{DEFAULT_SEARCH_ENGINE as s}from"../../constants/plugins/search.js";import{envConfig as t}from"../../../config/env-config.js";import{logger as m}from"../../tools/notifiers/logger.js";import{reporter as g}from"../../tools/notifiers/reporter.js";import{prepareSearchDocuments as E}from"./documents/search-documents.js";import{SearchEngine as u}from"./engines/search-engine.js";import{prepareAiSearchDocuments as S}from"./ai-indexer/prepare-ai-search-documents.js";import{isAiSearchEnabled as b}from"./utils.js";import{telemetryTraceStep as y}from"../../../cli/telemetry/helpers/trace-step.js";async function I(){let e=!0;return{async afterRoutesCreated(i,n){(t.SEARCH_DEV_REINIT||e)&&await D(i,n),e=!1},id:"search"}}async function D(e,i){await y("build.plugin.search",async n=>{const r=e.getConfig();if(n?.setAttribute("config",JSON.stringify(r.search||{})),r.search?.hide){m.info("Search is disabled in the config, skipping");return}const f=r.search?.engine||s,o=t.isDevelopMode?t.SEARCH_DEV_DEBUG?f:s:f,{l10n:l}=e.getGlobalData();if(o==="typesense"&&!t.isProductionEnv){m.info("Skip search indexer in preview mode");return}const h=b(r),c=r.rbac?.features?.aiSearch;let a;try{a=new u(o,l)}catch(p){await g.panic(p);return}await a.initIndexSchema(e.getSearchFacets()),e.setSearchEngine(a),e.setGlobalData({searchFeatures:{advanced:{enabled:o!==s&&!r.search?.filters?.hide},ai:{enabled:h,[d]:c&&Object.keys(c).length?c:void 0}}}),await E(i.fs,e,a),await S(e,i,{aiSearchEnabled:h,llmstxtEnabled:r.seo?.llmstxt?.hide!==!0})})}export{I as searchPlugin};
@@ -1,13 +1,13 @@
1
- import a from"picomatch";import{dirname as $,resolve as x}from"node:path";import{access as E,readFile as F,constants as P}from"fs/promises";import{removeTrailingSlash as w}from"../../../../utils/url/remove-trailing-slash.js";import{logger as I}from"../../../tools/notifiers/logger.js";const l="llms.txt",u="Table of contents";async function g(e,t,n={title:l,description:void 0},o){if(!t)return{title:n.title||l,description:n.description,details:void 0,sections:[{title:u,description:void 0,llmstxts:e}]};const s=t.title||n.title||l,r=t.description||n.description,i=await y(t,o),c=t.sections?.map(d=>{const{title:f,description:h,excludeFiles:L,includeFiles:m}=d,T=p(e,{excludeFiles:L,includeFiles:m});return{title:f,description:h,llmstxts:T}});return{title:s,description:r,details:i,sections:c||[{title:u,description:void 0,llmstxts:p(e,{includeFiles:["**/*"],excludeFiles:[]})}]}}async function y(e,t){const n=await t.getConfig();if(e?.details?.path&&n.configPath)try{const o=t.fs.getFileInfo(n.configPath);if(!o)throw new Error(`Config file ${n.configPath} not found`);const s=x(t.fs.cwd,$(o.relativePath),e.details.path);return await E(s,P.R_OK),F(s,"utf-8")}catch{throw new Error(`${e.details.path} is not accessible`)}if(e?.details?.content)return e.details.content}function p(e,t){const{excludeFiles:n,includeFiles:o}=t,s=n?.map(i=>a(i)),r=o?.map(i=>a(i));return e.filter(i=>s?.some(d=>d(i.fsPath))?!1:r?.some(d=>d(i.fsPath)))}async function S(e,t,n={title:l,description:void 0},o){const s=await g(e,t,n,o),r=[`# ${s.title}
1
+ import a from"picomatch";import{dirname as $,resolve as x}from"node:path";import{access as P,readFile as E,constants as F}from"fs/promises";import{removeTrailingSlash as w}from"../../../../utils/url/remove-trailing-slash.js";import{logger as g}from"../../../tools/notifiers/logger.js";import{withPathPrefix as I}from"@redocly/theme/core/utils";import{envConfig as y}from"../../../../config/env-config.js";const l="llms.txt",u="Table of contents";async function M(t,e,n={title:l,description:void 0},o){if(!e)return{title:n.title||l,description:n.description,details:void 0,sections:[{title:u,description:void 0,llmstxts:t}]};const s=e.title||n.title||l,r=e.description||n.description,i=await v(e,o),c=e.sections?.map(d=>{const{title:f,description:h,excludeFiles:m,includeFiles:L}=d,T=p(t,{excludeFiles:m,includeFiles:L});return{title:f,description:h,llmstxts:T}});return{title:s,description:r,details:i,sections:c||[{title:u,description:void 0,llmstxts:p(t,{includeFiles:["**/*"],excludeFiles:[]})}]}}async function v(t,e){const n=await e.getConfig();if(t?.details?.path&&n.configPath)try{const o=e.fs.getFileInfo(n.configPath);if(!o)throw new Error(`Config file ${n.configPath} not found`);const s=x(e.fs.cwd,$(o.relativePath),t.details.path);return await P(s,F.R_OK),E(s,"utf-8")}catch{throw new Error(`${t.details.path} is not accessible`)}if(t?.details?.content)return t.details.content}function p(t,e){const{excludeFiles:n,includeFiles:o}=e,s=n?.map(i=>a(i)),r=o?.map(i=>a(i));return t.filter(i=>s?.some(d=>d(i.fsPath))?!1:r?.some(d=>d(i.fsPath)))}async function j(t,e,n={title:l,description:void 0},o){const s=await M(t,e,n,o),r=[`# ${s.title}
2
2
 
3
3
  `];return s.description&&r.push(`> ${s.description}
4
4
 
5
5
  `),s.details&&r.push(`${s.details}
6
6
 
7
- `),s.sections.forEach(i=>{if(!i.llmstxts.length){I.warn(`llms.txt: No links found for section "${i.title}". Please check the includeFiles/excludeFiles patterns.`);return}r.push(`## ${i.title}
7
+ `),s.sections.forEach(i=>{if(!i.llmstxts.length){g.warn(`llms.txt: No links found for section "${i.title}". Please check the includeFiles/excludeFiles patterns.`);return}r.push(`## ${i.title}
8
8
  `),i.description?r.push(`${i.description.replace(/\n+$/,"")}
9
9
 
10
10
  `):r.push(`
11
- `),i.llmstxts.forEach(c=>{r.push(` - ${M({title:c.title,description:c.description,slug:v(c.slug)})}`)}),r.push(`
12
- `)}),r.join("")}function M({title:e,description:t,slug:n}){return`[${e}](${w(process.env.REDOCLY_PUBLIC_URL||"")}${encodeURI(n)})${t?`: ${t}`:""}
13
- `}function A(e){if(e?.details?.path&&e?.details?.content)throw new Error('"details.path" and "details.content" are mutually exclusive. Please use only one of them.')}function v(e){return`${e}${e==="/"?"index.html.md":".md"}`}export{S as generateLLMsTxt,v as getLLMsTxtMdSlug,M as llmsTxtLink,A as validateLLMsTxtConfig};
11
+ `),i.llmstxts.forEach(c=>{r.push(` - ${_({title:c.title,description:c.description,slug:D(c.slug)})}`)}),r.push(`
12
+ `)}),r.join("")}function _({title:t,description:e,slug:n}){return`[${t}](${w(y.REDOCLY_PUBLIC_URL||"")}${encodeURI(I(n))})${e?`: ${e}`:""}
13
+ `}function B(t){if(t?.details?.path&&t?.details?.content)throw new Error('"details.path" and "details.content" are mutually exclusive. Please use only one of them.')}function D(t){return`${t}${t==="/"?"index.html.md":".md"}`}export{j as generateLLMsTxt,D as getLLMsTxtMdSlug,_ as llmsTxtLink,B as validateLLMsTxtConfig};
@@ -1,2 +1,2 @@
1
- import{SEARCH_GROUP_FACET_FIELD as t}from"../../../constants/common.js";import{DEFAULT_AI_SEARCH_ENABLED as o}from"../../constants/plugins/search.js";import{isPrimitive as n}from"../../../utils/guards/is-primitive.js";import{isDevelopMode as s}from"../../utils/envs/is-develop-mode.js";import{EntitlementsProvider as f}from"../../entitlements/entitlements-provider.js";function A(e){if(s())return process.env.SEARCH_DEV_DEBUG==="true";if(!f.instance().canAccessFeature("aiSearchLimit"))return!1;const r=e.aiAssistant;return typeof r?.hide=="boolean"?!r?.hide:o}function S(e){let i;return e&&Object.keys(e).forEach(r=>{r===t&&(i=e[r])}),i}function h(e){return Object.entries(e||{}).map(([i,r])=>` - ${i}: ${n(r)?r:JSON.stringify(r)}`).join(`
2
- `)}export{h as formatDocumentMetadata,S as getSearchDocumentGroup,A as isAiSearchEnabled};
1
+ import{SEARCH_GROUP_FACET_FIELD as n}from"../../../constants/common.js";import{DEFAULT_AI_SEARCH_ENABLED as o}from"../../constants/plugins/search.js";import{isPrimitive as s}from"../../../utils/guards/is-primitive.js";import{envConfig as r}from"../../../config/env-config.js";import{EntitlementsProvider as m}from"../../entitlements/entitlements-provider.js";function E(t){if(r.isDevelopMode)return r.SEARCH_DEV_DEBUG==="true";if(!m.instance().canAccessFeature("aiSearchLimit"))return!1;const e=t.aiAssistant;return typeof e?.hide=="boolean"?!e?.hide:o}function d(t){return t?.[n]}function S(t){return Object.entries(t||{}).map(([i,e])=>` - ${i}: ${s(e)?e:JSON.stringify(e)}`).join(`
2
+ `)}export{S as formatDocumentMetadata,d as getSearchDocumentGroup,E as isAiSearchEnabled};
@@ -1,8 +1,6 @@
1
1
  import type { LifecyclePluginInstance, PluginOptions } from '../../types';
2
- import type { ResolvedNavItem } from '@redocly/config';
3
2
  import type { ContentFs } from '../../fs/content-fs.js';
4
3
  export declare function sidebarsPlugin({ contentDir, }: PluginOptions): Promise<LifecyclePluginInstance>;
5
- export declare function removeMarkdownTags(items: ResolvedNavItem[]): ResolvedNavItem[];
6
4
  export declare function resolveSidebarId(relativePath: string, sidebarPath: string, fs: ContentFs): Promise<string | null>;
7
5
  export declare function isSidebarIgnored(ignore: string[], sidebarPath: string): boolean;
8
6
  //# sourceMappingURL=index.d.ts.map
@@ -1,3 +1,3 @@
1
- import{writeFileSync as tt}from"node:fs";import*as u from"path";import et from"@markdoc/markdoc";import{withoutHash as ot}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as at,CONFIG_FILE_NAME as K}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as rt}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{readEnvVariable as nt}from"../../utils/envs/read-env-variable.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 A}from"../../tools/notifiers/reporter.js";import{logger as x}from"../../tools/notifiers/logger.js";import{sha1 as ft}from"../../utils/crypto/sha1.js";import{collectItemsLinkedToSidebars as dt,resolveItems as Z}from"../nav-utils.js";import{getInnerText as ut}from"../markdown/markdoc/helpers/get-inner-text.js";import{getExcludedFromLinkCheckerPatterns as mt,getSidebarReferences as gt,hasCircularDependency as pt}from"./utils.js";import{getLocaleFromRelativePath as ht}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as St}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as yt}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as bt}from"../../../cli/telemetry/helpers/trace-step.js";const Ft=180,It=170,Dt=10;async function Jt({contentDir:l}){return{id:"sidebars",async afterRoutesCreated(o,i){await bt("build.plugin.sidebars",async()=>{const{cache:d,fs:c}=i,I=o.getConfig(),D=new Map,P=new Set,B=[E,...c.localeFolders],j=o.getGlobalData()[yt]||{},G=new Map;let L=c.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!Ct(I.ignore??[],t)&&t);const $=await gt(i,l,L),q=it(L.filter(t=>!$.has(t)),t=>ct(t)?.versionFolderPath||t),_=mt(I),Q=await dt(I?.navbar,o,i,{navFile:K,excludedFromLinkCheckerPatterns:_});let w;const T=pt($);T&&Array.isArray(T)&&await A.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 m=(await Promise.all(t.map(async n=>{const e=(await d.load(n,"yaml")).data;if(!Array.isArray(e)){await A.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',n,c,n,typeof e);return}return{items:e,sidebarRelativePath:n,locale:ht(n)}}))).filter(X),r=(await k(m))?.firstLink;w||(w=r)}const z=Object.entries(I?.catalogClassic??{});for(const t of B){for(const[e,s]of z)await W(e,s,t);const m={},r=new Set,n=o.getAllRoutesForLocale(t);for(const e of n)if(U(e)&&e.fsPath&&!r.has(e.fsPath)){r.add(e.fsPath);let f=u.posix.dirname(e.fsPath);const h=u.parse(f).root;do m[f]=(m[f]||0)+1,f=u.dirname(f);while(f&&f!="."&&h!=f)}for(const e of n){if(D.has(e.slug))continue;const s=U(e),f=u.dirname(e.fsPath),h=m[f]===1,g=Et(e.baseSlug||e.slug);s&&h?await k([{items:[{directory:f}],sidebarRelativePath:"sidebar.yaml_"+g,locale:t}]):e.getSidebar!==void 0&&await k([{items:[{page:e.fsPath}],sidebarRelativePath:"sidebar.yaml_"+g,locale:t}])}for(const[e,s]of z)await W(e,s,t,!0)}if(L.length===0)for(const t of B){x.verbose("Creating default sidebar");const m=t===E,r=`sidebars.yaml${m?"":"_"+t}`,n=m?"":`${c.localizationFolder}/${t}`,e=(await k([{items:[{directory:`./${n}`}],sidebarRelativePath:r,locale:t,ignoredRoutes:P}]))?.firstLink;w||(w=e)}if(!o.getRouteBySlug("/")&&!o.getConfig().redirects?.["/"]){const m=o.getAllRoutes().find(n=>!St(n.slug)),r=w?w.link:m?.baseSlug??null;if(r){const n=ot(r);o.addRedirect("/",{to:n,type:302}),x.info("Creating default redirect for index page => %s",n)}}const H=nt("REDOCLY_METADATA_OUTPUT_FOLDER");H&&(x.info("Writing catalog data..."),tt(u.join(H,rt),JSON.stringify(Object.fromEntries(G.entries()))));function U(t){return P.has(t.slug)||j[t.fsPath]}async function k(t){if(t.length===0)return;const r=(await Promise.all(t.map(async({items:g,locale:F,sidebarRelativePath:p,ignoredRoutes:R})=>{const a=await Z(g,u.dirname(u.join(l,p)),o,i,{locale:F,ignoredRoutes:R,navFile:p,excludedFromLinkCheckerPatterns:_});if(!a){await A.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",p);return}return a}))).flat().filter(X),n=N(r,"routeSlug"),e=t[0].sidebarRelativePath,s=J(e),f=new Set;for(const g of n){const F=o.getRouteBySlug(g)?.fsPath??"",p=j[F];p&&(Array.from(f).find(a=>a.key===p.key&&a.version===p.version)||f.add(p)),o.addRouteSharedData(g,"sidebar",s),D.set(Y(g),r)}const h=f.size===1?Array.from(f)[0]:void 0;return await o.createSharedData(s,{relatedNavbarItem:Q?.get(e),items:r,catalogEntity:h?{key:h.key,version:h.version}:void 0}),{firstLink:M(r,g=>!!g.link),resolved:r}}async function W(t,m,r,n=!1){const e=structuredClone(m);r&&r!==E&&e.items.forEach(a=>{a.directory=u.posix.join(c.localizationFolder||"",r,a.directory||"")});let s=await Z(e.items,l,o,i,{groupCustomSidebars:!0,locale:r,navFile:K,excludedFromLinkCheckerPatterns:_});if(s&&(s=wt(s)),!s){await A.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}const f=r===E?"":"/"+r.toLowerCase(),h=r===E?"":`-${r}`,g=Y(u.posix.join(f,e.slug));if(n)for(const a of s){const S=M(a.items||[],b=>!!b.routeSlug);if(!S?.routeSlug)continue;const y=D.get(S.routeSlug);if(!y)continue;const O=N(y,"routeSlug"),v="current-catalog-info-"+a.routeSlug+h,C={catalog:{label:e.title,titleTranslationKey:e.titleTranslationKey,link:g,icon:e?.icon},item:{label:a.metadata?.title,link:a.link,icon:a.icon}};await o.createSharedData(v,C);for(const b of O)o.addRouteSharedData(b,"current-catalog-info",v),P.add(b);const V=M(y,b=>!!b.link&&!b.external&&st(b.link)&&(!a.version||b.version===a.version));V&&(a.sidebar=[{...V,items:void 0}])}const F={},p=new Set;for(const a of s){if(!(a.routeSlug||a.sidebar?.[0]?.routeSlug)||!a.fsPath||p.has(a.fsPath))continue;p.add(a.fsPath);const y=u.dirname(a.fsPath);F[y]=(F[y]||0)+1}if(n){const a=await o.createSharedData("catalog-"+t+h,s.flatMap(S=>{const y=u.dirname(S.fsPath??""),O=F[y]===1,v=C=>({...C,fsPath:O?y:C.fsPath??""});return S.type==="group"&&S.items?.every(C=>C.type==="group")?(S.items||[]).map(v):v(S)}));o.addRouteSharedData(g,"catalog",a),Pt(r,s,G,F)}const R=N(s,"routeSlug");for(const a of R)P.add(a)}})}}}function Pt(l,o,i,d){if(l===E)for(const c of o){const I=c.routeSlug||c.sidebar?.[0]?.routeSlug;if(!I||!c.fsPath)continue;const D=u.dirname(c.fsPath),P=d[D]===1;i.set(I,{rootFileFsPath:c.fsPath,fsPath:P?D:c.fsPath,metadata:c.metadata||{},title:c.metadata?.title||c.label||"Untitled",version:c.version||"latest"})}}function wt(l){const o=i=>{if(!i)return i;const d=et.parse(i);return ut([d])};return l.map(i=>{const d={...i};return d.metadata?.description&&(d.metadata={...d.metadata,description:o(d.metadata.description)}),d})}function J(l){return at+lt(l)}async function qt(l,o,i){const d=u.posix.join(u.dirname(l),o);return await i.exists(d)?J(d):(await A.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",l,i,l,o),null)}function Ct(l,o){const i=/\/?([a-zA-Z0-9-_]+\/)*sidebars?(-[a-zA-Z0-9-_]+)?\.yaml/;return l.filter(c=>i.test(c)).includes(o)}function Et(l){const o=l.replaceAll("/","_");if(o.length>Ft){const i=o.slice(0,It),d=ft(l).slice(0,Dt).replaceAll("/","_");return i+d}else return o}export{Ct as isSidebarIgnored,wt as removeMarkdownTags,qt as resolveSidebarId,Jt as sidebarsPlugin};
1
+ import{writeFileSync as tt}from"node:fs";import*as u from"path";import{withoutHash as et}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as ot,CONFIG_FILE_NAME as V}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as at}from"../../constants/common.js";import{findDeepFirst as x}from"../../../utils/tree/find-deep-first.js";import{isDefined as X}from"../../../utils/guards/is-defined.js";import{partition as rt}from"../../../utils/array/partition.js";import{collectPropValueDeep as B}from"../../../utils/tree/collect-prop-value-deep.js";import{envConfig as it}from"../../../config/env-config.js";import{isLocalLink as nt}from"../../../utils/path/is-local-link.js";import{normalizeRouteSlug as Y}from"../../../utils/path/normalize-route-slug.js";import{slash as st}from"../../../utils/path/slash.js";import{parsePathVersions as lt}from"../../../utils/path/parse-path-versions.js";import{reporter as R}from"../../tools/notifiers/reporter.js";import{logger as v}from"../../tools/notifiers/logger.js";import{sha1 as ct}from"../../utils/crypto/sha1.js";import{collectItemsLinkedToSidebars as ft,resolveItems as Z}from"../nav-utils.js";import{getExcludedFromLinkCheckerPatterns as dt,getSidebarReferences as ut,hasCircularDependency as gt}from"./utils.js";import{getLocaleFromRelativePath as mt}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as pt}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as ht}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as St}from"../../../cli/telemetry/helpers/trace-step.js";const yt=180,bt=170,Ft=10;async function Kt({contentDir:c}){return{id:"sidebars",async afterRoutesCreated(e,f){v.info("Calculating sidebars..."),await St("build.plugin.sidebars",async()=>{const{cache:S,fs:n}=f,C=e.getConfig(),I=new Map,D=new Set,M=[E,...n.localeFolders],G=e.getGlobalData()[ht]||{},$={};let k=n.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!It(C.ignore??[],t)&&t);const j=await ut(f,c,k),q=rt(k.filter(t=>!j.has(t)),t=>lt(t)?.versionFolderPath||t),T=dt(C),Q=await ft(C?.navbar,e,f,{navFile:V,excludedFromLinkCheckerPatterns:T});let P;const O=gt(j);O&&Array.isArray(O)&&await R.panicOnBuildContentError(`Sidebar references have circular dependency. Please check your sidebar files.
2
+ Circular dependency chain: ${O.reverse().join(" -> ")}
3
+ `);for(const t of q){const g=(await Promise.all(t.map(async i=>{const l=(await S.load(i,"yaml")).data;if(!Array.isArray(l)){await R.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',i,n,i,typeof l);return}return{items:l,sidebarRelativePath:i,locale:mt(i)}}))).filter(X),r=(await L(g))?.firstLink;P||(P=r)}const z=Object.entries(C?.catalogClassic??{});for(const t of M){for(const[a,m]of z)await W(a,m,t);const g={},r=new Set,i=e.getAllRoutesForLocale(t);for(const a of i)if(U(a)&&a.fsPath&&!r.has(a.fsPath)){r.add(a.fsPath);let s=u.posix.dirname(a.fsPath);const d=u.parse(s).root;do g[s]=(g[s]||0)+1,s=u.dirname(s);while(s&&s!="."&&d!=s)}const l=v.startTiming("Creating automatic sidebars...");for(const a of i){if(I.has(a.slug))continue;const m=U(a),s=u.dirname(a.fsPath),d=g[s]===1,p=Dt(a.baseSlug||a.slug);m&&d?await L([{items:[{directory:s}],sidebarRelativePath:"sidebar.yaml_"+p,locale:t}]):a.getSidebar!==void 0&&await L([{items:[{page:a.fsPath}],sidebarRelativePath:"sidebar.yaml_"+p,locale:t}])}v.infoTime(l,"Creating automatic sidebars...");for(const[a,m]of z)await W(a,m,t,!0)}if(k.length===0)for(const t of M){v.verbose("Creating default sidebar");const g=t===E,r=`sidebars.yaml${g?"":"_"+t}`,i=g?"":`${n.localizationFolder}/${t}`,l=(await L([{items:[{directory:`./${i}`}],sidebarRelativePath:r,locale:t,ignoredRoutes:D}]))?.firstLink;P||(P=l)}if(!e.getRouteBySlug("/")&&!e.getConfig().redirects?.["/"]){const g=e.getAllRoutes().find(i=>!pt(i.slug)),r=P?P.link:g?.baseSlug??null;if(r){const i=et(r);e.addRedirect("/",{to:i,type:302}),v.info("Creating default redirect for index page => %s",i)}}const H=it.REDOCLY_METADATA_OUTPUT_FOLDER;H&&(v.info("Writing catalog data..."),tt(u.join(H,at),JSON.stringify($)));function U(t){return D.has(t.slug)||G[t.fsPath]}async function L(t){if(t.length===0)return;const r=(await Promise.all(t.map(async({items:d,locale:p,sidebarRelativePath:h,ignoredRoutes:_})=>{const o=await Z(d,u.dirname(u.join(c,h)),e,f,{locale:p,ignoredRoutes:_,navFile:h,excludedFromLinkCheckerPatterns:T});if(!o){await R.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",h);return}return o}))).flat().filter(X),i=B(r,"routeSlug"),l=t[0].sidebarRelativePath,a=J(l),m=new Set;for(const d of i){const p=e.getRouteBySlug(d)?.fsPath??"",h=G[p];h&&(Array.from(m).find(o=>o.key===h.key&&o.version===h.version)||m.add(h)),e.addRouteSharedData(d,"sidebar",a),I.set(Y(d),r)}const s=m.size===1?Array.from(m)[0]:void 0;return await e.createSharedData(a,{relatedNavbarItem:Q?.get(l),items:r,catalogEntity:s?{key:s.key,version:s.version}:void 0}),{firstLink:x(r,d=>!!d.link),resolved:r}}async function W(t,g,r,i=!1){const l=structuredClone(g);r&&r!==E&&l.items.forEach(o=>{o.directory=u.posix.join(n.localizationFolder||"",r,o.directory||"")});let a=await Z(l.items,c,e,f,{groupCustomSidebars:!0,locale:r,navFile:V,excludedFromLinkCheckerPatterns:T});if(!a){await R.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}const m=r===E?"":"/"+r.toLowerCase(),s=r===E?"":`-${r}`,d=Y(u.posix.join(m,l.slug));if(i)for(const o of a){const y=x(o.items||[],F=>!!F.routeSlug);if(!y?.routeSlug)continue;const b=I.get(y.routeSlug);if(!b)continue;const N=B(b,"routeSlug"),w="current-catalog-info-"+o.routeSlug+s,A={catalog:{label:l.title,titleTranslationKey:l.titleTranslationKey,link:d,icon:l?.icon},item:{label:o.metadata?.title,link:o.link,icon:o.icon}};await e.createSharedData(w,A);for(const F of N)e.addRouteSharedData(F,"current-catalog-info",w),D.add(F);const K=x(b,F=>!!F.link&&!F.external&&nt(F.link)&&(!o.version||F.version===o.version));K&&(o.sidebar=[{...K,items:void 0}])}const p={},h=new Set;for(const o of a){if(!(o.routeSlug||o.sidebar?.[0]?.routeSlug)||!o.fsPath||h.has(o.fsPath))continue;h.add(o.fsPath);const b=u.dirname(o.fsPath);p[b]=(p[b]||0)+1}if(i){const o=await e.createSharedData("catalog-"+t+s,a.flatMap(y=>{const b=u.dirname(y.fsPath??""),N=p[b]===1,w=A=>({...A,fsPath:N?b:A.fsPath??""});return y.type==="group"&&y.items?.every(A=>A.type==="group")?(y.items||[]).map(w):w(y)}));e.addRouteSharedData(d,"catalog",o),Ct(r,a,$,p)}const _=B(a,"routeSlug");for(const o of _)D.add(o)}})}}}function Ct(c,e,f,S){if(c===E)for(const n of e){const C=n.routeSlug||n.sidebar?.[0]?.routeSlug;if(!C||!n.fsPath)continue;const I=u.dirname(n.fsPath),D=S[I]===1;f[C]={rootFileFsPath:n.fsPath,fsPath:D?I:n.fsPath,metadata:n.metadata||{},title:n.metadata?.title||n.label||"Untitled",version:n.version||"latest"}}}function J(c){return ot+st(c)}async function Vt(c,e,f){const S=u.posix.join(u.dirname(c),e);return await f.exists(S)?J(S):(await R.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",c,f,c,e),null)}function It(c,e){const f=/\/?([a-zA-Z0-9-_]+\/)*sidebars?(-[a-zA-Z0-9-_]+)?\.yaml/;return c.filter(n=>f.test(n)).includes(e)}function Dt(c){const e=c.replaceAll("/","_");if(e.length>yt){const f=e.slice(0,bt),S=ct(c).slice(0,Ft).replaceAll("/","_");return f+S}else return e}export{It as isSidebarIgnored,Vt as resolveSidebarId,Kt as sidebarsPlugin};
@@ -1 +1 @@
1
- import{DEFAULT_SSO_IDP_TITLE as d}from"../../../constants/common.js";import{telemetryTraceStep as u}from"../../../cli/telemetry/helpers/trace-step.js";const f="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",y="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function O(g){return{id:"sso",async processContent(e){await u("build.plugin.sso",async c=>{const o=e.getConfig();if(c?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(o.sso||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0||o.sso&&Array.isArray(o.sso)&&!o.sso.length)return;const a=!!(o.rbac&&typeof o.rbac=="object"&&Object.keys(o.rbac).length!==0),p=o.requiresLogin;if(!a&&!p)return;let n=f,i=process.env.REDOCLY_OAUTH_USE_INTROSPECT?y:"";const s=o.residency;if(s){const r=s.endsWith("/")?s.slice(0,-1):s;n=`${r.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,i=process.env.REDOCLY_OAUTH_USE_INTROSPECT?`${r}/api/sso/oidc/introspect`:""}let t="AUTO";o.sso&&(Array.isArray(o.sso)?t=o.sso.join(","):t=o.sso);const l={oidc:{title:d,type:"OIDC",configurationUrl:n,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid"],authorizationRequestCustomParams:{login_hint:"{{ process.env.ORG_ID }}",login_type:t,prompt:"login"},audience:"{{ process.env.ORG_ID }}",introspectEndpoint:i}};e.setGlobalConfig({ssoDirect:l})})},async afterRoutesCreated(e){}}}export{O as ssoPlugin};
1
+ import{DEFAULT_SSO_IDP_TITLE as f}from"../../../constants/common.js";import{envConfig as c}from"../../../config/env-config.js";import{telemetryTraceStep as u}from"../../../cli/telemetry/helpers/trace-step.js";const g="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",y="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function m(C){return{id:"sso",async processContent(e){await u("build.plugin.sso",async a=>{const o=e.getConfig();if(a?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(o.sso||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0||o.sso&&Array.isArray(o.sso)&&!o.sso.length)return;const l=!!(o.rbac&&typeof o.rbac=="object"&&Object.keys(o.rbac).length!==0),p=o.requiresLogin;if(!l&&!p)return;let i=g,n=c.REDOCLY_OAUTH_USE_INTROSPECT?y:"";const s=o.residency;if(s){const r=s.endsWith("/")?s.slice(0,-1):s;i=`${r.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,n=c.REDOCLY_OAUTH_USE_INTROSPECT?`${r}/api/sso/oidc/introspect`:""}let t="AUTO";o.sso&&(Array.isArray(o.sso)?t=o.sso.join(","):t=o.sso);const d={oidc:{title:f,type:"OIDC",configurationUrl:i,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid"],authorizationRequestCustomParams:{login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:t,prompt:"login"},audience:"{{ process.env.ORGANIZATION_ID }}",introspectEndpoint:n}};e.setGlobalConfig({ssoDirect:d})})},async afterRoutesCreated(e){}}}export{m as ssoPlugin};
@@ -9,5 +9,6 @@ export declare abstract class BaseRepository {
9
9
  protected constructor(dbConnection: DatabaseConnection);
10
10
  close(): Promise<void>;
11
11
  sync(): Promise<void>;
12
+ isNonRemoteDatabaseMode: () => boolean;
12
13
  }
13
14
  //# sourceMappingURL=base-repository.d.ts.map
@@ -1 +1 @@
1
- class n{static#e="ORGANIZATION_ID";static#t="PROJECT_ID";organizationId;projectId;databaseClient;path;constructor(t){const e=this.#r();this.organizationId=this.#n(e),this.projectId=this.#i(e),this.databaseClient=t.client,this.path=t.path}async close(){await this.databaseClient.close()}async sync(){await this.databaseClient.sync()}#n=t=>{const e=process.env.ORGANIZATION_ID;if(e)return e;if(t)return n.#e;throw new Error("ORGANIZATION_ID environment variable is required. Ensure it is set in your environment configuration.")};#i=t=>{const e=process.env.PROJECT_ID;if(e)return e;if(t)return n.#t;throw new Error("PROJECT_ID environment variable is required. Ensure it is set in your environment configuration.")};#r=()=>!process.env.SQLD_REMOTE_DATABASE_URL&&!process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN}export{n as BaseRepository};
1
+ import{envConfig as i}from"../../../config/env-config.js";import{SQLD_REMOTE_DATABASE_URL_NO_DEPLOYMENT_YET_VAR as r}from"../../constants/plugins/catalog-entities.js";class n{static#t="ORGANIZATION_ID";static#e="PROJECT_ID";organizationId;projectId;databaseClient;path;constructor(e){const t=this.isNonRemoteDatabaseMode();this.organizationId=this.#i(t),this.projectId=this.#n(t),this.databaseClient=e.client,this.path=e.path}async close(){await this.databaseClient.close()}async sync(){await this.databaseClient.sync()}#i=e=>{const t=i.ORGANIZATION_ID;if(t)return t;if(e)return n.#t;throw new Error("ORGANIZATION_ID environment variable is required. Ensure it is set in your environment configuration.")};#n=e=>{const t=i.PROJECT_ID;if(t)return t;if(e)return n.#e;throw new Error("PROJECT_ID environment variable is required. Ensure it is set in your environment configuration.")};isNonRemoteDatabaseMode=()=>i.SQLD_REMOTE_DATABASE_URL===r||!i.SQLD_REMOTE_DATABASE_AUTH_TOKEN}export{n as BaseRepository};
@@ -1 +1 @@
1
- import{logger as e}from"../../tools/notifiers/logger.js";import{CATALOG_LOCAL_DATABASE_MIGRATIONS_FOLDER as r,CATALOG_LOCAL_DATABASE_FOLDER as i,CATALOG_LOCAL_DATABASE_NAME as s,MAIN_LOCAL_DATABASE_MIGRATIONS_FOLDER as _,MAIN_LOCAL_DATABASE_FOLDER as E,MAIN_LOCAL_DATABASE_NAME as l,SQLD_REMOTE_DATABASE_FOLDER as c,SQLD_REMOTE_DATABASE_MIGRATIONS_FOLDER as D,SQLD_REMOTE_DATABASE_NAME as T}from"./constants.js";import{LocalDatabaseInitializationStrategy as n,RemoteDatabaseInitializationStrategy as L}from"./database-initialization-strategy.js";import{DatabaseConnectionsManager as O}from"./database-connections-manager.js";class g{static async create(a,t){switch(a){case"main-local":return await this.#a(t);case"catalog-local":return await this.#t(t);case"sqld-remote":return await this.#e(t);default:return null}}static async#a(a){return await new n().initialize({...a,databaseName:l,additionalFolder:E,migrationsFolder:_})}static async#t(a){return await new n().initialize({...a,databaseName:s,additionalFolder:i,migrationsFolder:r})}static async#e(a){const t=process.env.SQLD_REMOTE_DATABASE_URL&&process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN,A=a.sqldRemoteDatabaseUrl&&a.sqldRemoteDatabaseAuthToken;if(!t&&!A)return process.env.NEW_CATALOG_ENABLED==="true"&&e.warn("SQLD_REMOTE_DATABASE_URL and SQLD_REMOTE_DATABASE_AUTH_TOKEN env variables or sqldRemoteDatabaseUrl and sqldRemoteDatabaseAuthToken options not set - remote database will not be initialized"),null;try{return await O.getConnection({config:{...a,databaseName:T,additionalFolder:c,migrationsFolder:D,syncUrl:process.env.SQLD_REMOTE_DATABASE_URL||a.sqldRemoteDatabaseUrl,authToken:process.env.SQLD_REMOTE_DATABASE_AUTH_TOKEN||a.sqldRemoteDatabaseAuthToken},strategy:new L})}catch(o){return e.error("Remote database connection initialization failed",o),null}}}export{g as DatabaseConnectionFactory};
1
+ import{logger as i}from"../../tools/notifiers/logger.js";import{envConfig as e}from"../../../config/env-config.js";import{CATALOG_LOCAL_DATABASE_FOLDER as A,CATALOG_LOCAL_DATABASE_MIGRATIONS_FOLDER as s,CATALOG_LOCAL_DATABASE_NAME as _,MAIN_LOCAL_DATABASE_FOLDER as l,MAIN_LOCAL_DATABASE_MIGRATIONS_FOLDER as c,MAIN_LOCAL_DATABASE_NAME as E,SQLD_REMOTE_DATABASE_FOLDER as D,SQLD_REMOTE_DATABASE_MIGRATIONS_FOLDER as T,SQLD_REMOTE_DATABASE_NAME as L}from"./constants.js";import{LocalDatabaseInitializationStrategy as o,RemoteDatabaseInitializationStrategy as d}from"./database-initialization-strategy.js";import{DatabaseConnectionsManager as m}from"./database-connections-manager.js";import{SQLD_REMOTE_DATABASE_URL_NO_DEPLOYMENT_YET_VAR as O}from"../../constants/plugins/catalog-entities.js";class N{static async create(a,t){switch(a){case"main-local":return await this.#a(t);case"catalog-local":return await this.#t(t);case"sqld-remote":return await this.#e(t);default:return null}}static async#a(a){return await new o().initialize({...a,databaseName:E,additionalFolder:l,migrationsFolder:c})}static async#t(a){return await new o().initialize({...a,databaseName:_,additionalFolder:A,migrationsFolder:s})}static async#e(a){try{const t=e.SQLD_REMOTE_DATABASE_URL||a.sqldRemoteDatabaseUrl,n=t===O?void 0:t,r=e.SQLD_REMOTE_DATABASE_AUTH_TOKEN||a.sqldRemoteDatabaseAuthToken;return(!n||!r)&&!e.isDevelopMode?(i.warn("Your remote database is not initialized yet, please wait for production deployment."),null):await m.getConnection({config:{...a,databaseName:L,additionalFolder:D,migrationsFolder:T,syncUrl:n,authToken:e.SQLD_REMOTE_DATABASE_AUTH_TOKEN||a.sqldRemoteDatabaseAuthToken},strategy:new d})}catch(t){return i.error("Remote database connection initialization failed",t),null}}}export{N as DatabaseConnectionFactory};
@@ -1 +1 @@
1
- import{logger as r}from"../../tools/notifiers/logger.js";import{DatabaseClient as g}from"./client.js";import{DatabasePathGenerator as p}from"./database-path-generator.js";import{retryAsyncOperation as h}from"./utils/retry-async-operation.js";class u{async initialize({removeExisting:a,baseDbDir:t,runWithPragmaWalWriteOptimization:s,databaseName:o,additionalFolder:l,migrationsFolder:c}){r.info("Initializing local database client...");const m=r.startTiming(),{databasePath:e}=await p.prepareDatabasePath({baseDir:t,databaseName:o,additionalFolder:l,removeExisting:a}),n={url:`file:${e}`},i=await g.init(n,{runWithPragmaWalWriteOptimization:s});return await i.migrate(t,c),r.infoTime(m,"Local database client initialized"),{client:i,path:e}}}class w{#t;#a;constructor(a){this.#t=a?.skipLogs??!1,this.#a=this.#t?void 0:r}async initialize({removeExisting:a,baseDbDir:t,syncUrl:s,authToken:o,databaseName:l,additionalFolder:c,migrationsFolder:m}){this.#a?.info("Initializing remote database client...");const e=this.#a?.startTiming();return await h(async()=>{const{databasePath:n}=await p.prepareDatabasePath({baseDir:t,databaseName:l,additionalFolder:c,removeExisting:a}),i=await g.init({url:`file:${n}`,syncUrl:s,authToken:o});return await i.migrate(t,m),this.#a?.infoTime(e??"","Remote database client initialized"),{client:i,path:n}},{maxRetries:3,retryStrategy:"exponential",delay:1e3,logger:this.#a,messages:{retry:"Retrying remote database client initialization",maxRetriesReached:"Max retries reached, remote database client initialization failed"}})}}export{u as LocalDatabaseInitializationStrategy,w as RemoteDatabaseInitializationStrategy};
1
+ import{logger as n}from"../../tools/notifiers/logger.js";import{DatabaseClient as g}from"./client.js";import{DatabasePathGenerator as p}from"./database-path-generator.js";import{retryAsyncOperation as f}from"./utils/retry-async-operation.js";import{SqldNotRunningError as d}from"./sqld-not-running-error.js";class R{async initialize({removeExisting:i,baseDbDir:a,runWithPragmaWalWriteOptimization:o,databaseName:s,additionalFolder:l,migrationsFolder:c}){n.info("Initializing local database client...");const m=n.startTiming(),{databasePath:r}=await p.prepareDatabasePath({baseDir:a,databaseName:s,additionalFolder:l,removeExisting:i}),t={url:`file:${r}`},e=await g.init(t,{runWithPragmaWalWriteOptimization:o});return await e.migrate(a,c),n.infoTime(m,"Local database client initialized"),{client:e,path:r}}}class x{#i;#t;constructor(i){this.#i=i?.skipLogs??!1,this.#t=this.#i?void 0:n}async initialize({removeExisting:i,baseDbDir:a,syncUrl:o,authToken:s,databaseName:l,additionalFolder:c,migrationsFolder:m}){this.#t?.info("Initializing remote database client...");const r=this.#t?.startTiming();return await f(async()=>{try{const{databasePath:t}=await p.prepareDatabasePath({baseDir:a,databaseName:l,additionalFolder:c,removeExisting:i}),e=await g.init({url:`file:${t}`,syncUrl:o,authToken:s});return await e.migrate(a,m),this.#t?.infoTime(r??"","Remote database client initialized"),{client:e,path:t}}catch(t){throw d.isSqldNotRunningError(t)?new d("SQLD server is not running yet, wait for production deployment",{cause:t}):t}},{maxRetries:3,retryStrategy:"exponential",delay:1e3,logger:this.#t,messages:{retry:"Retrying remote database client initialization",maxRetriesReached:"Max retries reached, remote database client initialization failed"}})}}export{R as LocalDatabaseInitializationStrategy,x as RemoteDatabaseInitializationStrategy};
@@ -1 +1 @@
1
- import{logger as r}from"../../tools/notifiers/logger.js";import{DatabaseConnectionFactory as a}from"./database-connection-factory.js";class e{static#e=!1;static async init(t){if(!(process.env.REDOCLY_LOCAL_DEV==="true"||process.env.CI==="true")&&!e.#e)try{await e.#t(t)==="PRECONNECTED"&&(e.#e=!0)}catch(o){r.error("Failed to preconnect to sqld remote database",o)}}static#t=async t=>await a.create("sqld-remote",{baseDbDir:t})?(r.info("Sqld remote database preconnected"),"PRECONNECTED"):(r.warn("Sqld remote database preconnect failed"),"NOT_PRECONNECTED")}export{e as DatabasePreconnectService};
1
+ import{logger as o}from"../../tools/notifiers/logger.js";import{envConfig as n}from"../../../config/env-config.js";import{DatabaseConnectionFactory as i}from"./database-connection-factory.js";class t{static#t=!1;static async init(e){if(!(n.REDOCLY_INTERNAL_DEV==="true"||n.CI==="true")&&!t.#t)try{await t.#e(e)==="PRECONNECTED"&&(t.#t=!0)}catch(r){o.error("Failed to preconnect to sqld remote database",r)}}static#e=async e=>await i.create("sqld-remote",{baseDbDir:e})?(o.info("Sqld remote database preconnected"),"PRECONNECTED"):(o.warn("Sqld remote database preconnect failed"),"NOT_PRECONNECTED")}export{t as DatabasePreconnectService};