@redocly/realm 0.135.0-next.7 → 0.136.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/dist/cli/build/analytics/collect-analytics.js +1 -1
  3. package/dist/cli/build/analytics/collectors/get-skills-usage.d.ts +3 -0
  4. package/dist/cli/build/analytics/collectors/get-skills-usage.js +1 -0
  5. package/dist/client/templates/openapi-docs/helpers.js +1 -1
  6. package/dist/constants/common.d.ts +8 -0
  7. package/dist/constants/common.js +1 -1
  8. package/dist/server/config/env-config.d.ts +2 -0
  9. package/dist/server/config/env-schema.d.ts +5 -0
  10. package/dist/server/config/env-schemas/feature-flags.d.ts +4 -0
  11. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  12. package/dist/server/constants/plugins/search.d.ts +1 -2
  13. package/dist/server/constants/plugins/search.js +1 -1
  14. package/dist/server/esbuild/plugins/on-rebuild.js +1 -1
  15. package/dist/server/fs/fs.js +1 -1
  16. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -1
  17. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/arazzo-entities-extractor.js +1 -1
  18. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/asyncapi-entities-extractor.js +1 -1
  19. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/graphql-entities-extractor.js +2 -2
  20. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
  21. package/dist/server/plugins/config-parser/loaders/redocly-config-loader.js +1 -1
  22. package/dist/server/plugins/lifecycle.js +2 -2
  23. package/dist/server/plugins/mcp/{docs-mcp/codemode → codemode}/build-tool-type-declarations.d.ts +1 -1
  24. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.d.ts +4 -0
  25. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +4 -0
  26. package/dist/server/plugins/mcp/codemode/capabilities/index.d.ts +3 -0
  27. package/dist/server/plugins/mcp/codemode/capabilities/index.js +1 -0
  28. package/dist/server/plugins/mcp/codemode/capabilities/registry.d.ts +4 -0
  29. package/dist/server/plugins/mcp/codemode/capabilities/registry.js +1 -0
  30. package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +13 -0
  31. package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +13 -0
  32. package/dist/server/plugins/mcp/codemode/capabilities/utils.js +7 -0
  33. package/dist/server/plugins/mcp/codemode/constants.d.ts +5 -0
  34. package/dist/server/plugins/mcp/codemode/constants.js +1 -0
  35. package/dist/server/plugins/mcp/codemode/invoke-tool.d.ts +4 -0
  36. package/dist/server/plugins/mcp/codemode/invoke-tool.js +1 -0
  37. package/dist/server/plugins/mcp/codemode/prompts.d.ts +6 -0
  38. package/dist/server/plugins/mcp/codemode/prompts.js +4 -0
  39. package/dist/server/plugins/mcp/codemode/sandbox/sandbox-polyfills.d.ts +3 -0
  40. package/dist/server/plugins/mcp/codemode/sandbox/sandbox-polyfills.js +100 -0
  41. package/dist/server/plugins/mcp/{docs-mcp/codemode → codemode/sandbox}/sandbox.d.ts +1 -1
  42. package/dist/server/plugins/mcp/codemode/sandbox/sandbox.js +15 -0
  43. package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +7 -0
  44. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +1 -0
  45. package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +5 -0
  46. package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -0
  47. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -0
  48. package/dist/server/plugins/mcp/codemode/types.d.ts +24 -0
  49. package/dist/server/plugins/mcp/codemode/types.js +0 -0
  50. package/dist/server/plugins/mcp/constants.d.ts +2 -0
  51. package/dist/server/plugins/mcp/constants.js +1 -1
  52. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +0 -4
  53. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  54. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
  55. package/dist/server/plugins/mcp/docs-mcp/utils.js +1 -1
  56. package/dist/server/plugins/mcp/gateway-mcp/eligibility.d.ts +30 -0
  57. package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -0
  58. package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.d.ts +13 -0
  59. package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.js +1 -0
  60. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.d.ts +12 -0
  61. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -0
  62. package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.d.ts +9 -0
  63. package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.js +1 -0
  64. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.d.ts +6 -0
  65. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -0
  66. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  67. package/dist/server/plugins/mcp/handlers/errors.d.ts +3 -21
  68. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  69. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
  70. package/dist/server/plugins/mcp/index.js +1 -1
  71. package/dist/server/plugins/mcp/servers/docs-server.d.ts +5 -10
  72. package/dist/server/plugins/mcp/servers/docs-server.js +1 -3
  73. package/dist/server/plugins/mcp/servers/mcp-server.d.ts +18 -0
  74. package/dist/server/plugins/mcp/servers/mcp-server.js +1 -0
  75. package/dist/server/plugins/mcp/types.d.ts +23 -8
  76. package/dist/server/plugins/mcp/utils/mode.d.ts +7 -0
  77. package/dist/server/plugins/mcp/utils/mode.js +1 -0
  78. package/dist/server/plugins/mcp/utils/xmcp-utils.d.ts +12 -60
  79. package/dist/server/plugins/mcp/utils/xmcp-utils.js +1 -1
  80. package/dist/server/plugins/mcp/utils.d.ts +8 -0
  81. package/dist/server/plugins/mcp/utils.js +1 -1
  82. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  83. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +15 -3
  84. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  85. package/dist/server/plugins/openapi-docs/index.js +1 -1
  86. package/dist/server/plugins/search/engines/search-engine.d.ts +2 -1
  87. package/dist/server/plugins/search/index.js +1 -1
  88. package/dist/server/plugins/skills/discover-skills.d.ts +17 -0
  89. package/dist/server/plugins/skills/discover-skills.js +1 -0
  90. package/dist/server/plugins/skills/index.d.ts +3 -0
  91. package/dist/server/plugins/skills/index.js +1 -0
  92. package/dist/server/plugins/skills/utils/parse-skill.d.ts +18 -0
  93. package/dist/server/plugins/skills/utils/parse-skill.js +1 -0
  94. package/dist/server/plugins/sso/index.js +1 -1
  95. package/dist/server/store.d.ts +4 -0
  96. package/dist/server/store.js +1 -1
  97. package/dist/server/types/plugins/common.d.ts +3 -0
  98. package/dist/server/types/plugins/search.d.ts +0 -1
  99. package/dist/server/types/plugins/skills.d.ts +16 -0
  100. package/dist/server/types/plugins/skills.js +0 -0
  101. package/dist/server/utils/cookie.d.ts +3 -0
  102. package/dist/server/utils/cookie.js +1 -1
  103. package/dist/server/utils/skills/can-access-skill.d.ts +9 -0
  104. package/dist/server/utils/skills/can-access-skill.js +1 -0
  105. package/dist/server/utils/skills/get-accessible-skills.d.ts +5 -0
  106. package/dist/server/utils/skills/get-accessible-skills.js +1 -0
  107. package/dist/server/utils/skills/get-skill-url.d.ts +2 -0
  108. package/dist/server/utils/skills/get-skill-url.js +1 -0
  109. package/dist/server/web-server/auth.js +4 -4
  110. package/dist/server/web-server/middleware/corsMiddleware.d.ts +1 -0
  111. package/dist/server/web-server/middleware/corsMiddleware.js +1 -1
  112. package/dist/server/web-server/middleware/ensureSearchData.js +1 -1
  113. package/dist/server/web-server/routes/auth.js +1 -1
  114. package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.d.ts +305 -256
  115. package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.d.ts +46 -39
  116. package/dist/server/web-server/routes/health.js +1 -1
  117. package/dist/server/web-server/routes/index.js +1 -1
  118. package/dist/server/web-server/routes/mcp-routes/a2a.d.ts +10 -0
  119. package/dist/server/web-server/routes/mcp-routes/a2a.js +1 -0
  120. package/dist/server/web-server/routes/mcp-routes/agent-card.d.ts +4 -0
  121. package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -0
  122. package/dist/server/web-server/routes/mcp-routes/constants.d.ts +14 -0
  123. package/dist/server/web-server/routes/mcp-routes/constants.js +1 -0
  124. package/dist/server/web-server/routes/mcp-routes/mcp-routes.d.ts +1 -1
  125. package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
  126. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.d.ts +4 -0
  127. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -0
  128. package/dist/server/web-server/routes/mcp-routes/types.d.ts +34 -0
  129. package/dist/server/web-server/routes/mcp-routes/types.js +0 -0
  130. package/dist/server/web-server/routes/mcp-routes/utils/build-agent-card.d.ts +10 -0
  131. package/dist/server/web-server/routes/mcp-routes/utils/build-agent-card.js +1 -0
  132. package/dist/server/web-server/routes/page-data.js +1 -1
  133. package/dist/server/web-server/routes/skills/build-skills-index.d.ts +4 -0
  134. package/dist/server/web-server/routes/skills/build-skills-index.js +1 -0
  135. package/dist/server/web-server/routes/skills/constants.d.ts +4 -0
  136. package/dist/server/web-server/routes/skills/constants.js +1 -0
  137. package/dist/server/web-server/routes/skills/skill-markdown.d.ts +4 -0
  138. package/dist/server/web-server/routes/skills/skill-markdown.js +1 -0
  139. package/dist/server/web-server/routes/skills/skills-index.d.ts +4 -0
  140. package/dist/server/web-server/routes/skills/skills-index.js +1 -0
  141. package/dist/server/web-server/routes/skills/skills-routes.d.ts +4 -0
  142. package/dist/server/web-server/routes/skills/skills-routes.js +1 -0
  143. package/dist/server/web-server/routes/skills/types.d.ts +12 -0
  144. package/dist/server/web-server/routes/skills/types.js +0 -0
  145. package/dist/server/web-server/utils/resolve-public-base-url.d.ts +4 -0
  146. package/dist/server/web-server/utils/resolve-public-base-url.js +1 -0
  147. package/dist/server/web-server/utils.js +1 -1
  148. package/dist/server/workers/api-routes-worker-pool.js +1 -1
  149. package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
  150. package/dist/server/workers/scorecards-worker-pool.js +1 -1
  151. package/dist/server/workers/worker-pool.d.ts +1 -0
  152. package/dist/server/workers/worker-pool.js +1 -1
  153. package/package.json +10 -10
  154. package/dist/server/plugins/mcp/docs-mcp/codemode/prompts.d.ts +0 -5
  155. package/dist/server/plugins/mcp/docs-mcp/codemode/prompts.js +0 -4
  156. package/dist/server/plugins/mcp/docs-mcp/codemode/sandbox.js +0 -7
  157. package/dist/server/plugins/mcp/docs-mcp/codemode/types.d.ts +0 -9
  158. package/dist/server/plugins/mcp/docs-mcp/tools/execute.js +0 -1
  159. package/dist/server/plugins/mcp/mode.d.ts +0 -9
  160. package/dist/server/plugins/mcp/mode.js +0 -1
  161. /package/dist/server/plugins/mcp/{docs-mcp/codemode → codemode}/build-tool-type-declarations.js +0 -0
  162. /package/dist/server/plugins/mcp/{docs-mcp/codemode → codemode/capabilities}/types.js +0 -0
  163. /package/dist/server/plugins/mcp/{docs-mcp → codemode}/tools/execute.d.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,88 @@
1
1
  # @redocly/realm
2
2
 
3
+ ## 0.136.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a749e28ae3c: Added support for agent skills placed under the `@skills` folder.
8
+ - a749e28ae3c: Added support for A2A agent card and MCP server card.
9
+
10
+ ### Patch Changes
11
+
12
+ - 56e4931831a: Allowed the `redocly` special value in the `access.idps` config option to offer the standard Redocly login (email/password and Social Login providers) alongside specific identity providers.
13
+ - 6e91bb8a540: Fixed SSO logout to require re-authentication with the identity provider, preventing automatic login immediately after logout.
14
+ Session expiry continues to re-authenticate silently.
15
+ - d05d0e5d302: Updated `@redocly/openapi-core` to version `2.39.0`.
16
+ - Updated dependencies [7630938561e]
17
+ - Updated dependencies [83d149073d]
18
+ - Updated dependencies [d05d0e5d302]
19
+ - Updated dependencies [a749e28ae3c]
20
+ - @redocly/theme@0.68.0-next.0
21
+ - @redocly/openapi-docs@3.24.0-next.0
22
+ - @redocly/realm-asyncapi-sdk@0.14.0-next.0
23
+ - @redocly/asyncapi-docs@1.13.0-next.0
24
+ - @redocly/graphql-docs@1.13.0-next.0
25
+ - @redocly/portal-plugin-mock-server@0.21.0-next.0
26
+
27
+ ## 0.135.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 76189db569: Added `GraphQL` support to Docs MCP server.
32
+ - d88f0270a1: Adds validation and logging for mutually exclusive `access.idps` and `access.sso` in `redocly.yaml`.
33
+ - 736405a589: Added `title` attribute to the `json-schema` Markdoc tag to display a heading above the rendered schema.
34
+ - ed259391ab: Updated the `img` Markdoc tag with `framed`, `caption`, and `images` properties.
35
+ - a614929940: Added annotations to the MCP tools.
36
+ - 8358282927: Added support for the `openapi-code-sample` and `openapi-response-sample` Markdoc tags in `llms.txt`.
37
+ - 914428551a: Added a setup instructions page which is displayed when users open the Docs MCP server URL `/mcp` in a browser.
38
+
39
+ ### Patch Changes
40
+
41
+ - d3d0786f4b: Fixed an issue where the Docs MCP server `search` tool returned results from all locales.
42
+ After the fix, search results are filtered by the requested locale, defaulting to the project's default locale.
43
+ - b93a2a6166: Fixed an issue where the login button did not return users to their previous page after signing in.
44
+ - 08dea43493: Fixed scroll synchronization between the Webview and editor: dragging the Webview scrollbar scrolls the editor, and mouse-wheel scrolling maintains alignment.
45
+ - 612676ed50: Fixed an issue where setting an empty string in `openapi.corsProxyUrl` did not disable the CORS proxy server.
46
+ - 63244207e9: Fixed an issue where search results prioritized matches in page text over matches in page titles.
47
+ - 054f8d0400: Fixed issues in the breadcrumbs dropdown component where the chevron icon did not change and a focus outline was added on click.
48
+ - 413e45fabe: Fixed an issue where the selected version persisted across versioned content sets instead of resetting to each set's default version.
49
+ - ed64b3849b: Fixed an issue where italic or bold text inside headings was excluded from generated anchor links.
50
+ - f07927efd7: Fixed an issue where Markdown output for `llms.txt` was missing blank lines after Markdoc tags.
51
+ - 735eee33a0: Fixed an issue where MCP page actions were hidden on pages for which `llms.txt` files weren't generated.
52
+ - 09ad3982eb: Updated `@redocly/openapi-core` to version `2.37.0`.
53
+ - 2115596347: Fixed layout shift in the sidebar that happened when users selected a sidebar item.
54
+ - 4267dc2f1e: Fixed an issue where the Markdoc `tabs` tag crashed if it contained content without a `label` attribute.
55
+ - e811ac08af: Fixed an issue where API functions could stop working and return errors after a function had been edited, added, or renamed during preview.
56
+ Changes are picked up automatically.
57
+ A full restart of Webview is no longer required.
58
+ - f52a2b04b5: Fixed an issue where the deprecated badge didn't appear in search dialog results for the Typesense search engine.
59
+ - c202a2acd4: Improved HTTP caching for public and private pages.
60
+ - ead3c5da07: Fixed an issue where search results were incorrectly scoped to the selected product, version, or filter.
61
+ This issue occurred when names of products, versions or filters included the same word, for example: `Version` and `Version 2`.
62
+ - Updated dependencies [359a05ad5d]
63
+ - Updated dependencies [46970189d8]
64
+ - Updated dependencies [5f5fcd52f7]
65
+ - Updated dependencies [63244207e9]
66
+ - Updated dependencies [054f8d0400]
67
+ - Updated dependencies [9df2991666]
68
+ - Updated dependencies [735eee33a0]
69
+ - Updated dependencies [09ad3982eb]
70
+ - Updated dependencies [4800c0c1f2]
71
+ - Updated dependencies [2115596347]
72
+ - Updated dependencies [4267dc2f1e]
73
+ - Updated dependencies [ed259391ab]
74
+ - Updated dependencies [2d154630f3]
75
+ - Updated dependencies [8358282927]
76
+ - Updated dependencies [914428551a]
77
+ - Updated dependencies [33b827ed76]
78
+ - @redocly/realm-asyncapi-sdk@0.13.0
79
+ - @redocly/theme@0.67.0
80
+ - @redocly/openapi-docs@3.23.0
81
+ - @redocly/portal-plugin-mock-server@0.20.0
82
+ - @redocly/asyncapi-docs@1.12.0
83
+ - @redocly/graphql-docs@1.12.0
84
+ - @redocly/portal-legacy-ui@0.18.0
85
+
3
86
  ## 0.135.0-next.7
4
87
 
5
88
  ### Minor Changes
@@ -1 +1 @@
1
- import{getApiFunctionsUsage as f}from"./collectors/get-api-functions-usage.js";import{getAsyncApiUsage as l}from"./collectors/get-async-api-usage.js";import{getConfigStatsUsage as c}from"./collectors/get-config-stats-usage.js";import{getFileExtensionsUsage as d}from"./collectors/get-file-extensions-usage.js";import{getFrontmatterUsage as U}from"./collectors/get-frontmatter-usage.js";import{getMarkdocUsage as p}from"./collectors/get-markdoc-usage.js";import{getNestedConfigsUsage as u}from"./collectors/get-nested-configs-usage.js";import{getProcessedConfigStatsUsage as S}from"./collectors/get-processed-config-stats-usage.js";import{getRefsUsage as C}from"./collectors/get-refs-usage.js";import{getThemeFolderUsage as x}from"./collectors/get-theme-folder-usage.js";import{telemetry as y}from"../../telemetry/index.js";async function w(r,i){const n=[f,l,c,d,U,p,u,S,C,x],g=await Promise.allSettled(n.map(t=>t({store:r,context:i}))),e={},s={};for(const t of g)if(t.status==="fulfilled"){const{name:o,value:a,version:m}=t.value;a&&(e[o]=a,s[o]=m)}y.sendBuildMessage({usageStats:e.usageStats,asyncApiUsage:e.asyncApiUsage,buildContext:e.buildContext,fileExtensions:e.fileExtensions,frontmatterUsage:e.frontmatterUsage,markdocUsage:e.markdocUsage,processedBuildContext:e.processedBuildContext,nestedConfigStats:e.nestedConfigStats,refsUsageStats:e.refsUsageStats,themeFolderUsage:e.themeFolderUsage,versions:JSON.stringify(s)})}export{w as collectAnalytics};
1
+ import{getApiFunctionsUsage as f}from"./collectors/get-api-functions-usage.js";import{getAsyncApiUsage as c}from"./collectors/get-async-api-usage.js";import{getConfigStatsUsage as U}from"./collectors/get-config-stats-usage.js";import{getFileExtensionsUsage as d}from"./collectors/get-file-extensions-usage.js";import{getFrontmatterUsage as p}from"./collectors/get-frontmatter-usage.js";import{getMarkdocUsage as u}from"./collectors/get-markdoc-usage.js";import{getNestedConfigsUsage as S}from"./collectors/get-nested-configs-usage.js";import{getProcessedConfigStatsUsage as C}from"./collectors/get-processed-config-stats-usage.js";import{getRefsUsage as x}from"./collectors/get-refs-usage.js";import{getSkillsUsage as y}from"./collectors/get-skills-usage.js";import{getThemeFolderUsage as k}from"./collectors/get-theme-folder-usage.js";import{telemetry as v}from"../../telemetry/index.js";async function O(i,r){const g=[f,c,U,d,p,u,S,C,x,y,k],n=await Promise.allSettled(g.map(t=>t({store:i,context:r}))),e={},s={};for(const t of n)if(t.status==="fulfilled"){const{name:o,value:a,version:l}=t.value;a&&(e[o]=a,s[o]=l)}const m={usageStats:e.usageStats,asyncApiUsage:e.asyncApiUsage,buildContext:e.buildContext,fileExtensions:e.fileExtensions,frontmatterUsage:e.frontmatterUsage,markdocUsage:e.markdocUsage,processedBuildContext:e.processedBuildContext,nestedConfigStats:e.nestedConfigStats,refsUsageStats:e.refsUsageStats,skillsUsage:e.skillsUsage,themeFolderUsage:e.themeFolderUsage,versions:JSON.stringify(s)};v.sendBuildMessage(m)}export{O as collectAnalytics};
@@ -0,0 +1,3 @@
1
+ import type { Collector } from '../collect-analytics.js';
2
+ export declare const getSkillsUsage: Collector;
3
+ //# sourceMappingURL=get-skills-usage.d.ts.map
@@ -0,0 +1 @@
1
+ import e from"node:path";import{stat as n}from"node:fs/promises";import{AGENT_CARD_SLUG as s}from"../../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as o}from"../../../../server/constants/common.js";const g=async({store:t})=>{const i=t.getSkills().length.toString(),r=await a(e.join(t.contentDir,o,...s.split("/").filter(Boolean)));return{version:"1",name:"skillsUsage",value:JSON.stringify({skills:i,agentCardOverride:r})}};async function a(t){try{return(await n(t)).isFile()}catch{return!1}}export{g as getSkillsUsage};
@@ -1,4 +1,4 @@
1
- import{useMemo as f}from"react";import{components as g}from"@redocly-markdoc/components";import{schema as c}from"@redocly-markdoc/schema";import{Ast as d}from"@markdoc/markdoc";import{PageNavigation as h}from"@redocly/theme/components/PageNavigation/PageNavigation";import{tags as _,components as y}from"@redocly/theme/markdoc/default";import{Breadcrumbs as P}from"@redocly/theme/components/Breadcrumbs/Breadcrumbs";import{withPathPrefix as m}from"@redocly/theme/core/utils";import{ServerRoutes as u}from"../../../constants/api.js";import{OPENAPI_DOCS_TEMPLATE_ID as w}from"../../../constants/common.js";import{isBrowser as S}from"../../../utils/env/is-browser.js";import*as O from"../../../markdoc/nodes/index.js";import v from"../../../markdoc/tags/index.js";import{normalizeCustomTags as C}from"../../../markdoc/helpers/normalize-custom-tags.js";import*as T from"../../app/markdoc/custom-components/index.js";import{usePageData as x,useSidebarSiblingsData as A}from"../../providers/page-data/hooks";import{telemetry as E}from"../../app/telemetry/index.js";import{getMockServerDocsConfig as R}from"./mock-server-config.js";function X(o="",r="",t="/"){return o.endsWith(t)&&(o=o.slice(0,-t.length)),r.startsWith(t)&&(r=r.slice(t.length)),!o||!r?o+r:o+t+r}function b(o){if(o)return Object.entries(o).reduce((r,[t,n])=>(r[t]=d.fromJSON(JSON.stringify(n)),r),{})}function Z(o,{markdown:r,baseSlug:t}){return f(()=>{const i=S();if(o.options.oAuth2RedirectURI=i?`${window.location.origin}${m(u.REPLAY_OAUTH2_CALLBACK)}`:null,o.options.routingBasePath=m(t),o.options.mockServer=R(o.options.mockServer,t),o.options.corsProxyUrl===void 0){const e=m(`${u.CORS_PROXY}/`);o.options.corsProxyUrl=i?new URL(e,window.location.origin).toString():e}o.options.scrollYOffset=i?parseInt(getComputedStyle(document.documentElement).getPropertyValue("--navbar-height"),10):0,o.options.markdocOptions={tags:{...v,..._,...C(c?.tags??{})},nodes:{...O,...c?.nodes??{}},functions:{...c?.functions??{}},components:{...T,...y,...g,...globalThis.__LOADER.markdocComponents},...r,partials:b(r?.partials)},o.options.unstable_hooks={...o.options.unstable_hooks,MiddlePanelFooter:()=>{const{templateId:e}=x()||{},{nextPage:s,prevPage:a}=A()||{};return e===w?null:h({nextPage:s,prevPage:a})},MiddlePanelHeader:()=>P({})};const l={codeSamplesLanguageSwitch:"samples_language_switch",codeSamplesCopy:"code_samples_copy",panelToggle:"panel_toggle",targetServerSwitch:"target_server_switch",tryItOpen:"try_it_toggle",tryItSent:"try_it_sent"},p={};for(const[e,s]of Object.entries(l)){const a=U(o.options.events?.[e]);p[e]=F(a,s)}return o.options.events=p,o},[o,r,t])}function U(o){if(typeof window>"u")return null;if(typeof o=="function")return o;if(typeof o!="string")return null;try{const r=o.trim();if(!r.match(/^(\([^)]*\)\s*=>\s*.+|[a-zA-Z_$][\w$]*\s*=>\s*.+)$/))throw new Error("Invalid function format. Only arrow functions allowed.");if(["eval","Function","constructor","prototype","__proto__","import","require","process","global","window","document"].some(i=>r.includes(i)))throw new Error("Function contains prohibited keywords");return new Function("event",`
1
+ import{useMemo as f}from"react";import{components as d}from"@redocly-markdoc/components";import{schema as c}from"@redocly-markdoc/schema";import{Ast as g}from"@markdoc/markdoc";import{PageNavigation as h}from"@redocly/theme/components/PageNavigation/PageNavigation";import{tags as _,components as y}from"@redocly/theme/markdoc/default";import{Breadcrumbs as P}from"@redocly/theme/components/Breadcrumbs/Breadcrumbs";import{withPathPrefix as m}from"@redocly/theme/core/utils";import{ServerRoutes as u}from"../../../constants/api.js";import{OPENAPI_DOCS_TEMPLATE_ID as w}from"../../../constants/common.js";import{isBrowser as S}from"../../../utils/env/is-browser.js";import*as O from"../../../markdoc/nodes/index.js";import v from"../../../markdoc/tags/index.js";import{normalizeCustomTags as C}from"../../../markdoc/helpers/normalize-custom-tags.js";import*as T from"../../app/markdoc/custom-components/index.js";import{usePageData as x,useSidebarSiblingsData as A}from"../../providers/page-data/hooks";import{telemetry as E}from"../../app/telemetry/index.js";import{getMockServerDocsConfig as R}from"./mock-server-config.js";function X(o="",r="",t="/"){return o.endsWith(t)&&(o=o.slice(0,-t.length)),r.startsWith(t)&&(r=r.slice(t.length)),!o||!r?o+r:o+t+r}function b(o){if(o)return Object.entries(o).reduce((r,[t,n])=>(r[t]=g.fromJSON(JSON.stringify(n)),r),{})}function Z(o,{markdown:r,baseSlug:t}){return f(()=>{const i=S();if(o.options.oAuth2RedirectURI=i?`${window.location.origin}${m(u.REPLAY_OAUTH2_CALLBACK)}`:void 0,o.options.routingBasePath=m(t),o.options.mockServer=R(o.options.mockServer,t),o.options.corsProxyUrl===void 0){const e=m(`${u.CORS_PROXY}/`);o.options.corsProxyUrl=i?new URL(e,window.location.origin).toString():e}o.options.scrollYOffset=i?parseInt(getComputedStyle(document.documentElement).getPropertyValue("--navbar-height"),10):0,o.options.markdocOptions={tags:{...v,..._,...C(c?.tags??{})},nodes:{...O,...c?.nodes??{}},functions:{...c?.functions??{}},components:{...T,...y,...d,...globalThis.__LOADER.markdocComponents},...r,partials:b(r?.partials)},o.options.unstable_hooks={...o.options.unstable_hooks,MiddlePanelFooter:()=>{const{templateId:e}=x()||{},{nextPage:s,prevPage:a}=A()||{};return e===w?null:h({nextPage:s,prevPage:a})},MiddlePanelHeader:()=>P({})};const l={codeSamplesLanguageSwitch:"samples_language_switch",codeSamplesCopy:"code_samples_copy",panelToggle:"panel_toggle",targetServerSwitch:"target_server_switch",tryItOpen:"try_it_toggle",tryItSent:"try_it_sent"},p={};for(const[e,s]of Object.entries(l)){const a=U(o.options.events?.[e]);p[e]=F(a,s)}return o.options.events=p,o},[o,r,t])}function U(o){if(typeof window>"u")return null;if(typeof o=="function")return o;if(typeof o!="string")return null;try{const r=o.trim();if(!r.match(/^(\([^)]*\)\s*=>\s*.+|[a-zA-Z_$][\w$]*\s*=>\s*.+)$/))throw new Error("Invalid function format. Only arrow functions allowed.");if(["eval","Function","constructor","prototype","__proto__","import","require","process","global","window","document"].some(i=>r.includes(i)))throw new Error("Function contains prohibited keywords");return new Function("event",`
2
2
  'use strict';
3
3
  const userFn = ${r};
4
4
  return userFn(event);
@@ -6,6 +6,7 @@ export declare const AuthCookieNames: {
6
6
  readonly FEDERATED_ACCESS_TOKEN: 'federated_access_token';
7
7
  readonly FEDERATED_ID_TOKEN: 'federated_id_token';
8
8
  };
9
+ export declare const POST_LOGOUT_COOKIE_NAME = "post_logout";
9
10
  export declare const OPENAPI_DOCS_TEMPLATE_ID = "openapi_docs";
10
11
  export declare const ASYNC_API_DOCS_TEMPLATE_ID = "asyncapi_docs";
11
12
  export declare const GRAPHQL_TEMPLATE_ID = "graphql_docs";
@@ -18,6 +19,7 @@ export declare const PUBLIC_RBAC_SCOPE_ITEM: {
18
19
  };
19
20
  export declare const REQUIRED_OIDC_SCOPES: string[];
20
21
  export declare const DEFAULT_COOKIE_EXPIRATION: number;
22
+ export declare const POST_LOGOUT_COOKIE_EXPIRATION: number;
21
23
  export declare const DEFAULT_ANONYMOUS_VISITOR_TEAM = "anonymous";
22
24
  export declare const DEFAULT_AUTHENTICATED_TEAM = "authenticated";
23
25
  export declare const DEFAULT_RBAC_SCOPE = "**";
@@ -26,6 +28,12 @@ export declare const TRANSLATIONS_FILE_NAME = "translations.yaml";
26
28
  export declare const CONFIG_FILE_NAME = "redocly.yaml";
27
29
  export declare const DEFAULT_THEME_NAME = "@redocly/theme";
28
30
  export declare const USER_THEME_ALIAS = "@theme";
31
+ export declare const USER_SKILLS_ALIAS = "@skills";
32
+ export declare const USER_SKILL_FILENAME = "SKILL.md";
33
+ export declare const AGENT_SKILLS_BASE = "/.well-known/agent-skills";
34
+ export declare const AGENT_CARD_SLUG = "/.well-known/agent-card.json";
35
+ export declare const A2A_SLUG = "/a2a";
36
+ export declare const MCP_SERVER_CARD_SLUG = "/.well-known/mcp/server-card.json";
29
37
  export declare const GLOBAL_DATA_URL = "/app-data.json";
30
38
  export declare const EJECT_COMPONENT_URL = "/eject-component";
31
39
  export declare enum cliCommandNames {
@@ -1 +1 @@
1
- const s={AUTHORIZATION:"authorization",IDP_ID_TOKEN:"idp_id_token",IDP_ACCESS_TOKEN:"idp_access_token",FEDERATED_ACCESS_TOKEN:"federated_access_token",FEDERATED_ID_TOKEN:"federated_id_token"},n="openapi_docs",_="asyncapi_docs",E="graphql_docs",p="/_spec-gql",i="markdoc",A="tags",c="*",d={[c]:"read"},O=["openid","email"],T=1440*60,I="anonymous",R="authenticated",S="**",L="Reunite",l="translations.yaml",C="redocly.yaml",x="@redocly/theme",D="@theme",P="/app-data.json",N="/eject-component";var t;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(t||(t={}));var e;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(e||(e={}));var r;(function(o){o.AI_SEARCH="aiSearch"})(r||(r={}));const m="/login",u="/invite",g={AUTH0_PASS:"/auth/auth0-pass"},U={NotExist:"ENOENT"},M="default_locale",h="sidebar-",b="PUBLIC_",F="branch.",v=["BROKEN_LINK","MARKDOC","RESOLVE"],k=["logo","navbar","products","footer","sidebar","scripts","links","feedback","search","aiAssistant","colorMode","palette","navigation","codeSnippet","markdown","openapi","graphql","analytics","userMenu","versionPicker","breadcrumbs","catalog","entitiesCatalog","scorecard","scorecards","scorecardClassic","mcp","banner"],a="redocly_category",H="redocly_product",y="redocly_version",G="redocly_teams",B=a,f={asyncapi:"asyncapi",apiFunctions:"apiFunctions",reactPages:"reactPages",catalog:"catalog",catalogClassic:"catalogClassic",lint:"lint",scorecard:"scorecard",scorecards:"scorecards",l10n:"l10n",openapi:"openapi",graphql:"graphql",markdown:"markdown",devOnboarding:"devOnboarding",seo:"seo",redirects:"redirects",customPlugins:"customPlugins",themeEjecting:"themeEjecting",products:"products",breadcrumbs:"breadcrumbs",mockServer:"mockServer",sso:"sso",rbac:"rbac",analytics:"analytics",removeAttribution:"removeAttribution",advancedSearch:"advancedSearch",soap:"soap",ssoDirect:"ssoDirect",codeWalkthrough:"codeWalkthrough",aiSearchLimit:"aiSearchLimit",kvStorageLimit:"kvStorageLimit",mcp:"mcp",banner:"banner"};export{_ as ASYNC_API_DOCS_TEMPLATE_ID,s as AuthCookieNames,F as BRANCH_ENV_PREFIX,C as CONFIG_FILE_NAME,i as CUSTOM_MARKDOC_OPTIONS_PATH,A as CUSTOM_MARKDOC_TAGS_PATH,I as DEFAULT_ANONYMOUS_VISITOR_TEAM,R as DEFAULT_AUTHENTICATED_TEAM,T as DEFAULT_COOKIE_EXPIRATION,M as DEFAULT_LOCALE_PLACEHOLDER,S as DEFAULT_RBAC_SCOPE,L as DEFAULT_SSO_IDP_TITLE,x as DEFAULT_THEME_NAME,m as DEV_LOGIN_SLUG,N as EJECT_COMPONENT_URL,g as ExternalRoutes,f as FEATURE,e as FEEDBACK_TYPES,U as FsErrors,P as GLOBAL_DATA_URL,p as GRAPHQL_SPEC_SLUG,E as GRAPHQL_TEMPLATE_ID,u as INVITE_SLUG,v as MARKDOC_ERROR_TYPES,n as OPENAPI_DOCS_TEMPLATE_ID,b as PUBLIC_ENV_PREFIX,d as PUBLIC_RBAC_SCOPE_ITEM,c as RBAC_ALL_OTHER_TEAMS,O as REQUIRED_OIDC_SCOPES,r as RbacFeatures,a as SEARCH_CATEGORY_FIELD,B as SEARCH_GROUP_FACET_FIELD,H as SEARCH_PRODUCT_FIELD,G as SEARCH_RBAC_FIELD,y as SEARCH_VERSION_FIELD,h as SIDEBAR_PREFIX,l as TRANSLATIONS_FILE_NAME,k as UI_ACCESSIBLE_CONFIG_PROPS,D as USER_THEME_ALIAS,t as cliCommandNames};
1
+ const a={AUTHORIZATION:"authorization",IDP_ID_TOKEN:"idp_id_token",IDP_ACCESS_TOKEN:"idp_access_token",FEDERATED_ACCESS_TOKEN:"federated_access_token",FEDERATED_ID_TOKEN:"federated_id_token"},n="post_logout",_="openapi_docs",E="asyncapi_docs",p="graphql_docs",A="/_spec-gql",i="markdoc",S="tags",c="*",L={[c]:"read"},O=["openid","email"],d=1440*60,I=720*60*60,T="anonymous",R="authenticated",l="**",C="Reunite",x="translations.yaml",P="redocly.yaml",D="@redocly/theme",N="@theme",m="@skills",U="SKILL.md",u="/.well-known/agent-skills",g="/.well-known/agent-card.json",M="/a2a",h="/.well-known/mcp/server-card.json",F="/app-data.json",b="/eject-component";var t;(function(o){o.BUILD="build",o.DEVELOP="develop",o.PREPARE="prepare"})(t||(t={}));var e;(function(o){o.RATING="rating",o.SENTIMENT="sentiment",o.COMMENT="comment",o.MOOD="mood",o.PROBLEM="problem",o.SCALE="scale"})(e||(e={}));var r;(function(o){o.AI_SEARCH="aiSearch"})(r||(r={}));const k="/login",v="/invite",G={AUTH0_PASS:"/auth/auth0-pass"},H={NotExist:"ENOENT"},y="default_locale",K="sidebar-",B="PUBLIC_",w="branch.",V=["BROKEN_LINK","MARKDOC","RESOLVE"],f=["logo","navbar","products","footer","sidebar","scripts","links","feedback","search","aiAssistant","colorMode","palette","navigation","codeSnippet","markdown","openapi","graphql","analytics","userMenu","versionPicker","breadcrumbs","catalog","entitiesCatalog","scorecard","scorecards","scorecardClassic","mcp","banner"],s="redocly_category",j="redocly_product",q="redocly_version",X="redocly_teams",Q=s,W={asyncapi:"asyncapi",apiFunctions:"apiFunctions",reactPages:"reactPages",catalog:"catalog",catalogClassic:"catalogClassic",lint:"lint",scorecard:"scorecard",scorecards:"scorecards",l10n:"l10n",openapi:"openapi",graphql:"graphql",markdown:"markdown",devOnboarding:"devOnboarding",seo:"seo",redirects:"redirects",customPlugins:"customPlugins",themeEjecting:"themeEjecting",products:"products",breadcrumbs:"breadcrumbs",mockServer:"mockServer",sso:"sso",rbac:"rbac",analytics:"analytics",removeAttribution:"removeAttribution",advancedSearch:"advancedSearch",soap:"soap",ssoDirect:"ssoDirect",codeWalkthrough:"codeWalkthrough",aiSearchLimit:"aiSearchLimit",kvStorageLimit:"kvStorageLimit",mcp:"mcp",banner:"banner"};export{M as A2A_SLUG,g as AGENT_CARD_SLUG,u as AGENT_SKILLS_BASE,E as ASYNC_API_DOCS_TEMPLATE_ID,a as AuthCookieNames,w as BRANCH_ENV_PREFIX,P as CONFIG_FILE_NAME,i as CUSTOM_MARKDOC_OPTIONS_PATH,S as CUSTOM_MARKDOC_TAGS_PATH,T as DEFAULT_ANONYMOUS_VISITOR_TEAM,R as DEFAULT_AUTHENTICATED_TEAM,d as DEFAULT_COOKIE_EXPIRATION,y as DEFAULT_LOCALE_PLACEHOLDER,l as DEFAULT_RBAC_SCOPE,C as DEFAULT_SSO_IDP_TITLE,D as DEFAULT_THEME_NAME,k as DEV_LOGIN_SLUG,b as EJECT_COMPONENT_URL,G as ExternalRoutes,W as FEATURE,e as FEEDBACK_TYPES,H as FsErrors,F as GLOBAL_DATA_URL,A as GRAPHQL_SPEC_SLUG,p as GRAPHQL_TEMPLATE_ID,v as INVITE_SLUG,V as MARKDOC_ERROR_TYPES,h as MCP_SERVER_CARD_SLUG,_ as OPENAPI_DOCS_TEMPLATE_ID,I as POST_LOGOUT_COOKIE_EXPIRATION,n as POST_LOGOUT_COOKIE_NAME,B as PUBLIC_ENV_PREFIX,L as PUBLIC_RBAC_SCOPE_ITEM,c as RBAC_ALL_OTHER_TEAMS,O as REQUIRED_OIDC_SCOPES,r as RbacFeatures,s as SEARCH_CATEGORY_FIELD,Q as SEARCH_GROUP_FACET_FIELD,j as SEARCH_PRODUCT_FIELD,X as SEARCH_RBAC_FIELD,q as SEARCH_VERSION_FIELD,K as SIDEBAR_PREFIX,x as TRANSLATIONS_FILE_NAME,f as UI_ACCESSIBLE_CONFIG_PROPS,m as USER_SKILLS_ALIAS,U as USER_SKILL_FILENAME,N as USER_THEME_ALIAS,t as cliCommandNames};
@@ -53,6 +53,7 @@ declare function loadEnvConfig(): {
53
53
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
54
54
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
55
55
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: boolean | undefined;
56
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: boolean | undefined;
56
57
  SEARCH_DEV_REINIT?: string | undefined;
57
58
  SEARCH_DEV_DEBUG: boolean;
58
59
  TYPESENSE_API_URL?: string | undefined;
@@ -132,6 +133,7 @@ export declare const envConfig: {
132
133
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
133
134
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
134
135
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: boolean | undefined;
136
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: boolean | undefined;
135
137
  SEARCH_DEV_REINIT?: string | undefined;
136
138
  SEARCH_DEV_DEBUG: boolean;
137
139
  TYPESENSE_API_URL?: string | undefined;
@@ -57,6 +57,7 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
57
57
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL: z.ZodOptional<z.ZodString>;
58
58
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT: z.ZodOptional<z.ZodString>;
59
59
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
60
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
60
61
  } & {
61
62
  SEARCH_DEV_REINIT: z.ZodOptional<z.ZodString>;
62
63
  SEARCH_DEV_DEBUG: z.ZodEffects<z.ZodDefault<z.ZodEnum<["true", "false"]>>, boolean, "false" | "true" | undefined>;
@@ -133,6 +134,7 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
133
134
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
134
135
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
135
136
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: boolean | undefined;
137
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: boolean | undefined;
136
138
  SEARCH_DEV_REINIT?: string | undefined;
137
139
  SEARCH_DEV_DEBUG: boolean;
138
140
  TYPESENSE_API_URL?: string | undefined;
@@ -202,6 +204,7 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
202
204
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
203
205
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
204
206
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: "false" | "true" | undefined;
207
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: "false" | "true" | undefined;
205
208
  SEARCH_DEV_REINIT?: string | undefined;
206
209
  SEARCH_DEV_DEBUG?: "false" | "true" | undefined;
207
210
  TYPESENSE_API_URL?: string | undefined;
@@ -271,6 +274,7 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
271
274
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
272
275
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
273
276
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: boolean | undefined;
277
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: boolean | undefined;
274
278
  SEARCH_DEV_REINIT?: string | undefined;
275
279
  SEARCH_DEV_DEBUG: boolean;
276
280
  TYPESENSE_API_URL?: string | undefined;
@@ -340,6 +344,7 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
340
344
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
341
345
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
342
346
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: "false" | "true" | undefined;
347
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: "false" | "true" | undefined;
343
348
  SEARCH_DEV_REINIT?: string | undefined;
344
349
  SEARCH_DEV_DEBUG?: "false" | "true" | undefined;
345
350
  TYPESENSE_API_URL?: string | undefined;
@@ -17,6 +17,8 @@ export declare const featureFlagsSchema: z.ZodObject<{
17
17
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT: z.ZodOptional<z.ZodString>;
18
18
  /** Experimental: serve the Docs MCP server in codemode (a single `execute` tool). */
19
19
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
20
+ /** Experimental: give the docs MCP `execute` sandbox a guarded `fetch` that can call gateway-eligible APIs. */
21
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
20
22
  }, "strip", z.ZodTypeAny, {
21
23
  NEW_CATALOG_ENABLED?: boolean | undefined;
22
24
  NEW_SCORECARDS_ENABLED?: boolean | undefined;
@@ -28,6 +30,7 @@ export declare const featureFlagsSchema: z.ZodObject<{
28
30
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
29
31
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
30
32
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: boolean | undefined;
33
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: boolean | undefined;
31
34
  }, {
32
35
  NEW_CATALOG_ENABLED?: "false" | "true" | undefined;
33
36
  NEW_SCORECARDS_ENABLED?: "false" | "true" | undefined;
@@ -39,5 +42,6 @@ export declare const featureFlagsSchema: z.ZodObject<{
39
42
  REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
40
43
  REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
41
44
  REDOCLY_EXP_MCP_CODE_MODE_ENABLED?: "false" | "true" | undefined;
45
+ REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED?: "false" | "true" | undefined;
42
46
  }>;
43
47
  //# sourceMappingURL=feature-flags.d.ts.map
@@ -1 +1 @@
1
- import{z as _}from"zod";import{envBooleanStringOptional as E}from"../../utils/envs/env-boolean-string.js";const o=_.object({NEW_CATALOG_ENABLED:E(),NEW_SCORECARDS_ENABLED:E(),ENABLE_COMMENTS:_.string().optional(),REDOCLY_EXP_DISABLE_MD_VALIDATION:E(),ENABLE_SOURCE_MAPS:E(),PLAN_GATES:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_ENABLED:E(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT:_.string().optional(),REDOCLY_EXP_MCP_CODE_MODE_ENABLED:E()});export{o as featureFlagsSchema};
1
+ import{z as _}from"zod";import{envBooleanStringOptional as E}from"../../utils/envs/env-boolean-string.js";const D=_.object({NEW_CATALOG_ENABLED:E(),NEW_SCORECARDS_ENABLED:E(),ENABLE_COMMENTS:_.string().optional(),REDOCLY_EXP_DISABLE_MD_VALIDATION:E(),ENABLE_SOURCE_MAPS:E(),PLAN_GATES:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_ENABLED:E(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT:_.string().optional(),REDOCLY_EXP_MCP_CODE_MODE_ENABLED:E(),REDOCLY_EXP_MCP_GATEWAY_SERVER_ENABLED:E()});export{D as featureFlagsSchema};
@@ -1,5 +1,4 @@
1
- import type { SearchEngineType, SearchDocument } from '../../types';
2
- export declare const DEFAULT_SEARCH_ENGINE: SearchEngineType;
1
+ import type { SearchDocument } from '../../types';
3
2
  export declare const SEARCH_INDEX_FIELDS: string[];
4
3
  export declare const SEARCH_GROUP_NAME_DOCUMENTATION = "Documentation";
5
4
  export declare const SEARCH_GROUP_NAME_API = "API Reference";
@@ -1 +1 @@
1
- import{DEFAULT_ANONYMOUS_VISITOR_TEAM as e,DEFAULT_AUTHENTICATED_TEAM as t}from"../../../constants/common.js";const _="flexsearch",A=["title","text","path","httpPath","parameters[]:name","parameters[]:description","parameters[]:place","parameters[]:path"],o="Documentation",r="API Reference",p="search",T=100,a=10,n=20,s=100,c=150,I="ai-search",S=50,C=250,R=Symbol("metadata"),D={id:"",url:"",title:"",text:"",security:[],parameters:[{place:"",mediaType:void 0,name:"",description:"",path:[],type:"object",required:!1,example:void 0,enum:void 0}],rbacTeams:[e,t]},N=!0,x=["title"];export{I as AI_INDEX_EXPORT_FOLDER,S as AI_SEARCH_CHUNK_SIZE,C as AI_SEARCH_DOCUMENT_CHUNK_SIZE,D as BASE_SEARCH_DOCUMENT,N as DEFAULT_AI_SEARCH_ENABLED,_ as DEFAULT_SEARCH_ENGINE,x as DISABLE_DEEP_LINK_IF_FIELDS_EXIST,c as HIGHLIGHTED_TEXT_MAX_LENGTH,p as SEARCH_DATA_EXPORT_FOLDER,R as SEARCH_DOCUMENT_METADATA_KEY,a as SEARCH_GROUP_LIMIT,r as SEARCH_GROUP_NAME_API,o as SEARCH_GROUP_NAME_DOCUMENTATION,A as SEARCH_INDEX_FIELDS,T as SEARCH_LIMIT,n as SEARCH_MAX_FACET_VALUES,s as SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT};
1
+ import{DEFAULT_ANONYMOUS_VISITOR_TEAM as e,DEFAULT_AUTHENTICATED_TEAM as t}from"../../../constants/common.js";const _=["title","text","path","httpPath","parameters[]:name","parameters[]:description","parameters[]:place","parameters[]:path"],A="Documentation",o="API Reference",r="search",p=100,T=10,a=20,n=100,s=150,c="ai-search",I=50,S=250,C=Symbol("metadata"),R={id:"",url:"",title:"",text:"",security:[],parameters:[{place:"",mediaType:void 0,name:"",description:"",path:[],type:"object",required:!1,example:void 0,enum:void 0}],rbacTeams:[e,t]},D=!0,H=["title"];export{c as AI_INDEX_EXPORT_FOLDER,I as AI_SEARCH_CHUNK_SIZE,S as AI_SEARCH_DOCUMENT_CHUNK_SIZE,R as BASE_SEARCH_DOCUMENT,D as DEFAULT_AI_SEARCH_ENABLED,H as DISABLE_DEEP_LINK_IF_FIELDS_EXIST,s as HIGHLIGHTED_TEXT_MAX_LENGTH,r as SEARCH_DATA_EXPORT_FOLDER,C as SEARCH_DOCUMENT_METADATA_KEY,T as SEARCH_GROUP_LIMIT,o as SEARCH_GROUP_NAME_API,A as SEARCH_GROUP_NAME_DOCUMENTATION,_ as SEARCH_INDEX_FIELDS,p as SEARCH_LIMIT,a as SEARCH_MAX_FACET_VALUES,n as SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT};
@@ -1 +1 @@
1
- const r=new Map,b=e=>({name:"esbuild-on-rebuild",setup:u=>{const{label:t}=e;r.set(t,0);function l(){return r.get(t)===0}u.onStart(()=>l()?e.buildStart():e.rebuildStart()),u.onEnd(()=>{l()?e.buildEnd():e.rebuildEnd();const n=r.get(t);r.set(t,(n||0)+1)})}});export{b as OnRebuild};
1
+ const r=new Map,n=e=>({name:"esbuild-on-rebuild",setup:u=>{const{label:t}=e;r.set(t,0);function a(){return r.get(t)===0}u.onStart(()=>a()?e.buildStart():e.rebuildStart()),u.onEnd(async()=>{a()?await e.buildEnd():await e.rebuildEnd();const l=r.get(t);r.set(t,(l||0)+1)})}});export{n as OnRebuild};
@@ -1 +1 @@
1
- import*as l from"chokidar";import h from"path";import*as p from"node:fs/promises";import{createHash as m}from"node:crypto";import{slash as n}from"../../utils/path/slash.js";import{logger as d}from"../tools/notifiers/logger.js";import{sha1 as u}from"../utils/crypto/sha1.js";import{debouncedEmit as g}from"./utils/debounced-emit.js";import{trackAccessStore as r}from"./utils/async-storage.js";import{removeBom as w}from"./utils/string-utils.js";class R{cwd;ignored;filesList=new Map;watcher;#t=new Map;#e=[];constructor(t,e=[]){this.cwd=t,this.ignored=e,this.watcher=this.#s()}get ready(){return this.watcher.then(()=>!0)}getFileInfo(t){return this.filesList.get(t)}watch(t){this.#e.push(t)}async dispose(){(await this.watcher).close()}exists(t){const e=this.filesList.has(t);return r.getStore()?.push({type:"exists",path:t,hash:e?"t":"f"}),e}async read(t,e="utf-8"){try{let i=await p.readFile(h.join(this.cwd,t),e);i=w(i);const s=u(i);r.getStore()?.push({type:"read",path:t,hash:s});const a=this.filesList.get(t);return a&&(a.hash=s),i}catch(i){throw r.getStore()?.push({type:"read",path:t,hash:"error"}),i}}scan(t){const e=[],i=m("sha1");this.filesList.forEach(a=>{(!t||t.test(a.relativePath))&&(e.push(a),i.update(a.relativePath))});const s=i.digest("base64");return this.#t.set(t,s),r.getStore()?.push({type:"scan",hash:s,pattern:t}),e}emitCodeUpdated(){this.emit({event:"code-updated"})}addVirtualFile(t,e){this.filesList.set(t,{relativePath:t,realRelativePath:e.realRelativePath,hash:e.hash,isVirtual:!0}),r.getStore()?.push({type:"read",path:t,hash:e.hash??""})}getPatternScanHash(t){return this.#t.get(t)}emit=g(async t=>{for(const e of t)switch(e.event){case"add":this.filesList.set(e.path,{relativePath:e.path,realRelativePath:e.path,hash:void 0,isVirtual:!1});for(const s of this.#t.keys())s&&s.test(e.path)&&this.#t.set(s,void 0),s||this.#t.set(s,void 0);break;case"change":const i=this.filesList.get(e.path);i&&(i.hash=void 0);break;case"unlink":this.filesList.delete(e.path);for(const s of this.#t.keys())s&&s.test(e.path)&&this.#t.delete(s),s||this.#t.delete(s);break}for(const e of this.#e)await e(t)});async#s(){return d.startTiming("init-fs"),new Promise((t,e)=>{const i=l.watch(this.cwd,{usePolling:!1,ignoreInitial:!0,ignored:[/(\/.git\/|\/node_modules\/|@theme)/,h.join(this.cwd,"public"),h.join(this.cwd,"README.md"),...this.ignored]});i.on("ready",()=>{this.filesList=v(i.getWatched(),this.cwd),t(i),d.infoTime("init-fs","File system scan completed")}).on("error",e).on("add",(s,a)=>{this.emit({event:"add",path:n(h.relative(this.cwd,s)),stats:a})}).on("change",(s,a)=>{this.emit({event:"change",path:n(h.relative(this.cwd,s)),stats:a})}).on("unlink",s=>{this.emit({event:"unlink",path:n(h.relative(this.cwd,s))})})})}}function v(o,t){const e=new Map;for(const i of Object.keys(o))for(const s of o[i]){const a=h.join(i,s);if(o[a])continue;const f=n(h.dirname(h.relative(t,a))),c=h.posix.join(f,s);e.set(c,{relativePath:c,realRelativePath:c,isVirtual:!1,hash:void 0})}return e}export{R as Fs};
1
+ import*as f from"chokidar";import h from"path";import*as p from"node:fs/promises";import{createHash as l}from"node:crypto";import{slash as o}from"../../utils/path/slash.js";import{logger as c}from"../tools/notifiers/logger.js";import{sha1 as m}from"../utils/crypto/sha1.js";import{USER_THEME_ALIAS as u,USER_SKILLS_ALIAS as g,USER_SKILL_FILENAME as w}from"../../constants/common.js";import{debouncedEmit as L}from"./utils/debounced-emit.js";import{trackAccessStore as r}from"./utils/async-storage.js";import{removeBom as S}from"./utils/string-utils.js";const E=`${g}(/.*)?`,y=w.replace(".","\\."),v=new RegExp(`^(${E}|${y})$`);class j{cwd;ignored;filesList=new Map;watcher;#t=new Map;#e=[];constructor(t,e=[]){this.cwd=t,this.ignored=e,this.watcher=this.#i()}get ready(){return this.watcher.then(()=>!0)}getFileInfo(t){return this.filesList.get(t)}watch(t){this.#e.push(t)}async dispose(){(await this.watcher).close()}exists(t){const e=this.filesList.has(t);return r.getStore()?.push({type:"exists",path:t,hash:e?"t":"f"}),e}async read(t,e="utf-8"){try{let i=await p.readFile(h.join(this.cwd,t),e);i=S(i);const s=m(i);r.getStore()?.push({type:"read",path:t,hash:s});const a=this.filesList.get(t);return a&&(a.hash=s),i}catch(i){throw r.getStore()?.push({type:"read",path:t,hash:"error"}),i}}scan(t){const e=[],i=l("sha1");this.filesList.forEach(a=>{(!t||t.test(a.relativePath))&&(e.push(a),i.update(a.relativePath))});const s=i.digest("base64");return this.#t.set(t,s),r.getStore()?.push({type:"scan",hash:s,pattern:t}),e}emitCodeUpdated(){this.emit({event:"code-updated"})}addVirtualFile(t,e){this.filesList.set(t,{relativePath:t,realRelativePath:e.realRelativePath,hash:e.hash,isVirtual:!0}),r.getStore()?.push({type:"read",path:t,hash:e.hash??""})}getPatternScanHash(t){return this.#t.get(t)}#s(t){return v.test(t)}emit=L(async t=>{for(const e of t)if(!("path"in e&&this.#s(e.path)))switch(e.event){case"add":this.filesList.set(e.path,{relativePath:e.path,realRelativePath:e.path,hash:void 0,isVirtual:!1});for(const s of this.#t.keys())s&&s.test(e.path)&&this.#t.set(s,void 0),s||this.#t.set(s,void 0);break;case"change":const i=this.filesList.get(e.path);i&&(i.hash=void 0);break;case"unlink":this.filesList.delete(e.path);for(const s of this.#t.keys())s&&s.test(e.path)&&this.#t.delete(s),s||this.#t.delete(s);break}for(const e of this.#e)await e(t)});async#i(){return c.startTiming("init-fs"),new Promise((t,e)=>{const i=f.watch(this.cwd,{usePolling:!1,ignoreInitial:!0,ignored:[new RegExp(`(/.git/|/node_modules/|${u})`),h.join(this.cwd,"public"),h.join(this.cwd,"README.md"),...this.ignored]});i.on("ready",()=>{this.filesList=this.#a(i.getWatched()),t(i),c.infoTime("init-fs","File system scan completed")}).on("error",e).on("add",(s,a)=>{this.emit({event:"add",path:o(h.relative(this.cwd,s)),stats:a})}).on("change",(s,a)=>{this.emit({event:"change",path:o(h.relative(this.cwd,s)),stats:a})}).on("unlink",s=>{this.emit({event:"unlink",path:o(h.relative(this.cwd,s))})})})}#a(t){const e=new Map;for(const i of Object.keys(t))for(const s of t[i]){const a=h.join(i,s);if(t[a])continue;const d=o(h.dirname(h.relative(this.cwd,a))),n=h.posix.join(d,s);this.#s(n)||e.set(n,{relativePath:n,realRelativePath:n,isVirtual:!1,hash:void 0})}return e}}export{j as Fs};
@@ -1 +1 @@
1
- import{and as E,eq as c,isNull as R,or as T,sql as N}from"drizzle-orm";import{VERSION_NOT_SPECIFIED as I}from"@redocly/theme/core/constants";import{sha1 as V}from"../../../../../utils/crypto/sha1.js";import{envConfig as F}from"../../../../../config/env-config.js";import{entitiesTable as i}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{convertFilterToWhereCondition as K}from"../../../../../providers/database/pagination/filter.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{RevisionRepository as x}from"../common/revision-repository.js";import{VersionRepository as z}from"../common/version-repository.js";import{EntityAttributesWriteRepository as H}from"../entityAttributes/entity-attributes-write-repository.js";import{createEntityDbRecord as O}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as k}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromFileSchema as P}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{createEntityRelationDbRecordFromDto as j}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{EntitiesReadRepository as G}from"./entities-read-repository.js";import{RelationsReadRepository as M}from"../relations/relations-read-repository.js";import{RelationsWriteRepository as $}from"../relations/relations-write-repository.js";const v=15;class ce{#e;#t;#n;#o;#i;#s;#a;#u;#r;constructor(e,s,r){this.#e=e,this.#i=s,this.#s=r,this.#t=new x(e),this.#n=new z(e),this.#o=new H(e),this.#a=new G(e),this.#u=new M(e),this.#r=new $(e,s,r)}async createEntity({entity:e,source:s,fileHash:r,sourceFile:o,isRootEntity:t,isDeleted:n,rbacTeams:u,errorOnSkip:h=!1,revision:f}){const{relations:l=[],...y}=e,d=V(JSON.stringify(y)),p=e.version??I,C=f??new Date().toISOString(),W=await this.#t.shouldSkipRevisionCreation(e.key,p,d,t,n);if(Array.isArray(u)&&await this.#o.upsertEntityAttributes({entityKey:e.key,rbacTeams:u,organizationId:this.#i,projectId:this.#s}),W){if(h)throw new Error("Entity validation failed: entity already exists");return null}const{shouldSetNewCurrentRevision:g,hasCurrentRevision:L}=await this.#t.getCurrentRevisionInfo({key:e.key,version:p,revision:C}),w=O({entity:{...e,revision:C,hash:d,isCurrent:g,isDefaultVersion:g,isDeleted:n,version:p},organizationId:this.#i,projectId:this.#s,source:s,sourceFile:o??null,fileHash:r??null}),{key:D,..._}=w;if(g&&L&&(await this.#t.markAllRevisionsAsNotCurrent(D),await this.#n.markAllVersionsAsNotDefault(D)),F.isDevelopMode&&!F.REDOCLY_INTERNAL_DEV)return await this.#l(w,l);const A=await this.#e.client.insert(i).values(w).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:_}).returning();return A.length?(l&&await this.#r.createEntityRelations(l.map(S=>({...S,sourceKey:e.key,targetKey:S.key}))),k(A[0])):null}async updateEntity(e,s){const{shouldSetNewCurrentRevision:r,hasCurrentRevision:o}=await this.#t.getCurrentRevisionInfo({key:s.key,version:e.version??s.version??I,revision:s.revision});r&&o&&(await this.#t.markAllRevisionsAsNotCurrent(s.key),await this.#n.markAllVersionsAsNotDefault(s.key));const t=O({entity:{...s,...e,hash:V(JSON.stringify({...s,...e})),isCurrent:r,isDefaultVersion:r,createdAt:s.createdAt??void 0},organizationId:this.#i,projectId:this.#s,source:"remote",sourceFile:null,fileHash:null}),{key:n,source:u,scorecardsStatus:h,...f}=t,l=await this.#e.client.insert(i).values(t).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:{...f,scorecardsStatus:N`CASE WHEN ${i.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return l.length?k(l[0]):null}async setEntitiesAsOutdated(e){const s=K(e);await this.#e.client.update(i).set({scorecardsStatus:"OUTDATED"}).where(s)}async#l(e,s){const{key:r,source:o,version:t,isDefaultVersion:n,...u}=e,l=await this.#e.client.select({id:i.id}).from(i).where(E(c(i.key,r),t?c(i.version,t):R(i.version))).limit(1).get()!=null?await this.#e.client.update(i).set(u).where(E(c(i.key,r),t?c(i.version,t):R(i.version))).returning():await this.#e.client.insert(i).values(e).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:u}).returning(),y=s?.map(d=>{const p=P({relation:d,sourceFile:e.sourceFile??"",fileHash:e.fileHash??"",sourceKey:e.key,sourceVersion:e.version??null,sourceRevision:e.revision??null,organizationId:this.#i,projectId:this.#s});return this.#e.client.insert(a).values(p).onConflictDoUpdate({target:[a.sourceKey,a.targetKey,a.sourceVersion,a.targetVersion,a.sourceRevision,a.targetRevision,a.sourceToTargetRelation],set:p}).run()})??[];return await m(y,v,async d=>d),k(l[0])}async softDeleteEntitiesWithRelations({filter:e,revision:s,fileHash:r}){const t={op:"AND",conditions:[e,{field:"is_deleted",operator:"equal",value:!1}]};for(;;){const n=await this.#a.getEntities({paginationParams:{filter:t,limit:500}});if(n.items.length===0)break;const u=await this.#c({entities:n.items,revision:s,fileHash:r});await this.#d(u,s)}}async deleteEntity(e){return await this.#r.deleteEntityRelationsOnEntityRemoval(e),await this.#e.client.delete(i).where(c(i.id,e.id)),await this.#t.ensureDefaultAndCurrentRevisionForKey(e.key),e.id}async deleteEntities(e){const s=K(e);if(!s)return!1;const r=await this.#e.client.delete(i).where(s).returning({key:i.key,source:i.source,isCurrent:i.isCurrent,isDefaultVersion:i.isDefaultVersion,version:i.version});if(r.length===0)return!0;const o=r.reduce((t,n)=>((n.isCurrent||n.isDefaultVersion)&&t.add(n.key),t),new Set);if(o.size===0)return!0;await m(Array.from(o),v,async t=>this.#t.ensureDefaultAndCurrentRevisionForKey(t));for(const t of r)await this.#e.client.delete(a).where(T(E(c(a.sourceKey,t.key),...t.version?[c(a.sourceVersion,t.version)]:[R(a.sourceVersion)]),E(c(a.targetKey,t.key),...t.version?[c(a.targetVersion,t.version)]:[R(a.targetVersion)])));return!0}async updateEntityScorecardsStatus(e,s){return(await this.#e.client.update(i).set({scorecardsStatus:s}).where(c(i.id,e)).returning()).length>0}async updateEntityScorecardsStatusIfCalculating(e,s){return(await this.#e.client.update(i).set({scorecardsStatus:s}).where(N`${i.id} = ${e} AND ${i.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}async#c({entities:e,revision:s,fileHash:r}){return(await m(e,v,async t=>{const n={type:t.type,key:t.key,title:t.title,summary:t.summary??void 0,tags:t.tags??void 0,metadata:t.metadata??void 0,git:t.git??void 0,contact:t.contact??void 0,links:t.links??void 0,version:t.version??void 0};return this.createEntity({entity:n,sourceFile:t.sourceFile??"",fileHash:r,isDeleted:!0,errorOnSkip:!1,source:t.source,revision:s})})).filter(t=>t!==null)}async#d(e,s){if(e.length===0)return!0;const r=await m(e,v,async o=>(await this.#u.getRelationsForEntity(o.key,o.version,s)).map(n=>{if(!n)return null;const u=n.direction,h=n.sourceToTargetRelation,f=n.targetKey,l=u==="outgoing"?o.key:f,y=u==="outgoing"?f:o.key,d=u==="outgoing"?h:h.startsWith("reverse:")?h.slice(8):h;return!d||!l||!y?null:j({type:d,sourceKey:l,targetKey:y,sourceVersion:o.version,targetVersion:o.version,sourceRevision:s,targetRevision:s,isDeleted:!0},this.#i,this.#s)}).filter(n=>n!==null));return await m(r.flat(),v,async o=>this.#r.upsertEntityRelation(o)),!0}}export{ce as EntitiesWriteRepository};
1
+ import{and as v,eq as c,isNull as E,or as T,sql as N}from"drizzle-orm";import{VERSION_NOT_SPECIFIED as I}from"@redocly/theme/core/constants";import{sha1 as V}from"../../../../../utils/crypto/sha1.js";import{envConfig as F}from"../../../../../config/env-config.js";import{entitiesTable as i}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-table.js";import{convertFilterToWhereCondition as K}from"../../../../../providers/database/pagination/filter.js";import{entitiesRelationsTable as a}from"../../../../../providers/database/databases/sqlite-db/schemas/entities-relations-table.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{RevisionRepository as x}from"../common/revision-repository.js";import{VersionRepository as z}from"../common/version-repository.js";import{EntityAttributesWriteRepository as H}from"../entityAttributes/entity-attributes-write-repository.js";import{createEntityDbRecord as O}from"../../mappers/create-entity-db-record.js";import{createEntityReadModel as k}from"../../mappers/create-entity-read-model.js";import{createEntityRelationDbRecordFromFileSchema as P}from"../../mappers/create-entity-relation-db-record-from-file-schema.js";import{createEntityRelationDbRecordFromDto as j}from"../../mappers/create-entity-relation-db-record-from-dto.js";import{EntitiesReadRepository as G}from"./entities-read-repository.js";import{RelationsReadRepository as M}from"../relations/relations-read-repository.js";import{RelationsWriteRepository as $}from"../relations/relations-write-repository.js";const m=15;class ce{#e;#t;#n;#o;#i;#s;#a;#u;#r;constructor(e,s,r){this.#e=e,this.#i=s,this.#s=r,this.#t=new x(e),this.#n=new z(e),this.#o=new H(e),this.#a=new G(e),this.#u=new M(e),this.#r=new $(e,s,r)}async createEntity({entity:e,source:s,fileHash:r,sourceFile:o,isRootEntity:t,isDeleted:n,rbacTeams:l,errorOnSkip:d=!1,revision:h}){const{relations:u=[],...f}=e,y=V(JSON.stringify(f)),R=e.version??I,C=h??new Date().toISOString(),W=await this.#t.shouldSkipRevisionCreation(e.key,R,y,t,n);if(Array.isArray(l)&&await this.#o.upsertEntityAttributes({entityKey:e.key,rbacTeams:l,organizationId:this.#i,projectId:this.#s}),W){if(d)throw new Error("Entity validation failed: entity already exists");return null}const{shouldSetNewCurrentRevision:g,hasCurrentRevision:L}=await this.#t.getCurrentRevisionInfo({key:e.key,version:R,revision:C}),w=O({entity:{...e,revision:C,hash:y,isCurrent:g,isDefaultVersion:g,isDeleted:n,version:R},organizationId:this.#i,projectId:this.#s,source:s,sourceFile:o??null,fileHash:r??null}),{key:D,..._}=w;if(g&&L&&(await this.#t.markAllRevisionsAsNotCurrent(D),await this.#n.markAllVersionsAsNotDefault(D)),F.isDevelopMode&&!F.REDOCLY_INTERNAL_DEV)return await this.#l(w,u);const A=await this.#e.client.insert(i).values(w).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:_}).returning();return A.length?(u&&await this.#r.createEntityRelations(u.map(S=>({...S,sourceKey:e.key,targetKey:S.key}))),k(A[0])):null}async updateEntity(e,s){const{shouldSetNewCurrentRevision:r,hasCurrentRevision:o}=await this.#t.getCurrentRevisionInfo({key:s.key,version:e.version??s.version??I,revision:s.revision});r&&o&&(await this.#t.markAllRevisionsAsNotCurrent(s.key),await this.#n.markAllVersionsAsNotDefault(s.key));const t=O({entity:{...s,...e,hash:V(JSON.stringify({...s,...e})),isCurrent:r,isDefaultVersion:r,createdAt:s.createdAt??void 0},organizationId:this.#i,projectId:this.#s,source:"remote",sourceFile:null,fileHash:null}),{key:n,source:l,scorecardsStatus:d,...h}=t,u=await this.#e.client.insert(i).values(t).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:{...h,scorecardsStatus:N`CASE WHEN ${i.scorecardsStatus} = 'CALCULATING' THEN 'CANCELLED' ELSE 'OUTDATED' END`}}).returning();return u.length?k(u[0]):null}async setEntitiesAsOutdated(e){const s=K(e);await this.#e.client.update(i).set({scorecardsStatus:"OUTDATED"}).where(s)}async#l(e,s){const{key:r,source:o,version:t,...n}=e,h=await this.#e.client.select({id:i.id}).from(i).where(v(c(i.key,r),t?c(i.version,t):E(i.version))).limit(1).get()!=null?await this.#e.client.update(i).set(n).where(v(c(i.key,r),t?c(i.version,t):E(i.version))).returning():await this.#e.client.insert(i).values(e).onConflictDoUpdate({target:[i.key,i.source,i.revision,i.version],set:n}).returning(),u=s?.map(f=>{const y=P({relation:f,sourceFile:e.sourceFile??"",fileHash:e.fileHash??"",sourceKey:e.key,sourceVersion:e.version??null,sourceRevision:e.revision??null,organizationId:this.#i,projectId:this.#s});return this.#e.client.insert(a).values(y).onConflictDoUpdate({target:[a.sourceKey,a.targetKey,a.sourceVersion,a.targetVersion,a.sourceRevision,a.targetRevision,a.sourceToTargetRelation],set:y}).run()})??[];return await p(u,m,async f=>f),k(h[0])}async softDeleteEntitiesWithRelations({filter:e,revision:s,fileHash:r}){const t={op:"AND",conditions:[e,{field:"is_deleted",operator:"equal",value:!1}]};for(;;){const n=await this.#a.getEntities({paginationParams:{filter:t,limit:500}});if(n.items.length===0)break;const l=await this.#c({entities:n.items,revision:s,fileHash:r});await this.#d(l,s)}}async deleteEntity(e){return await this.#r.deleteEntityRelationsOnEntityRemoval(e),await this.#e.client.delete(i).where(c(i.id,e.id)),await this.#t.ensureDefaultAndCurrentRevisionForKey(e.key),e.id}async deleteEntities(e){const s=K(e);if(!s)return!1;const r=await this.#e.client.delete(i).where(s).returning({key:i.key,source:i.source,isCurrent:i.isCurrent,isDefaultVersion:i.isDefaultVersion,version:i.version});if(r.length===0)return!0;const o=r.reduce((t,n)=>((n.isCurrent||n.isDefaultVersion)&&t.add(n.key),t),new Set);if(o.size===0)return!0;await p(Array.from(o),m,async t=>this.#t.ensureDefaultAndCurrentRevisionForKey(t));for(const t of r)await this.#e.client.delete(a).where(T(v(c(a.sourceKey,t.key),...t.version?[c(a.sourceVersion,t.version)]:[E(a.sourceVersion)]),v(c(a.targetKey,t.key),...t.version?[c(a.targetVersion,t.version)]:[E(a.targetVersion)])));return!0}async updateEntityScorecardsStatus(e,s){return(await this.#e.client.update(i).set({scorecardsStatus:s}).where(c(i.id,e)).returning()).length>0}async updateEntityScorecardsStatusIfCalculating(e,s){return(await this.#e.client.update(i).set({scorecardsStatus:s}).where(N`${i.id} = ${e} AND ${i.scorecardsStatus} = 'CALCULATING'`).returning()).length>0}async#c({entities:e,revision:s,fileHash:r}){return(await p(e,m,async t=>{const n={type:t.type,key:t.key,title:t.title,summary:t.summary??void 0,tags:t.tags??void 0,metadata:t.metadata??void 0,git:t.git??void 0,contact:t.contact??void 0,links:t.links??void 0,version:t.version??void 0};return this.createEntity({entity:n,sourceFile:t.sourceFile??"",fileHash:r,isDeleted:!0,errorOnSkip:!1,source:t.source,revision:s})})).filter(t=>t!==null)}async#d(e,s){if(e.length===0)return!0;const r=await p(e,m,async o=>(await this.#u.getRelationsForEntity(o.key,o.version,s)).map(n=>{if(!n)return null;const l=n.direction,d=n.sourceToTargetRelation,h=n.targetKey,u=l==="outgoing"?o.key:h,f=l==="outgoing"?h:o.key,y=l==="outgoing"?d:d.startsWith("reverse:")?d.slice(8):d;return!y||!u||!f?null:j({type:y,sourceKey:u,targetKey:f,sourceVersion:o.version,targetVersion:o.version,sourceRevision:s,targetRevision:s,isDeleted:!0},this.#i,this.#s)}).filter(n=>n!==null));return await p(r.flat(),m,async o=>this.#r.upsertEntityRelation(o)),!0}}export{ce as EntitiesWriteRepository};
@@ -1 +1 @@
1
- import y from"node:path";import{removeLeadingSlash as g}from"@redocly/theme/core/utils";import{toKebabCase as d}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as m}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as v}from"./base.js";const f=15;class A extends v{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t,i){const a=g(t.realRelativePath),l=t.document.info.title,e=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:t.document["x-redocly-catalog-key"]});return{type:this.type,key:e,title:l,summary:t.document.info.description?w(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a},version:i}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t,i,a,l){if(!this.#t(t)){this.context.logger.warn(`Skipping Arazzo description without source descriptions: ${t.realRelativePath}`);return}const e=this.getRbacTeamsForDefinition(t.relativePath),o=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntity({entity:{...o},revision:i,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,rbacTeams:e,source:"file"}),l.delete(`${o.key}:${a}`),await this.#e(t,o.key,o.version,a,i,l,e);const h=t.document.sourceDescriptions||[];await m(h,f,async r=>{if(!(r.type!=="openapi"||!r.url))try{const s=this.resolveSourceDescriptionUrl(r.url,t.realRelativePath);if(!s){!r.url.startsWith("http://")&&!r.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${r.url}`);return}const c=await this.context.cache.load(s,"load-oas");if(!(c.data&&Array.isArray(c.data)&&c.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${s}`);return}const p=c.data[0],u=this.resolveEntityKey({realRelativePath:p.realRelativePath,customKey:p.definition["x-redocly-catalog-key"]});await this.catalogEntitiesService.createEntityRelation({sourceKey:o.key,type:"relatesTo",targetKey:u,sourceFile:t.realRelativePath,fileHash:t.hash}),await this.#r(t,r.name,p,o.key,u,o.version,i)}catch(s){this.context.logger.warn(`Failed to create relation to OpenAPI source "${r.url}": ${s instanceof Error?s.message:"Unknown error"}`)}})}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,i,a,l,e,o,h)=>{try{const r=t.document.components?.inputs,s=r?Object.entries(r):[],c=[];for(const[n,p]of s)c.push(async()=>{const u=await this.#a({schemaName:n,schema:p,description:t,parentKey:i,parentVersion:a,parentRevision:e,rbacTeams:h});o.delete(`${u?.key}:${l}`),u&&await this.catalogEntitiesService.createEntityRelation({sourceKey:i,type:"uses",targetKey:u.key,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:e,targetRevision:e})});if(c.length===0)return;await m(c,f,n=>n())}catch(r){this.context.logger.warn(`Failed to create data schema entities for Arazzo description: ${r instanceof Error?r.message:"Unknown error"}`)}};#a=async({schemaName:t,schema:i,description:a,parentKey:l,parentVersion:e,parentRevision:o,rbacTeams:h})=>{const r={type:"data-schema",key:`${l}-${d(t)}`,title:t,summary:i.description||i.title||null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a.realRelativePath,schema:"{}"},version:e};try{return await this.catalogEntitiesService.createEntity({entity:r,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:h,source:"file",revision:o})}catch(s){return this.context.logger.warn(`Failed to create data schema entity for ${t}: ${s instanceof Error?s.message:"Unknown error"}`),null}};#r=async(t,i,a,l,e,o,h)=>{const r=t.document.workflows||[];if(r.length===0)return;const s=new Set;for(const c of r)for(const n of c.steps||[]){if(!n.operationId)continue;const p=n.operationId.startsWith(`${i}.`)?n.operationId.substring(`${i}.`.length):n.operationId;p&&s.add(p)}s.size!==0&&await m(Array.from(s),f,async c=>{try{const n=`${e}-${d(c)}`;await this.catalogEntitiesService.createEntityRelation({sourceKey:l,type:"uses",targetKey:n,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:o,targetVersion:o,sourceRevision:h,targetRevision:h})}catch(n){this.context.logger.warn(`Failed to create relation to operation "${c}": ${n instanceof Error?n.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,i){try{const a=t.trim(),l=a.startsWith("@")?a.slice(1):a,[e]=l.split("#");if(e.startsWith("http://")||e.startsWith("https://"))return null;if(e.startsWith("/"))return g(y.posix.normalize(e));const o=y.posix.dirname(i);return e.startsWith(o+"/")?y.posix.normalize(e):y.posix.normalize(y.posix.join(o,e))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{A as ArazzoEntitiesExtractor};
1
+ import u from"node:path";import{removeLeadingSlash as w}from"@redocly/theme/core/utils";import{toKebabCase as m}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as f}from"../../../../../utils/async/promise-map-limit.js";import{removeMarkdocTags as v}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";const g=15;class S extends E{constructor(t){super("arazzo",t)}mapApiDescriptionToEntity(t,o){const a=w(t.realRelativePath),l=t.document.info.title,e=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:t.document["x-redocly-catalog-key"]});return{type:this.type,key:e,title:l,summary:t.document.info.description?v(t.document.info.description):null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a},version:o}}async loadApiDescriptions(){return(await this.context.cache.load(".","arazzo-docs")).data}async processApiDescription(t,o,a,l){if(!this.#t(t))throw new Error("Arazzo description has no source descriptions");const e=this.getRbacTeamsForDefinition(t.relativePath),i=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntity({entity:{...i},revision:o,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,rbacTeams:e,source:"file"}),l.delete(`${i.key}:${a}`),await this.#e(t,i.key,i.version,a,o,l,e);const h=t.document.sourceDescriptions||[];await f(h,g,async r=>{if(!(r.type!=="openapi"||!r.url))try{const s=this.resolveSourceDescriptionUrl(r.url,t.realRelativePath);if(!s){!r.url.startsWith("http://")&&!r.url.startsWith("https://")&&this.context.logger.warn(`Could not resolve URL to local path: ${r.url}`);return}const c=await this.context.cache.load(s,"load-oas");if(!(c.data&&Array.isArray(c.data)&&c.data.length>0)){this.context.logger.warn(`No OpenAPI definition found at path: ${s}`);return}const p=c.data[0],y=this.resolveEntityKey({realRelativePath:p.realRelativePath,customKey:p.definition["x-redocly-catalog-key"]});await this.catalogEntitiesService.createEntityRelation({sourceKey:i.key,type:"relatesTo",targetKey:y,sourceFile:t.realRelativePath,fileHash:t.hash}),await this.#r(t,r.name,p,i.key,y,i.version,o)}catch(s){this.context.logger.warn(`Failed to create relation to OpenAPI source "${r.url}": ${s instanceof Error?s.message:"Unknown error"}`)}})}#t=t=>!!t?.document?.sourceDescriptions&&t.document.sourceDescriptions.length>0;#e=async(t,o,a,l,e,i,h)=>{try{const r=t.document.components?.inputs,s=r?Object.entries(r):[],c=[];for(const[n,p]of s)c.push(async()=>{const y=`${o}-${m(n)}`,d=await this.#a({schemaName:n,schema:p,description:t,parentKey:o,parentVersion:a,parentRevision:e,rbacTeams:h});i.delete(`${y}:${l}`),d&&await this.catalogEntitiesService.createEntityRelation({sourceKey:o,type:"uses",targetKey:d.key,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:e,targetRevision:e})});if(c.length===0)return;await f(c,g,n=>n())}catch(r){this.context.logger.warn(`Failed to create data schema entities for Arazzo description: ${r instanceof Error?r.message:"Unknown error"}`)}};#a=async({schemaName:t,schema:o,description:a,parentKey:l,parentVersion:e,parentRevision:i,rbacTeams:h})=>{const r={type:"data-schema",key:`${l}-${m(t)}`,title:t,summary:o.description||o.title||null,tags:["arazzo"],metadata:{specType:this.specType,descriptionFile:a.realRelativePath,schema:"{}"},version:e};try{return await this.catalogEntitiesService.createEntity({entity:r,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:h,source:"file",revision:i})}catch(s){return this.context.logger.warn(`Failed to create data schema entity for ${t}: ${s instanceof Error?s.message:"Unknown error"}`),null}};#r=async(t,o,a,l,e,i,h)=>{const r=t.document.workflows||[];if(r.length===0)return;const s=new Set;for(const c of r)for(const n of c.steps||[]){if(!n.operationId)continue;const p=n.operationId.startsWith(`${o}.`)?n.operationId.substring(`${o}.`.length):n.operationId;p&&s.add(p)}s.size!==0&&await f(Array.from(s),g,async c=>{try{const n=`${e}-${m(c)}`;await this.catalogEntitiesService.createEntityRelation({sourceKey:l,type:"uses",targetKey:n,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:i,targetVersion:i,sourceRevision:h,targetRevision:h})}catch(n){this.context.logger.warn(`Failed to create relation to operation "${c}": ${n instanceof Error?n.message:"Unknown error"}`)}})};resolveSourceDescriptionUrl(t,o){try{const a=t.trim(),l=a.startsWith("@")?a.slice(1):a,[e]=l.split("#");if(e.startsWith("http://")||e.startsWith("https://"))return null;if(e.startsWith("/"))return w(u.posix.normalize(e));const i=u.posix.dirname(o);return e.startsWith(i+"/")?u.posix.normalize(e):u.posix.normalize(u.posix.join(i,e))}catch{return this.context.logger.warn(`Failed to resolve URL: ${t}`),null}}}export{S as ArazzoEntitiesExtractor};
@@ -1 +1 @@
1
- import{removeLeadingSlash as R}from"@redocly/theme/core/utils";import{toKebabCase as f}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as $}from"../../../../../utils/async/promise-map-limit-with-status.js";import{removeMarkdocTags as d}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as E}from"./base.js";import{extractPartsFromComponentsRef as y}from"../../../utils/extract-parts-from-components-ref.js";import{extractPartsFromChannelsMessageRef as w}from"../../../utils/extract-parts-from-channels-message-ref.js";const u=15;class M extends E{constructor(e){super("asyncapi",e)}mapApiDescriptionToEntity(e,t){const a=R(e.realRelativePath),n=e.document.info.title,s=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.document["x-redocly-catalog-key"]});return{type:this.type,key:s,title:n,summary:d(e.document.info.description),tags:e.document.info.tags?.map(r=>r.name),metadata:{specType:this.specType,descriptionFile:a},version:t}}async loadApiDescriptions(){return(await this.context.cache.load(".","asyncapi-docs")).data}async processApiDescription(e,t,a,n){const s=this.getRbacTeamsForDefinition(e.relativePath),r=this.mapApiDescriptionToEntity(e,a);await this.catalogEntitiesService.createEntity({entity:r,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,rbacTeams:s,source:"file"}),n.delete(`${r.key}:${a}`);const o=this.#a(e),[i,c]=await Promise.allSettled([this.#s(e,r.key,r.version,a,t,n,s),this.#n(o,e,r.key,r.version,a,t,n,s)]);i.status!=="fulfilled"&&this.context.logger.error("Schema processing failed:",i.reason),c.status!=="fulfilled"&&this.context.logger.error("Operation processing failed:",c.reason)}#a=e=>{const t=e.documentWithReferences.operations;return t?Object.entries(t).map(([a,n])=>({operationName:a,operation:n})):[]};#s=async(e,t,a,n,s,r,o)=>{const i=e.document.components?.schemas;if(!i)return;const c=Object.entries(i);if(c.length===0)return;const l=await $(c,u,async([m,h])=>{const g=await this.#r({schemaName:m,schema:h,description:e,parentKey:t,parentVersion:a,parentRevision:s,rbacTeams:o});r.delete(`${g?.key}:${n}`),g&&await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"uses",targetKey:g.key,sourceFile:e.realRelativePath,fileHash:e.hash,sourceVersion:a,targetVersion:a,sourceRevision:s,targetRevision:s})},this.context.logger);l.count.failed>0&&this.context.logger.warn(`Schema processing completed with ${l.count.failed} failures out of ${c.length} schemas for ${e.realRelativePath}`)};#r=async({schemaName:e,schema:t,description:a,parentKey:n,parentVersion:s,parentRevision:r,rbacTeams:o})=>{const i=`${n}-${f(e)}`,c="title"in t?t.title??t.description:null,l=JSON.stringify(t),m={type:"data-schema",key:i,title:e,summary:c,tags:[],metadata:{specType:this.specType,schema:l},version:s};try{return await this.catalogEntitiesService.createEntity({entity:m,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:o,source:"file",revision:r})}catch(h){return this.context.logger.warn(`Failed to create data schema entity for ${e}: ${h instanceof Error?h.message:"Unknown error"}`),null}};#n=async(e,t,a,n,s,r,o,i)=>{if(!e.length)return;const c=await $(e,u,async({operationName:l,operation:m})=>{const h=await this.#o(m,l,t,a,n,r,i);h&&o.delete(`${h}:${s}`)},this.context.logger);c.count.failed>0&&this.context.logger.warn(`Operation processing completed with ${c.count.failed} failures out of ${e.length} operations for ${t.realRelativePath}`)};#o=async(e,t,a,n,s,r,o)=>{const i=await this.#i(e.messages??[],a,n),c=await this.#c(t,e,i,a,n,s,r,o);return c&&await this.#l({apiOperationKey:c.key,operation:e,descriptionUniqueKey:n,description:a,descriptionVersion:s,parentRevision:r}),c?.key??null};#i=async(e,t,a)=>{if(!e||e.length===0)return[];const n=new Set;for(const s of e){let r=null;if("$ref"in s){const o=s.$ref.startsWith("#/channels/")?this.#e(s.$ref,t):s.$ref;if(o){const i=y(o);if(i?.componentName&&i.componentType==="messages"){const c=t.documentWithReferences.components?.messages[i.componentName];c?.payload&&"$ref"in c.payload&&c.payload.$ref&&(r=c.payload.$ref)}}}else s.payload&&"$ref"in s.payload&&s.payload.$ref&&(r=s.payload.$ref);if(r){const o=y(r);o?.componentName&&o.componentType==="schemas"&&n.add(`${a}-${f(o.componentName)}`)}}return Array.from(n)};#c=async(e,t,a,n,s,r,o,i)=>{const c={type:"api-operation",key:`${s}-${f(e)}`,title:t.title||e,summary:t.summary??"",tags:t.tags?.map(l=>l.name)??[],metadata:{method:t.action==="send"?"PUBLISH":"SUBSCRIBE",path:t.channel.address??"",payload:t.action==="receive"?a:[],responses:t.action==="send"?a:[]},version:r};try{return await this.catalogEntitiesService.createEntity({entity:c,sourceFile:n.realRelativePath,fileHash:n.hash,rbacTeams:i,source:"file",revision:o})}catch(l){return this.context.logger.warn(`Failed to create API operation entity for ${e}: ${l instanceof Error?l.message:"Unknown error"}`),null}};#l=async({apiOperationKey:e,operation:t,descriptionUniqueKey:a,description:n,descriptionVersion:s,parentRevision:r})=>(await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"partOf",targetKey:a,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r}),await this.#h(t,e,n,s,r),!Array.isArray(t.messages)||!t.messages?.length?[]:await this.#m(t.messages,e,n,a,s,r));#h=async(e,t,a,n,s)=>{e["x-catalogRelations"]?.length&&await p(e["x-catalogRelations"],u,async r=>{try{this.validateEntityRelationFileSchema(r),await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:r.type,targetKey:r.key,sourceFile:a.realRelativePath,fileHash:a.hash,sourceVersion:n,targetVersion:"",sourceRevision:s,targetRevision:""})}catch(o){this.context.logger.warn(`Error creating entity relation for operation ${t} based on custom property: ${o instanceof Error?o.message:"Unknown error"}`)}})};#m=async(e,t,a,n,s,r)=>e.length===0?[]:(await p(e,u,async i=>await this.#f(i,t,a,n,s,r)??"")).filter(i=>!!i);#f=async(e,t,a,n,s,r)=>"$ref"in e?this.#y(e,t,a,n,s,r):e.payload?this.#u(e,t,a,n,s,r):null;#y=async(e,t,a,n,s,r)=>{const o=e.$ref.startsWith("#/channels/")?this.#e(e.$ref,a):e.$ref;if(!o)return null;const i=y(o);if(!i||!i.componentName||i.componentType!=="messages")return null;const c=a.documentWithReferences.components?.messages[i.componentName];return!c?.payload||!("$ref"in c.payload)||!c.payload.$ref?null:this.#t(c.payload.$ref,t,a,n,s,r)};#e=(e,t)=>{const a=w(e);if(!a||!a.channelName||!a.messageName)return null;const n=t.documentWithReferences.channels?.[a.channelName];if(!n?.messages)return null;const s=n.messages[a.messageName];return!s||!("$ref"in s)||typeof s.$ref!="string"||!s.$ref.startsWith("#/components/messages/")?null:s.$ref};#u=async(e,t,a,n,s,r)=>!e.payload||!("$ref"in e.payload)||!e.payload.$ref?null:this.#t(e.payload.$ref,t,a,n,s,r);#t=async(e,t,a,n,s,r)=>{const o=y(e);if(!o||!o.componentName||o.componentType!=="schemas")return null;const i=`${n}-${f(o.componentName)}`;return await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"uses",targetKey:i,sourceFile:a.realRelativePath,fileHash:a.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r}),i}}export{M as AsyncApiEntitiesExtractor};
1
+ import{removeLeadingSlash as d}from"@redocly/theme/core/utils";import{toKebabCase as f}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as p}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as $}from"../../../../../utils/async/promise-map-limit-with-status.js";import{removeMarkdocTags as E}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as w}from"./base.js";import{extractPartsFromComponentsRef as y}from"../../../utils/extract-parts-from-components-ref.js";import{extractPartsFromChannelsMessageRef as S}from"../../../utils/extract-parts-from-channels-message-ref.js";const u=15;class T extends w{constructor(e){super("asyncapi",e)}mapApiDescriptionToEntity(e,t){const a=d(e.realRelativePath),r=e.document.info.title,s=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.document["x-redocly-catalog-key"]});return{type:this.type,key:s,title:r,summary:E(e.document.info.description),tags:e.document.info.tags?.map(n=>n.name),metadata:{specType:this.specType,descriptionFile:a},version:t}}async loadApiDescriptions(){return(await this.context.cache.load(".","asyncapi-docs")).data}async processApiDescription(e,t,a,r){const s=this.getRbacTeamsForDefinition(e.relativePath),n=this.mapApiDescriptionToEntity(e,a);await this.catalogEntitiesService.createEntity({entity:n,sourceFile:e.realRelativePath,fileHash:e.hash,isRootEntity:!0,rbacTeams:s,source:"file"}),r.delete(`${n.key}:${a}`);const o=this.#a(e),[c,i]=await Promise.allSettled([this.#s(e,n.key,n.version,a,t,r,s),this.#n(o,e,n.key,n.version,a,t,r,s)]);c.status!=="fulfilled"&&this.context.logger.error("Schema processing failed:",c.reason),i.status!=="fulfilled"&&this.context.logger.error("Operation processing failed:",i.reason)}#a=e=>{const t=e.documentWithReferences.operations;return t?Object.entries(t).map(([a,r])=>({operationName:a,operation:r})):[]};#s=async(e,t,a,r,s,n,o)=>{const c=e.document.components?.schemas;if(!c)return;const i=Object.entries(c);if(i.length===0)return;const l=await $(i,u,async([h,m])=>{const R=`${t}-${f(h)}`,g=await this.#r({schemaName:h,schema:m,description:e,parentKey:t,parentVersion:a,parentRevision:s,rbacTeams:o});n.delete(`${R}:${r}`),g&&await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"uses",targetKey:g.key,sourceFile:e.realRelativePath,fileHash:e.hash,sourceVersion:a,targetVersion:a,sourceRevision:s,targetRevision:s})},this.context.logger);l.count.failed>0&&this.context.logger.warn(`Schema processing completed with ${l.count.failed} failures out of ${i.length} schemas for ${e.realRelativePath}`)};#r=async({schemaName:e,schema:t,description:a,parentKey:r,parentVersion:s,parentRevision:n,rbacTeams:o})=>{const c=`${r}-${f(e)}`,i="title"in t?t.title??t.description:null,l=JSON.stringify(t),h={type:"data-schema",key:c,title:e,summary:i,tags:[],metadata:{specType:this.specType,schema:l},version:s};try{return await this.catalogEntitiesService.createEntity({entity:h,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:o,source:"file",revision:n})}catch(m){return this.context.logger.warn(`Failed to create data schema entity for ${e}: ${m instanceof Error?m.message:"Unknown error"}`),null}};#n=async(e,t,a,r,s,n,o,c)=>{if(!e.length)return;const i=await $(e,u,async({operationName:l,operation:h})=>{const m=await this.#o(h,l,t,a,r,n,c);o.delete(`${m}:${s}`)},this.context.logger);i.count.failed>0&&this.context.logger.warn(`Operation processing completed with ${i.count.failed} failures out of ${e.length} operations for ${t.realRelativePath}`)};#o=async(e,t,a,r,s,n,o)=>{const c=`${r}-${f(t)}`,i=await this.#c(e.messages??[],a,r),l=await this.#i(t,e,i,a,r,s,n,o);return l&&await this.#l({apiOperationKey:l.key,operation:e,descriptionUniqueKey:r,description:a,descriptionVersion:s,parentRevision:n}),c};#c=async(e,t,a)=>{if(!e||e.length===0)return[];const r=new Set;for(const s of e){let n=null;if("$ref"in s){const o=s.$ref.startsWith("#/channels/")?this.#e(s.$ref,t):s.$ref;if(o){const c=y(o);if(c?.componentName&&c.componentType==="messages"){const i=t.documentWithReferences.components?.messages[c.componentName];i?.payload&&"$ref"in i.payload&&i.payload.$ref&&(n=i.payload.$ref)}}}else s.payload&&"$ref"in s.payload&&s.payload.$ref&&(n=s.payload.$ref);if(n){const o=y(n);o?.componentName&&o.componentType==="schemas"&&r.add(`${a}-${f(o.componentName)}`)}}return Array.from(r)};#i=async(e,t,a,r,s,n,o,c)=>{const i={type:"api-operation",key:`${s}-${f(e)}`,title:t.title||e,summary:t.summary??"",tags:t.tags?.map(l=>l.name)??[],metadata:{method:t.action==="send"?"PUBLISH":"SUBSCRIBE",path:t.channel.address??"",payload:t.action==="receive"?a:[],responses:t.action==="send"?a:[]},version:n};try{return await this.catalogEntitiesService.createEntity({entity:i,sourceFile:r.realRelativePath,fileHash:r.hash,rbacTeams:c,source:"file",revision:o})}catch(l){return this.context.logger.warn(`Failed to create API operation entity for ${e}: ${l instanceof Error?l.message:"Unknown error"}`),null}};#l=async({apiOperationKey:e,operation:t,descriptionUniqueKey:a,description:r,descriptionVersion:s,parentRevision:n})=>(await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"partOf",targetKey:a,sourceFile:r.realRelativePath,fileHash:r.hash,sourceVersion:s,targetVersion:s,sourceRevision:n,targetRevision:n}),await this.#h(t,e,r,s,n),!Array.isArray(t.messages)||!t.messages?.length?[]:await this.#m(t.messages,e,r,a,s,n));#h=async(e,t,a,r,s)=>{e["x-catalogRelations"]?.length&&await p(e["x-catalogRelations"],u,async n=>{try{this.validateEntityRelationFileSchema(n),await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:n.type,targetKey:n.key,sourceFile:a.realRelativePath,fileHash:a.hash,sourceVersion:r,targetVersion:"",sourceRevision:s,targetRevision:""})}catch(o){this.context.logger.warn(`Error creating entity relation for operation ${t} based on custom property: ${o instanceof Error?o.message:"Unknown error"}`)}})};#m=async(e,t,a,r,s,n)=>e.length===0?[]:(await p(e,u,async c=>await this.#f(c,t,a,r,s,n)??"")).filter(c=>!!c);#f=async(e,t,a,r,s,n)=>"$ref"in e?this.#y(e,t,a,r,s,n):e.payload?this.#u(e,t,a,r,s,n):null;#y=async(e,t,a,r,s,n)=>{const o=e.$ref.startsWith("#/channels/")?this.#e(e.$ref,a):e.$ref;if(!o)return null;const c=y(o);if(!c||!c.componentName||c.componentType!=="messages")return null;const i=a.documentWithReferences.components?.messages[c.componentName];return!i?.payload||!("$ref"in i.payload)||!i.payload.$ref?null:this.#t(i.payload.$ref,t,a,r,s,n)};#e=(e,t)=>{const a=S(e);if(!a||!a.channelName||!a.messageName)return null;const r=t.documentWithReferences.channels?.[a.channelName];if(!r?.messages)return null;const s=r.messages[a.messageName];return!s||!("$ref"in s)||typeof s.$ref!="string"||!s.$ref.startsWith("#/components/messages/")?null:s.$ref};#u=async(e,t,a,r,s,n)=>!e.payload||!("$ref"in e.payload)||!e.payload.$ref?null:this.#t(e.payload.$ref,t,a,r,s,n);#t=async(e,t,a,r,s,n)=>{const o=y(e);if(!o||!o.componentName||o.componentType!=="schemas")return null;const c=`${r}-${f(o.componentName)}`;return await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"uses",targetKey:c,sourceFile:a.realRelativePath,fileHash:a.hash,sourceVersion:s,targetVersion:s,sourceRevision:n,targetRevision:n}),c}}export{T as AsyncApiEntitiesExtractor};
@@ -1,3 +1,3 @@
1
- import{buildSchema as O,isObjectType as g,isScalarType as I,isEnumType as P,isInterfaceType as w,isUnionType as E,isInputObjectType as S,getNamedType as u,printType as F}from"graphql";import{removeLeadingSlash as k}from"@redocly/theme/core/utils";import{toKebabCase as $}from"../../../../../../utils/string/to-kebab-case.js";import{capitalize as A}from"../../../../../../utils/string/capitalize.js";import{promiseMapLimit as T}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as R}from"../../../../../utils/async/promise-map-limit-with-status.js";import{sha1 as j}from"../../../../../utils/crypto/sha1.js";import{removeMarkdocTags as D}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as N}from"./base.js";const b=15,v=15,_=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class Q extends N{#t;constructor(t){super("graphql",t),this.#t=t.context.logger}async loadApiDescriptions(){const t=[];for(const{relativePath:e}of this.context.fs.scan(/(\.gql|\.graphql)$/))try{if(e.includes("@l10n")||await this.context.isPathIgnored(e))continue;const a=await this.context.cache.load(e,"graphql-doc");if(!a.data)continue;const{content:i,metadata:n}=a.data,s=O(i),r=j(i);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:r,schema:s,content:i,metadata:n})}catch(a){this.#t.warn(`Failed to load GraphQL schema from ${e}: ${a instanceof Error?a.message:"Unknown error"}`)}return t}mapApiDescriptionToEntity(t,e){const a=k(t.realRelativePath),i=t.relativePath.replace(/\.(gql|graphql)$/,""),n=this.#s(i.split("/").pop()||"GraphQL Schema"),s=this.#c(t.metadata?.tags),r=t.metadata?.["x-redocly-catalog-key"],h=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:typeof r=="string"?r:void 0,extensionPattern:/\.(gql|graphql)$/});return{type:this.type,key:h,title:n,summary:t.metadata?.description||null,tags:s.concat("graphql"),metadata:{specType:this.specType,descriptionFile:a},version:e}}async processApiDescription(t,e,a,i){const{schema:n}=t;if(!n)return;const s=this.getRbacTeamsForDefinition(t.relativePath),r=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntity({entity:r,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,rbacTeams:s,source:"file",revision:e}),i.delete(`${r.key}:${a}`),await Promise.all([this.#a(t,r.key,r.version,a,e,i,s),this.#f(t,r.key,r.version,a,e,i,s)])}#a=async(t,e,a,i,n,s,r)=>{const{schema:h}=t,c=h.getTypeMap(),l=this.#n(h),o=Object.entries(c).filter(([f])=>!f.startsWith("__")&&!_.has(f)&&!l.has(f));if(o.length===0)return;const p=await R(o,v,async([f,m])=>{const y=await this.#l({typeName:f,type:m,description:t,parentKey:e,parentVersion:a,parentRevision:n,rbacTeams:r});s.delete(`${y?.key}:${i}`),y&&await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"uses",targetKey:y.key,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:n,targetRevision:n})},this.#t);p.count.failed>0&&this.#t.warn(`Schema processing completed with ${p.count.failed} failures out of ${o.length} types for ${t.realRelativePath}`),await this.#p({description:t,descriptionUniqueKey:e,userTypes:o,parentRevision:n})};#s=t=>{const e=t.replace(/[^A-Za-z0-9]+/g," ").trim();return e?e.split(" ").map(a=>a&&A(a)).join(" "):"GraphQL Schema"};#e=(t,e)=>`${e}-${$(t)}`;#r=t=>g(t)?"object":w(t)?"interface":E(t)?"union":P(t)?"enum":S(t)?"input":I(t)?"scalar":"unknown";#n=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const i=t.getMutationType();i&&e.add(i.name);const n=t.getSubscriptionType();return n&&e.add(n.name),e};#i(t){const e=[],a=t.getQueryType();if(a){const s=a.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"QUERY",rootTypeName:a.name})}const i=t.getMutationType();if(i){const s=i.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"MUTATION",rootTypeName:i.name})}const n=t.getSubscriptionType();if(n){const s=n.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"SUBSCRIBE",rootTypeName:n.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const s of t.args){const r=u(s.type);r&&!r.name.startsWith("__")&&a.push(this.#e(r.name,e))}const i=[],n=u(t.type);return n&&!n.name.startsWith("__")&&i.push(this.#e(n.name,e)),{inputTypes:a,returnTypes:i}};#c=t=>{if(Array.isArray(t))return t.map(e=>String(e)).map(e=>e.trim()).filter(e=>e.length>0);if(typeof t=="string"){const e=t.trim();return e?[e]:[]}return[]};#l=async({typeName:t,type:e,description:a,parentKey:i,parentVersion:n,parentRevision:s,rbacTeams:r})=>{const h=this.#e(t,i),c=e.description??null,l=this.#r(e),o={type:"data-schema",key:h,title:t,summary:c,tags:["graphql"],metadata:{specType:this.specType,typeKind:l,sdl:this.#h(e,a.schema)},version:n};try{return await this.catalogEntitiesService.createEntity({entity:o,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:r,source:"file",revision:s})}catch(p){return this.#t.warn(`Failed to create data schema entity for ${t}: ${p instanceof Error?p.message:"Unknown error"}`),null}};#h=(t,e)=>{const a=new Set,i=[],n=new Set(["String","ID","Int","Float","Boolean"]),s=c=>{if(!c)return;const l=c.name;if(l.startsWith("__")||n.has(l)||a.has(l))return;const o=e.getType(l);o&&(a.add(l),i.push(o))};for(s(t);i.length>0;){const c=i.pop();if(g(c)){for(const o of c.getInterfaces?.()??[])s(o);const l=c.getFields();for(const o of Object.values(l)){s(u(o.type));for(const p of o.args??[])s(u(p.type))}}else if(w(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}else if(E(c))for(const l of c.getTypes())s(l);else if(S(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}}const r=[t.name,...[...a].filter(c=>c!==t.name)],h=[];for(const c of r){const l=e.getType(c);l&&h.push(F(l))}return h.join(`
1
+ import{buildSchema as v,isObjectType as T,isScalarType as I,isEnumType as P,isInterfaceType as E,isUnionType as S,isInputObjectType as $,getNamedType as u,printType as F}from"graphql";import{removeLeadingSlash as A}from"@redocly/theme/core/utils";import{toKebabCase as d}from"../../../../../../utils/string/to-kebab-case.js";import{capitalize as k}from"../../../../../../utils/string/capitalize.js";import{promiseMapLimit as w}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as R}from"../../../../../utils/async/promise-map-limit-with-status.js";import{sha1 as j}from"../../../../../utils/crypto/sha1.js";import{removeMarkdocTags as D}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as L}from"./base.js";const O=15,b=15,C=new Set(["String","ID","Int","Float","Boolean","DateTime","Date","Time","URL","URI","JSON","JSONObject","BigInt","BigDecimal"]);class U extends L{#t;constructor(t){super("graphql",t),this.#t=t.context.logger}async loadApiDescriptions(){const t=[];for(const{relativePath:e}of this.context.fs.scan(/(\.gql|\.graphql)$/))try{if(e.includes("@l10n")||await this.context.isPathIgnored(e))continue;const a=await this.context.cache.load(e,"graphql-doc");if(!a.data)continue;const{content:i,metadata:n}=a.data,s=v(i),r=j(i);t.push({realRelativePath:e,relativePath:e,isVirtual:!1,hash:r,schema:s,content:i,metadata:n})}catch(a){this.#t.warn(`Failed to load GraphQL schema from ${e}: ${a instanceof Error?a.message:"Unknown error"}`)}return t}mapApiDescriptionToEntity(t,e){const a=A(t.realRelativePath),i=t.relativePath.replace(/\.(gql|graphql)$/,""),n=this.#s(i.split("/").pop()||"GraphQL Schema"),s=this.#c(t.metadata?.tags),r=t.metadata?.["x-redocly-catalog-key"],h=this.resolveEntityKey({realRelativePath:t.realRelativePath,customKey:typeof r=="string"?r:void 0,extensionPattern:/\.(gql|graphql)$/});return{type:this.type,key:h,title:n,summary:t.metadata?.description||null,tags:s.concat("graphql"),metadata:{specType:this.specType,descriptionFile:a},version:e}}async processApiDescription(t,e,a,i){const{schema:n}=t;if(!n)throw new Error("GraphQL definition is missing a parsed schema");const s=this.getRbacTeamsForDefinition(t.relativePath),r=this.mapApiDescriptionToEntity(t,a);await this.catalogEntitiesService.createEntity({entity:r,sourceFile:t.realRelativePath,fileHash:t.hash,isRootEntity:!0,rbacTeams:s,source:"file",revision:e}),i.delete(`${r.key}:${a}`),await Promise.all([this.#a(t,r.key,r.version,a,e,i,s),this.#f(t,r.key,r.version,a,e,i,s)])}#a=async(t,e,a,i,n,s,r)=>{const{schema:h}=t,c=h.getTypeMap(),l=this.#n(h),o=Object.entries(c).filter(([f])=>!f.startsWith("__")&&!C.has(f)&&!l.has(f));if(o.length===0)return;const p=await R(o,b,async([f,m])=>{const y=this.#e(f,e),g=await this.#l({typeName:f,type:m,description:t,parentKey:e,parentVersion:a,parentRevision:n,rbacTeams:r});s.delete(`${y}:${i}`),g&&await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"uses",targetKey:g.key,sourceFile:t.realRelativePath,fileHash:t.hash,sourceVersion:a,targetVersion:a,sourceRevision:n,targetRevision:n})},this.#t);p.count.failed>0&&this.#t.warn(`Schema processing completed with ${p.count.failed} failures out of ${o.length} types for ${t.realRelativePath}`),await this.#p({description:t,descriptionUniqueKey:e,userTypes:o,parentRevision:n})};#s=t=>{const e=t.replace(/[^A-Za-z0-9]+/g," ").trim();return e?e.split(" ").map(a=>a&&k(a)).join(" "):"GraphQL Schema"};#e=(t,e)=>`${e}-${d(t)}`;#r=t=>T(t)?"object":E(t)?"interface":S(t)?"union":P(t)?"enum":$(t)?"input":I(t)?"scalar":"unknown";#n=t=>{const e=new Set,a=t.getQueryType();a&&e.add(a.name);const i=t.getMutationType();i&&e.add(i.name);const n=t.getSubscriptionType();return n&&e.add(n.name),e};#i(t){const e=[],a=t.getQueryType();if(a){const s=a.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"QUERY",rootTypeName:a.name})}const i=t.getMutationType();if(i){const s=i.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"MUTATION",rootTypeName:i.name})}const n=t.getSubscriptionType();if(n){const s=n.getFields();for(const[r,h]of Object.entries(s))e.push({fieldName:r,field:h,operationType:"SUBSCRIBE",rootTypeName:n.name})}return e}#o=(t,e)=>{const a=[];if(t.args)for(const s of t.args){const r=u(s.type);r&&!r.name.startsWith("__")&&a.push(this.#e(r.name,e))}const i=[],n=u(t.type);return n&&!n.name.startsWith("__")&&i.push(this.#e(n.name,e)),{inputTypes:a,returnTypes:i}};#c=t=>{if(Array.isArray(t))return t.map(e=>String(e)).map(e=>e.trim()).filter(e=>e.length>0);if(typeof t=="string"){const e=t.trim();return e?[e]:[]}return[]};#l=async({typeName:t,type:e,description:a,parentKey:i,parentVersion:n,parentRevision:s,rbacTeams:r})=>{const h=this.#e(t,i),c=e.description??null,l=this.#r(e),o={type:"data-schema",key:h,title:t,summary:c,tags:["graphql"],metadata:{specType:this.specType,typeKind:l,sdl:this.#h(e,a.schema)},version:n};try{return await this.catalogEntitiesService.createEntity({entity:o,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:r,source:"file",revision:s})}catch(p){return this.#t.warn(`Failed to create data schema entity for ${t}: ${p instanceof Error?p.message:"Unknown error"}`),null}};#h=(t,e)=>{const a=new Set,i=[],n=new Set(["String","ID","Int","Float","Boolean"]),s=c=>{if(!c)return;const l=c.name;if(l.startsWith("__")||n.has(l)||a.has(l))return;const o=e.getType(l);o&&(a.add(l),i.push(o))};for(s(t);i.length>0;){const c=i.pop();if(T(c)){for(const o of c.getInterfaces?.()??[])s(o);const l=c.getFields();for(const o of Object.values(l)){s(u(o.type));for(const p of o.args??[])s(u(p.type))}}else if(E(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}else if(S(c))for(const l of c.getTypes())s(l);else if($(c)){const l=c.getFields();for(const o of Object.values(l))s(u(o.type))}}const r=[t.name,...[...a].filter(c=>c!==t.name)],h=[];for(const c of r){const l=e.getType(c);l&&h.push(F(l))}return h.join(`
2
2
 
3
- `)};#p=async({description:t,descriptionUniqueKey:e,userTypes:a,parentRevision:i})=>{const n=a.filter(([,s])=>g(s));n.length!==0&&await T(n,v,async([s,r])=>{const c=r.getInterfaces?.()??[];if(!c.length)return;const l=this.#e(s,e);await T([...c],5,async o=>{const p=this.#e(o.name,e);try{await this.catalogEntitiesService.createEntityRelation({sourceKey:l,type:"implements",targetKey:p,sourceFile:t.realRelativePath,fileHash:t.hash,sourceRevision:i,targetRevision:i})}catch(f){this.#t.warn(`Failed to create 'implements' relation ${l} -> ${p}: ${f instanceof Error?f.message:"Unknown error"}`)}})})};#f=async(t,e,a,i,n,s,r)=>{const{schema:h}=t,c=this.#i(h);if(c.length===0)return;const o=(await R(c,b,async({fieldName:p,field:f,operationType:m,rootTypeName:y})=>{const d=await this.#y(p,f,m,y,t,e,a,n,r);d&&s.delete(`${d}:${i}`)},this.#t)).count.failed;o>0&&this.#t.warn(`Operation extraction completed with ${o} failures out of ${c.length} operations for ${e}`)};#y=async(t,e,a,i,n,s,r,h,c)=>{const{inputTypes:l,returnTypes:o}=this.#o(e,s),p=await this.#u({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:l,returnTypes:o,description:n,descriptionUniqueKey:s,descriptionVersion:r,parentRevision:h,rbacTeams:c});return p&&await this.#m({apiOperationKey:p.key,inputTypes:l,returnTypes:o,descriptionUniqueKey:s,description:n,descriptionVersion:r,parentRevision:h}),p?.key??null};#u=async({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:n,returnTypes:s,description:r,descriptionUniqueKey:h,descriptionVersion:c,parentRevision:l,rbacTeams:o})=>{const p=t,m={type:"api-operation",key:`${h}-${$(`${a.toLowerCase()}-${t}`)}`,title:p,summary:e.description?D(e.description):null,tags:["graphql"],metadata:{method:a,path:`${i}.${t}`,payload:n,responses:s},version:c};try{return await this.catalogEntitiesService.createEntity({entity:m,sourceFile:r.realRelativePath,fileHash:r.hash,rbacTeams:o,source:"file",revision:l})}catch(y){return this.#t.warn(`Failed to create API operation entity for ${p}: ${y instanceof Error?y.message:"Unknown error"}`),null}};#m=async({apiOperationKey:t,inputTypes:e,returnTypes:a,descriptionUniqueKey:i,description:n,descriptionVersion:s,parentRevision:r})=>{await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"partOf",targetKey:i,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r});const h=[...new Set(e)],c=[...new Set(a)],l=[...h.map(o=>({key:o,relationType:"uses"})),...c.map(o=>({key:o,relationType:"returns"}))];await T(l,b,async({key:o,relationType:p})=>{try{await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:p,targetKey:o,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r})}catch(f){this.#t.warn(`Failed to create relation between operation ${t} and type ${o} (${p}): ${f instanceof Error?f.message:"Unknown error"}`)}})}}export{Q as GraphqlEntitiesExtractor};
3
+ `)};#p=async({description:t,descriptionUniqueKey:e,userTypes:a,parentRevision:i})=>{const n=a.filter(([,s])=>T(s));n.length!==0&&await w(n,b,async([s,r])=>{const c=r.getInterfaces?.()??[];if(!c.length)return;const l=this.#e(s,e);await w([...c],5,async o=>{const p=this.#e(o.name,e);try{await this.catalogEntitiesService.createEntityRelation({sourceKey:l,type:"implements",targetKey:p,sourceFile:t.realRelativePath,fileHash:t.hash,sourceRevision:i,targetRevision:i})}catch(f){this.#t.warn(`Failed to create 'implements' relation ${l} -> ${p}: ${f instanceof Error?f.message:"Unknown error"}`)}})})};#f=async(t,e,a,i,n,s,r)=>{const{schema:h}=t,c=this.#i(h);if(c.length===0)return;const o=(await R(c,O,async({fieldName:p,field:f,operationType:m,rootTypeName:y})=>{const g=await this.#y(p,f,m,y,t,e,a,n,r);s.delete(`${g}:${i}`)},this.#t)).count.failed;o>0&&this.#t.warn(`Operation extraction completed with ${o} failures out of ${c.length} operations for ${e}`)};#y=async(t,e,a,i,n,s,r,h,c)=>{const l=`${s}-${d(`${a.toLowerCase()}-${t}`)}`,{inputTypes:o,returnTypes:p}=this.#o(e,s),f=await this.#u({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:o,returnTypes:p,description:n,descriptionUniqueKey:s,descriptionVersion:r,parentRevision:h,rbacTeams:c});return f&&await this.#m({apiOperationKey:f.key,inputTypes:o,returnTypes:p,descriptionUniqueKey:s,description:n,descriptionVersion:r,parentRevision:h}),l};#u=async({fieldName:t,field:e,operationType:a,rootTypeName:i,inputTypes:n,returnTypes:s,description:r,descriptionUniqueKey:h,descriptionVersion:c,parentRevision:l,rbacTeams:o})=>{const p=t,m={type:"api-operation",key:`${h}-${d(`${a.toLowerCase()}-${t}`)}`,title:p,summary:e.description?D(e.description):null,tags:["graphql"],metadata:{method:a,path:`${i}.${t}`,payload:n,responses:s},version:c};try{return await this.catalogEntitiesService.createEntity({entity:m,sourceFile:r.realRelativePath,fileHash:r.hash,rbacTeams:o,source:"file",revision:l})}catch(y){return this.#t.warn(`Failed to create API operation entity for ${p}: ${y instanceof Error?y.message:"Unknown error"}`),null}};#m=async({apiOperationKey:t,inputTypes:e,returnTypes:a,descriptionUniqueKey:i,description:n,descriptionVersion:s,parentRevision:r})=>{await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:"partOf",targetKey:i,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r});const h=[...new Set(e)],c=[...new Set(a)],l=[...h.map(o=>({key:o,relationType:"uses"})),...c.map(o=>({key:o,relationType:"returns"}))];await w(l,O,async({key:o,relationType:p})=>{try{await this.catalogEntitiesService.createEntityRelation({sourceKey:t,type:p,targetKey:o,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:s,targetVersion:s,sourceRevision:r,targetRevision:r})}catch(f){this.#t.warn(`Failed to create relation between operation ${t} and type ${o} (${p}): ${f instanceof Error?f.message:"Unknown error"}`)}})}}export{U as GraphqlEntitiesExtractor};
@@ -1 +1 @@
1
- import{REDOCLY_TEAMS_RBAC as $}from"@redocly/config";import{removeLeadingSlash as x}from"@redocly/theme/core/utils";import{toKebabCase as y}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as N}from"../../../../../utils/async/promise-map-limit-with-status.js";import{extractTeamsFromScopeItems as R}from"../../../../../utils/rbac.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as b}from"./base.js";import{OpenapiSchemaResolver as S}from"../../../utils/openapi-schema-resolver.js";import{extractPartsFromComponentsRef as k}from"../../../utils/extract-parts-from-components-ref.js";import{isValidTagName as v}from"../../../utils/is-valid-tag-name.js";const A=["get","post","put","delete","patch"],O=15,T=15;class _ extends b{#e;constructor(e){super("openapi",e),this.#e=e.context.logger}async loadApiDescriptions(){return await this.actions.loadOpenApiDefinitions(this.context)}mapApiDescriptionToEntity(e,n){const s=x(e.realRelativePath),r=e.definition.info.title,t=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.definition["x-redocly-catalog-key"]});return{type:this.type,key:t,title:r,summary:w(e.definition.info.description),tags:e.definition.tags?.filter(a=>a.name&&v(a.name)).map(a=>a.name),metadata:{specType:this.specType,descriptionFile:s},version:n}}async processApiDescription(e,n,s,r){if(S.clearSchemaCache(),!e?.definition?.paths)return;const t=this.getRbacTeamsForDefinition(e.relativePath),a=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntity({entity:a,sourceFile:e.realRelativePath,fileHash:e.hash,source:"file",isRootEntity:!0,rbacTeams:t,revision:n}),r.delete(`${a.key}:${s}`),await this.#r(e,a.key,a.version,s,n,r,t);const o=this.#s(e.definition.paths);if(o.length!==0){const c=(await N(o,O,async({operation:m,path:h,method:l})=>{if(!m.operationId)return;const f=await this.#n(m,h,l,e,a.key,a.version,n,t);f&&r.delete(`${f}:${s}`)},this.#e)).count.failed;c>0&&this.#e.warn(`Extraction completed with ${c} failures out of ${o.length} operations for ${a.key}`)}}#s(e){return Object.entries(e).flatMap(([n,s])=>A.filter(r=>s[r]).map(r=>{const t=s[r];if(!t)throw new Error(`Operation not found for method ${r} on path ${n}`);return{operation:t,path:n,method:r.toUpperCase()}}))}async#r(e,n,s,r,t,a,o){const i=e.definition.components?.schemas;if(!i)return;const c=Object.entries(i);c.length!==0&&await E(c,T,async([m,h])=>{const l=await this.#o({schemaName:m,schema:h,description:e,parentKey:n,parentVersion:s,parentRevision:t,rbacTeams:o});a.delete(`${l?.key}:${r}`),l&&await this.catalogEntitiesService.createEntityRelation({sourceKey:n,sourceVersion:s,sourceRevision:t,type:"uses",targetKey:l.key,targetVersion:s,targetRevision:t,sourceFile:e.realRelativePath,fileHash:e.hash})})}async#o({schemaName:e,schema:n,description:s,parentKey:r,parentVersion:t,parentRevision:a,rbacTeams:o}){const i=S.resolveSchemaRefs(n,s),c=JSON.stringify(i),m=i[$]?R(i[$]):o,h=R(i["x-rbac"]),l={type:"data-schema",key:`${r}-${y(e)}`,title:e,summary:i.description??i.title??null,tags:[],metadata:{specType:this.specType,schema:c},version:t};try{return await this.catalogEntitiesService.createEntity({entity:l,sourceFile:s.realRelativePath,fileHash:s.hash,rbacTeams:h.length?h:m,source:"file",revision:a})}catch(f){return this.#e.error(`Failed to create data schema entity for ${e}: ${f instanceof Error?f.message:"Unknown error"}`),null}}async#n(e,n,s,r,t,a,o,i){const c=await Promise.all([this.#h(e.requestBody??null,r),this.#m(e.responses??{},r)]),m=c[0].schemaNames,h=c[1].schemaNames;c[0].errors.length>0&&this.#e.warn(`Schema extraction errors for operation ${e.operationId}: ${c[0].errors.join(", ")}`),c[1].errors.length>0&&this.#e.warn(`Response schema extraction errors for operation ${e.operationId}: ${c[1].errors.join(", ")}`);const l=m.map(u=>`${t}-${y(u)}`),f=h.map(u=>`${t}-${y(u)}`),p=await this.#f({path:n,method:s,operation:e,requestBodySchemasKeys:l,responseSchemasKeys:f,description:r,parentKey:t,parentVersion:a,parentRevision:o,rbacTeams:i});return p&&await Promise.all([this.#i(m,e.operationId??"",r.realRelativePath,r.hash,t,a,o),this.#c(h,e.operationId??"",r.realRelativePath,r.hash,t,a,o),this.#p({apiOperationKey:p.key,operationRelations:e["x-catalogRelations"],descriptionUniqueKey:t,description:r,parentVersion:a,parentRevision:o})]),p?.key??null}async#i(e,n,s,r,t,a,o){return e.length===0||!n?[]:await this.#a(e,n,s,r,t,a,o)}async#c(e,n,s,r,t,a,o){return e.length===0||!n?[]:await this.#a(e,n,s,r,t,a,o)}#h(e,n){const s=[],r=[];try{if(e&&"content"in e&&e.content)for(const t of Object.values(e.content)){if(!t.schema?.$ref)continue;const a=this.#t(t.schema.$ref);a?.componentType==="schemas"&&a.componentName&&s.push(a.componentName)}if(e&&e.$ref){const t=this.#t(e.$ref);if(t?.componentType==="requestBodies"&&t.componentName){const a=n.definition.components?.requestBodies?.[t.componentName];if(a&&"content"in a)for(const o of Object.values(a.content??{})){if(!o.schema?.$ref)continue;const i=this.#t(o.schema.$ref);i?.componentType==="schemas"&&i.componentName&&s.push(i.componentName)}}}}catch(t){r.push(`Failed to extract request body schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:r}}#m(e,n){const s=[],r=[];try{for(const t of Object.values(e)){if(t&&"content"in t&&t.content)for(const a of Object.values(t.content)){if(!a.schema?.$ref)continue;const o=this.#t(a.schema.$ref);o?.componentType==="schemas"&&o.componentName&&s.push(o.componentName)}if(t&&t.$ref){const a=this.#t(t.$ref);if(a?.componentType==="responses"&&a.componentName){const o=n.definition.components?.responses?.[a.componentName];if(o&&"content"in o)for(const i of Object.values(o.content??{})){if(!i.schema?.$ref)continue;const c=this.#t(i.schema.$ref);c?.componentType==="schemas"&&c.componentName&&s.push(c.componentName)}}}}}catch(t){r.push(`Failed to extract response schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:r}}#t(e){try{return k(e)}catch{return{componentType:"",componentName:null}}}async#a(e,n,s,r,t,a,o){return e.length===0?[]:await E(e,T,async i=>await this.#l({operationId:n,schemaName:i,descriptionSourceFile:s,descriptionHash:r,parentKey:t,parentVersion:a,parentRevision:o}))}async#l({operationId:e,schemaName:n,descriptionSourceFile:s,descriptionHash:r,parentKey:t,parentVersion:a,parentRevision:o}){const i=`${t}-${y(n)}`;try{return await this.catalogEntitiesService.createEntityRelation({sourceKey:`${t}-${y(e)}`,type:"uses",targetKey:i,sourceFile:s,fileHash:r,sourceVersion:a,targetVersion:a,sourceRevision:o,targetRevision:o}),i}catch(c){throw this.#e.error(`Failed to create relation between operation ${e} and schema ${n}: ${c instanceof Error?c.message:"Unknown error"}`),c}}async#f({path:e,method:n,operation:s,requestBodySchemasKeys:r,responseSchemasKeys:t,description:a,parentKey:o,parentVersion:i,parentRevision:c,rbacTeams:m}){const h=`${s.operationId}`,l=`${o}-${y(h)}`,f=s[$]?R(s[$]):m,p=R(s["x-rbac"]),u={type:"api-operation",key:l,title:h,summary:w(s.summary),tags:s.tags?.filter(g=>v(g)),metadata:{path:e,method:n,payload:r,responses:t},version:i};try{return await this.catalogEntitiesService.createEntity({entity:u,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:p.length>0?p:f,source:"file",revision:c})}catch(g){return this.#e.error(`Failed to create API operation entity for ${h}: ${g instanceof Error?g.message:"Unknown error"}`),null}}async#p({apiOperationKey:e,operationRelations:n,descriptionUniqueKey:s,description:r,parentVersion:t,parentRevision:a}){try{await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"partOf",targetKey:s,sourceFile:r.realRelativePath,fileHash:r.hash,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),await this.#y(e,r,n,t,a)}catch(o){this.#e.error(`Failed to create API operation relations for ${e}: ${o instanceof Error?o.message:"Unknown error"}`)}}async#y(e,n,s,r,t){s?.length&&await E(s,O,async a=>{try{this.validateEntityRelationFileSchema(a),await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:a.type,targetKey:a.key,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:r,targetVersion:"",sourceRevision:t,targetRevision:""})}catch(o){this.context.logger.warn(`Error creating entity relation for operation ${e} based on custom property: ${o instanceof Error?o.message:"Unknown error"}`)}})}}export{_ as OpenApiEntitiesExtractor};
1
+ import{REDOCLY_TEAMS_RBAC as g}from"@redocly/config";import{removeLeadingSlash as x}from"@redocly/theme/core/utils";import{toKebabCase as y}from"../../../../../../utils/string/to-kebab-case.js";import{promiseMapLimit as E}from"../../../../../utils/async/promise-map-limit.js";import{promiseMapLimitWithStatus as b}from"../../../../../utils/async/promise-map-limit-with-status.js";import{extractTeamsFromScopeItems as R}from"../../../../../utils/rbac.js";import{removeMarkdocTags as w}from"../../../../../../markdoc/helpers/remove-markdoc-tags.js";import{BaseApiEntitiesExtractor as d}from"./base.js";import{OpenapiSchemaResolver as S}from"../../../utils/openapi-schema-resolver.js";import{extractPartsFromComponentsRef as A}from"../../../utils/extract-parts-from-components-ref.js";import{isValidTagName as v}from"../../../utils/is-valid-tag-name.js";const N=["get","post","put","delete","patch"],O=15,T=15;class _ extends d{#e;constructor(e){super("openapi",e),this.#e=e.context.logger}async loadApiDescriptions(){return await this.actions.loadOpenApiDefinitions(this.context)}mapApiDescriptionToEntity(e,n){const s=x(e.realRelativePath),r=e.definition.info.title,t=this.resolveEntityKey({realRelativePath:e.realRelativePath,customKey:e.definition["x-redocly-catalog-key"]});return{type:this.type,key:t,title:r,summary:w(e.definition.info.description),tags:e.definition.tags?.filter(a=>a.name&&v(a.name)).map(a=>a.name),metadata:{specType:this.specType,descriptionFile:s},version:n}}async processApiDescription(e,n,s,r){if(S.clearSchemaCache(),!e?.definition)throw new Error("OpenAPI definition is missing a bundled document");const t=this.getRbacTeamsForDefinition(e.relativePath),a=this.mapApiDescriptionToEntity(e,s);await this.catalogEntitiesService.createEntity({entity:a,sourceFile:e.realRelativePath,fileHash:e.hash,source:"file",isRootEntity:!0,rbacTeams:t,revision:n}),r.delete(`${a.key}:${s}`),await this.#r(e,a.key,a.version,s,n,r,t);const o=this.#s(e.definition.paths);if(o.length!==0){const c=(await b(o,O,async({operation:h,path:m,method:f})=>{if(!h.operationId)return;const l=await this.#n(h,m,f,e,a.key,a.version,n,t);r.delete(`${l}:${s}`)},this.#e)).count.failed;c>0&&this.#e.warn(`Extraction completed with ${c} failures out of ${o.length} operations for ${a.key}`)}}#s(e){return Object.entries(e??{}).flatMap(([n,s])=>N.filter(r=>s[r]).map(r=>{const t=s[r];if(!t)throw new Error(`Operation not found for method ${r} on path ${n}`);return{operation:t,path:n,method:r.toUpperCase()}}))}async#r(e,n,s,r,t,a,o){const i=e.definition.components?.schemas;if(!i)return;const c=Object.entries(i);c.length!==0&&await E(c,T,async([h,m])=>{const f=`${n}-${y(h)}`,l=await this.#o({schemaName:h,schema:m,description:e,parentKey:n,parentVersion:s,parentRevision:t,rbacTeams:o});a.delete(`${f}:${r}`),l&&await this.catalogEntitiesService.createEntityRelation({sourceKey:n,sourceVersion:s,sourceRevision:t,type:"uses",targetKey:l.key,targetVersion:s,targetRevision:t,sourceFile:e.realRelativePath,fileHash:e.hash})})}async#o({schemaName:e,schema:n,description:s,parentKey:r,parentVersion:t,parentRevision:a,rbacTeams:o}){const i=S.resolveSchemaRefs(n,s),c=JSON.stringify(i),h=i[g]?R(i[g]):o,m=R(i["x-rbac"]),f={type:"data-schema",key:`${r}-${y(e)}`,title:e,summary:i.description??i.title??null,tags:[],metadata:{specType:this.specType,schema:c},version:t};try{return await this.catalogEntitiesService.createEntity({entity:f,sourceFile:s.realRelativePath,fileHash:s.hash,rbacTeams:m.length?m:h,source:"file",revision:a})}catch(l){return this.#e.error(`Failed to create data schema entity for ${e}: ${l instanceof Error?l.message:"Unknown error"}`),null}}async#n(e,n,s,r,t,a,o,i){const c=`${t}-${y(`${e.operationId}`)}`,h=await Promise.all([this.#h(e.requestBody??null,r),this.#m(e.responses??{},r)]),m=h[0].schemaNames,f=h[1].schemaNames;h[0].errors.length>0&&this.#e.warn(`Schema extraction errors for operation ${e.operationId}: ${h[0].errors.join(", ")}`),h[1].errors.length>0&&this.#e.warn(`Response schema extraction errors for operation ${e.operationId}: ${h[1].errors.join(", ")}`);const l=m.map(p=>`${t}-${y(p)}`),u=f.map(p=>`${t}-${y(p)}`),$=await this.#f({path:n,method:s,operation:e,requestBodySchemasKeys:l,responseSchemasKeys:u,description:r,parentKey:t,parentVersion:a,parentRevision:o,rbacTeams:i});return $&&await Promise.all([this.#i(m,e.operationId??"",r.realRelativePath,r.hash,t,a,o),this.#c(f,e.operationId??"",r.realRelativePath,r.hash,t,a,o),this.#p({apiOperationKey:$.key,operationRelations:e["x-catalogRelations"],descriptionUniqueKey:t,description:r,parentVersion:a,parentRevision:o})]),c}async#i(e,n,s,r,t,a,o){return e.length===0||!n?[]:await this.#a(e,n,s,r,t,a,o)}async#c(e,n,s,r,t,a,o){return e.length===0||!n?[]:await this.#a(e,n,s,r,t,a,o)}#h(e,n){const s=[],r=[];try{if(e&&"content"in e&&e.content)for(const t of Object.values(e.content)){if(!t.schema?.$ref)continue;const a=this.#t(t.schema.$ref);a?.componentType==="schemas"&&a.componentName&&s.push(a.componentName)}if(e&&e.$ref){const t=this.#t(e.$ref);if(t?.componentType==="requestBodies"&&t.componentName){const a=n.definition.components?.requestBodies?.[t.componentName];if(a&&"content"in a)for(const o of Object.values(a.content??{})){if(!o.schema?.$ref)continue;const i=this.#t(o.schema.$ref);i?.componentType==="schemas"&&i.componentName&&s.push(i.componentName)}}}}catch(t){r.push(`Failed to extract request body schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:r}}#m(e,n){const s=[],r=[];try{for(const t of Object.values(e)){if(t&&"content"in t&&t.content)for(const a of Object.values(t.content)){if(!a.schema?.$ref)continue;const o=this.#t(a.schema.$ref);o?.componentType==="schemas"&&o.componentName&&s.push(o.componentName)}if(t&&t.$ref){const a=this.#t(t.$ref);if(a?.componentType==="responses"&&a.componentName){const o=n.definition.components?.responses?.[a.componentName];if(o&&"content"in o)for(const i of Object.values(o.content??{})){if(!i.schema?.$ref)continue;const c=this.#t(i.schema.$ref);c?.componentType==="schemas"&&c.componentName&&s.push(c.componentName)}}}}}catch(t){r.push(`Failed to extract response schemas: ${t instanceof Error?t.message:"Unknown error"}`)}return{schemaNames:[...new Set(s)],errors:r}}#t(e){try{return A(e)}catch{return{componentType:"",componentName:null}}}async#a(e,n,s,r,t,a,o){return e.length===0?[]:await E(e,T,async i=>await this.#l({operationId:n,schemaName:i,descriptionSourceFile:s,descriptionHash:r,parentKey:t,parentVersion:a,parentRevision:o}))}async#l({operationId:e,schemaName:n,descriptionSourceFile:s,descriptionHash:r,parentKey:t,parentVersion:a,parentRevision:o}){const i=`${t}-${y(n)}`;try{return await this.catalogEntitiesService.createEntityRelation({sourceKey:`${t}-${y(e)}`,type:"uses",targetKey:i,sourceFile:s,fileHash:r,sourceVersion:a,targetVersion:a,sourceRevision:o,targetRevision:o}),i}catch(c){throw this.#e.error(`Failed to create relation between operation ${e} and schema ${n}: ${c instanceof Error?c.message:"Unknown error"}`),c}}async#f({path:e,method:n,operation:s,requestBodySchemasKeys:r,responseSchemasKeys:t,description:a,parentKey:o,parentVersion:i,parentRevision:c,rbacTeams:h}){const m=`${s.operationId}`,f=`${o}-${y(m)}`,l=s[g]?R(s[g]):h,u=R(s["x-rbac"]),$={type:"api-operation",key:f,title:m,summary:w(s.summary),tags:s.tags?.filter(p=>v(p)),metadata:{path:e,method:n,payload:r,responses:t},version:i};try{return await this.catalogEntitiesService.createEntity({entity:$,sourceFile:a.realRelativePath,fileHash:a.hash,rbacTeams:u.length>0?u:l,source:"file",revision:c})}catch(p){return this.#e.error(`Failed to create API operation entity for ${m}: ${p instanceof Error?p.message:"Unknown error"}`),null}}async#p({apiOperationKey:e,operationRelations:n,descriptionUniqueKey:s,description:r,parentVersion:t,parentRevision:a}){try{await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:"partOf",targetKey:s,sourceFile:r.realRelativePath,fileHash:r.hash,sourceVersion:t,targetVersion:t,sourceRevision:a,targetRevision:a}),await this.#y(e,r,n,t,a)}catch(o){this.#e.error(`Failed to create API operation relations for ${e}: ${o instanceof Error?o.message:"Unknown error"}`)}}async#y(e,n,s,r,t){s?.length&&await E(s,O,async a=>{try{this.validateEntityRelationFileSchema(a),await this.catalogEntitiesService.createEntityRelation({sourceKey:e,type:a.type,targetKey:a.key,sourceFile:n.realRelativePath,fileHash:n.hash,sourceVersion:r,targetVersion:"",sourceRevision:t,targetRevision:""})}catch(o){this.context.logger.warn(`Error creating entity relation for operation ${e} based on custom property: ${o instanceof Error?o.message:"Unknown error"}`)}})}}export{_ as OpenApiEntitiesExtractor};
@@ -1 +1 @@
1
- import{redocConfigSchema as m,rootRedoclyConfigSchema as t}from"@redocly/config";import p from"is-glob";import{I18N_DIR_NAME as d,L10N_DIR_NAME as u}from"../../../constants/common.js";import{CONFIG_FILE_NAME as f}from"../../../../constants/common.js";import{DEFAULT_SEARCH_ENGINE as A}from"../../../constants/plugins/search.js";import{deepMerge as F}from"../../../../utils/object/deep-merge.js";import{logger as b}from"../../../tools/notifiers/logger.js";import{EntitlementsProvider as C}from"../../../entitlements/entitlements-provider.js";import{readAndValidateConfig as h}from"./utils/read-and-validate-config.js";import{resolveExternalPlugins as v}from"../../../external-plugins/resolve-external-plugins.js";import{getPathForAllLocales as l}from"../../../fs/utils/get-path-for-all-locales.js";import{parseRbacConfig as y}from"../../../utils/rbac.js";import{RbacConfigLocation as E,validateRbacConfig as S}from"../../validate-rbac-config.js";const z=async(e,{fs:r},s)=>{const a=await h(e,r,s,async c=>e===f?g(r.cwd,c?.plugins||[]):void 0);if(a?.access?.rbac){const c=await y(a.access.rbac);a.access.rbac=c,S(c,e===f?E.RootRedoclyYaml:void 0)}(a?.l10n||a?.i18n)&&(a.l10n=L(a),a.i18n=void 0);const i=F(a||{},{markdown:{partialsFolders:(a?.markdown?.partialsFolders||[]).flatMap(c=>l(c,r))}});return R({...i,configPath:e,ignore:I(a?.ignore,r)})};async function g(e,r){const s=await v(e,r),a=s.map(n=>n.config.schema?n.lifecyclePlugin.id:""),i={};for(const n of s){const o=n.lifecyclePlugin?.id;n.config.schema&&o&&t.properties&&(i[o]=n.config.schema)}return{...t,properties:{...i,...t.properties,openapi:m},$id:t.$id+a.join("")}}function R(e){const r=C.instance();return r.canAccessFeature("apiFunctions")||(e.apiFunctions=void 0),r.canAccessFeature("products")||(e.products=void 0),r.canAccessFeature("breadcrumbs")||(e.breadcrumbs={hide:!0}),r.canAccessFeature("seo")||(e.seo={llmstxt:{hide:!0}}),r.canAccessFeature("redirects")||(e.redirects={}),r.canAccessFeature("l10n")||(e.l10n=void 0),r.canAccessFeature("rbac")||e.access&&(e.access.rbac=void 0),r.canAccessFeature("sso")||e.access&&(e.access.sso=void 0),r.canAccessFeature("ssoDirect")||(e.ssoDirect=void 0),r.canAccessFeature("catalogClassic")||(e.catalog=void 0,e.catalogClassic=void 0),r.canAccessFeature("scorecard")||(e.scorecard=void 0,e.scorecardClassic=void 0),r.canAccessFeature("scorecards")||(e.scorecards=void 0),r.canAccessFeature("devOnboarding")||(e.developerOnboarding=void 0),r.canAccessFeature("analytics")||(e.analytics=void 0),r.canAccessFeature("removeAttribution")||(e.removeAttribution=void 0),r.canAccessFeature("mockServer")||(e.mockServer={off:!0}),r.canAccessFeature("advancedSearch")||e.search&&(e.search.engine=A),r.canAccessFeature("banner")||(e.banner=void 0),e}function I(e=[],r){return["static",...e].flatMap(s=>p(s)&&(s.startsWith("*")||s.startsWith(u)||s.startsWith("/"+u)||s.startsWith(d)||s.startsWith("/"+d))?s:l(s,r))}function L(e){return e.i18n&&b.warn("The `i18n` configuration is deprecated. Please use `l10n` instead."),e.l10n||e.i18n||{}}export{z as redoclyConfigLoader};
1
+ import{DEFAULT_SEARCH_ENGINE as m,redocConfigSchema as p,rootRedoclyConfigSchema as t}from"@redocly/config";import A from"is-glob";import{I18N_DIR_NAME as d,L10N_DIR_NAME as u}from"../../../constants/common.js";import{CONFIG_FILE_NAME as f}from"../../../../constants/common.js";import{deepMerge as F}from"../../../../utils/object/deep-merge.js";import{logger as b}from"../../../tools/notifiers/logger.js";import{EntitlementsProvider as C}from"../../../entitlements/entitlements-provider.js";import{readAndValidateConfig as h}from"./utils/read-and-validate-config.js";import{resolveExternalPlugins as E}from"../../../external-plugins/resolve-external-plugins.js";import{getPathForAllLocales as l}from"../../../fs/utils/get-path-for-all-locales.js";import{parseRbacConfig as S}from"../../../utils/rbac.js";import{RbacConfigLocation as v,validateRbacConfig as y}from"../../validate-rbac-config.js";const R=["**/_partials/**"],j=async(e,{fs:r},s)=>{const a=await h(e,r,s,async c=>e===f?L(r.cwd,c?.plugins||[]):void 0);if(a?.access?.rbac){const c=await S(a.access.rbac);a.access.rbac=c,y(c,e===f?v.RootRedoclyYaml:void 0)}(a?.l10n||a?.i18n)&&(a.l10n=I(a),a.i18n=void 0);const i=F(a||{},{markdown:{partialsFolders:(a?.markdown?.partialsFolders||R).flatMap(c=>l(c,r))}});return _({...i,configPath:e,ignore:g(a?.ignore,r)})};async function L(e,r){const s=await E(e,r),a=s.map(n=>n.config.schema?n.lifecyclePlugin.id:""),i={};for(const n of s){const o=n.lifecyclePlugin?.id;n.config.schema&&o&&t.properties&&(i[o]=n.config.schema)}return{...t,properties:{...i,...t.properties,openapi:p},$id:t.$id+a.join("")}}function _(e){const r=C.instance();return r.canAccessFeature("apiFunctions")||(e.apiFunctions=void 0),r.canAccessFeature("products")||(e.products=void 0),r.canAccessFeature("breadcrumbs")||(e.breadcrumbs={hide:!0}),r.canAccessFeature("seo")||(e.seo={llmstxt:{hide:!0}}),r.canAccessFeature("redirects")||(e.redirects={}),r.canAccessFeature("l10n")||(e.l10n=void 0),r.canAccessFeature("rbac")||e.access&&(e.access.rbac=void 0),r.canAccessFeature("sso")||e.access&&(e.access.sso=void 0),r.canAccessFeature("ssoDirect")||(e.ssoDirect=void 0),r.canAccessFeature("catalogClassic")||(e.catalog=void 0,e.catalogClassic=void 0),r.canAccessFeature("scorecard")||(e.scorecard=void 0,e.scorecardClassic=void 0),r.canAccessFeature("scorecards")||(e.scorecards=void 0),r.canAccessFeature("devOnboarding")||(e.developerOnboarding=void 0),r.canAccessFeature("analytics")||(e.analytics=void 0),r.canAccessFeature("removeAttribution")||(e.removeAttribution=void 0),r.canAccessFeature("mockServer")||(e.mockServer={off:!0}),r.canAccessFeature("advancedSearch")||e.search&&(e.search.engine=m),r.canAccessFeature("banner")||(e.banner=void 0),e}function g(e=[],r){return["static",...e].flatMap(s=>A(s)&&(s.startsWith("*")||s.startsWith(u)||s.startsWith("/"+u)||s.startsWith(d)||s.startsWith("/"+d))?s:l(s,r))}function I(e){return e.i18n&&b.warn("The `i18n` configuration is deprecated. Please use `l10n` instead."),e.l10n||e.i18n||{}}export{j as redoclyConfigLoader};