@redocly/realm 0.138.0-next.3 → 0.138.0-next.5

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 (148) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/cli/build/analytics/collect-analytics.js +1 -1
  3. package/dist/cli/build/analytics/collectors/get-sidebars-usage.d.ts +12 -0
  4. package/dist/cli/build/analytics/collectors/get-sidebars-usage.js +1 -0
  5. package/dist/cli/build/index.js +1 -1
  6. package/dist/cli/eject/resolveEjectParams.js +1 -1
  7. package/dist/cli/generate/string-utils.js +1 -1
  8. package/dist/cli/stats/collectors/extension-sampling.js +1 -1
  9. package/dist/cli/translations/collect-config-translations.js +1 -1
  10. package/dist/client/TestProvider.js +1 -1
  11. package/dist/client/app/Link.js +1 -1
  12. package/dist/client/app/Sidebar/useSidebarItems.js +1 -1
  13. package/dist/client/app/hooks/codeHighlight/treeview-transformer.js +1 -1
  14. package/dist/client/app/hooks/markdown/useMarkdownText.js +1 -1
  15. package/dist/client/app/search/index.d.ts +1 -1
  16. package/dist/client/app/search/index.js +1 -1
  17. package/dist/client/app/search/useSearch.d.ts +3 -0
  18. package/dist/client/app/search/useSearch.js +1 -1
  19. package/dist/client/providers/page-data/hooks.d.ts +2 -0
  20. package/dist/client/providers/page-data/hooks.js +1 -1
  21. package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
  22. package/dist/client/runtime/loader.js +1 -1
  23. package/dist/client/templates/api-docs/helpers.js +1 -1
  24. package/dist/client/templates/api-docs/template.js +7 -3
  25. package/dist/client/utils/catalog/parse-filter-query.js +1 -1
  26. package/dist/client/{app/Sidebar/helpers → utils}/filter-out-versioned-items.d.ts +12 -2
  27. package/dist/client/utils/filter-out-versioned-items.js +1 -0
  28. package/dist/client/utils/navigation-tabs.d.ts +14 -0
  29. package/dist/client/utils/navigation-tabs.js +1 -0
  30. package/dist/constants/l10n/langs/ar.js +1 -1
  31. package/dist/constants/l10n/langs/de.js +1 -1
  32. package/dist/constants/l10n/langs/en.js +1 -1
  33. package/dist/constants/l10n/langs/es.js +1 -1
  34. package/dist/constants/l10n/langs/fr.js +1 -1
  35. package/dist/constants/l10n/langs/hi.js +1 -1
  36. package/dist/constants/l10n/langs/it.js +1 -1
  37. package/dist/constants/l10n/langs/ja.js +1 -1
  38. package/dist/constants/l10n/langs/ko.js +1 -1
  39. package/dist/constants/l10n/langs/pl.js +1 -1
  40. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  41. package/dist/constants/l10n/langs/pt.js +1 -1
  42. package/dist/constants/l10n/langs/ru.js +1 -1
  43. package/dist/constants/l10n/langs/uk.js +1 -1
  44. package/dist/constants/l10n/langs/zh.js +1 -1
  45. package/dist/server/config/env-config.d.ts +0 -2
  46. package/dist/server/config/env-schema.d.ts +0 -5
  47. package/dist/server/config/env-schemas/feature-flags.d.ts +0 -4
  48. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  49. package/dist/server/constants/common.d.ts +1 -1
  50. package/dist/server/constants/common.js +1 -1
  51. package/dist/server/esbuild/esbuild-logger.js +3 -3
  52. package/dist/server/plugins/api-docs/index.js +1 -1
  53. package/dist/server/plugins/api-docs/utils/apply-nav-item-to-root.d.ts +9 -0
  54. package/dist/server/plugins/api-docs/utils/apply-nav-item-to-root.js +1 -0
  55. package/dist/server/plugins/api-docs/utils/decorators.js +1 -1
  56. package/dist/server/plugins/catalog-entities/utils/ajv-validator.js +1 -1
  57. package/dist/server/plugins/catalog-entities/utils/extract-parts-from-components-ref.js +1 -1
  58. package/dist/server/plugins/catalog-entities/utils/is-valid-tag-name.js +1 -1
  59. package/dist/server/plugins/catalog-entities/utils/openapi-component-content-extractor.js +1 -1
  60. package/dist/server/plugins/default-theme/extract-team-names.js +1 -1
  61. package/dist/server/plugins/get-reserved-routes.d.ts +4 -2
  62. package/dist/server/plugins/get-reserved-routes.js +1 -1
  63. package/dist/server/plugins/l10n/index.js +1 -1
  64. package/dist/server/plugins/markdown/search/to-markdown.js +1 -1
  65. package/dist/server/plugins/markdown/utils/sanitize-malformed-md-content.js +1 -1
  66. package/dist/server/plugins/mcp/audit/secret-patterns.js +1 -1
  67. package/dist/server/plugins/mcp/auth/assistant-anonymous-token.d.ts +0 -1
  68. package/dist/server/plugins/mcp/auth/assistant-anonymous-token.js +1 -1
  69. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  70. package/dist/server/plugins/mcp/codemode/build-tool-list.d.ts +6 -1
  71. package/dist/server/plugins/mcp/codemode/build-tool-list.js +2 -2
  72. package/dist/server/plugins/mcp/codemode/code-execution-audit.d.ts +3 -2
  73. package/dist/server/plugins/mcp/codemode/code-execution-audit.js +1 -1
  74. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +3 -4
  75. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -1
  76. package/dist/server/plugins/mcp/codemode/prompts.js +1 -1
  77. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +2 -2
  78. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  79. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  80. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -1
  81. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  82. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.js +1 -1
  83. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoint-info.js +1 -1
  84. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-security-schemes.js +1 -1
  85. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.d.ts +3 -4
  86. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
  87. package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.js +1 -1
  88. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +15 -3
  89. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +6 -5
  90. package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.js +1 -1
  91. package/dist/server/plugins/mcp/gateway-mcp/fetch/url-placeholders.js +1 -1
  92. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +2 -2
  93. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  94. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +35 -35
  95. package/dist/server/plugins/mcp/index.js +1 -1
  96. package/dist/server/plugins/mcp/servers/mcp-server.js +3 -3
  97. package/dist/server/plugins/mcp/types.d.ts +5 -11
  98. package/dist/server/plugins/mcp/utils/json-schema-validator.d.ts +2 -2
  99. package/dist/server/plugins/mcp/utils/json-schema-validator.js +1 -1
  100. package/dist/server/plugins/mcp/utils/mcp-client.js +1 -1
  101. package/dist/server/plugins/mcp/utils/public-endpoint.d.ts +9 -0
  102. package/dist/server/plugins/mcp/utils/public-endpoint.js +1 -0
  103. package/dist/server/plugins/mcp/utils/telemetry-attributes.d.ts +2 -1
  104. package/dist/server/plugins/mcp/utils/telemetry-attributes.js +1 -1
  105. package/dist/server/plugins/mcp/utils/xmcp-utils.d.ts +0 -7
  106. package/dist/server/plugins/mcp/utils/xmcp-utils.js +1 -1
  107. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  108. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +5 -7
  109. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  110. package/dist/server/plugins/nav-utils.js +1 -1
  111. package/dist/server/plugins/scorecard-classic/index.js +1 -1
  112. package/dist/server/plugins/scorecard-classic/template/useData.js +1 -1
  113. package/dist/server/plugins/search/llmstxt/index.js +1 -1
  114. package/dist/server/plugins/sidebars/index.js +7 -3
  115. package/dist/server/plugins/sidebars/tabs.d.ts +19 -0
  116. package/dist/server/plugins/sidebars/tabs.js +1 -0
  117. package/dist/server/plugins/sso/index.js +1 -1
  118. package/dist/server/store.js +1 -1
  119. package/dist/server/tools/notifiers/helpers/privacy/mask-subject.js +1 -1
  120. package/dist/server/tools/notifiers/helpers/privacy/remove-pii.js +1 -1
  121. package/dist/server/utils/catalog-classic/get-catalog-shared-data-id.d.ts +3 -0
  122. package/dist/server/utils/catalog-classic/get-catalog-shared-data-id.js +1 -0
  123. package/dist/server/utils/envs/interpolate-env-variables.js +1 -1
  124. package/dist/server/utils/rbac.js +1 -1
  125. package/dist/server/utils/report-all-errors.js +1 -1
  126. package/dist/server/utils/sandbox-context.js +1 -1
  127. package/dist/server/utils/static-data.js +1 -1
  128. package/dist/server/utils/write-problems-report.d.ts +3 -0
  129. package/dist/server/utils/write-problems-report.js +1 -0
  130. package/dist/server/web-server/auth.d.ts +16 -2
  131. package/dist/server/web-server/auth.js +4 -4
  132. package/dist/server/web-server/jwt/jwt.js +1 -1
  133. package/dist/server/web-server/jwt/token-types.d.ts +11 -0
  134. package/dist/server/web-server/jwt/token-types.js +1 -0
  135. package/dist/server/web-server/routes/auth.js +1 -1
  136. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  137. package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
  138. package/dist/server/web-server/routes/semantic-search.d.ts +1 -1
  139. package/dist/server/web-server/routes/semantic-search.js +1 -1
  140. package/dist/server/web-server/routes/static-content.js +1 -1
  141. package/dist/utils/path/parse-path-versions.js +1 -1
  142. package/dist/utils/string/to-kebab-case.js +1 -1
  143. package/package.json +8 -8
  144. package/dist/client/app/Sidebar/helpers/filter-out-versioned-items.js +0 -1
  145. package/dist/server/plugins/mcp/auth/token-audience-telemetry.d.ts +0 -7
  146. package/dist/server/plugins/mcp/auth/token-audience-telemetry.js +0 -1
  147. package/dist/server/plugins/mcp/auth/token-audience.d.ts +0 -6
  148. package/dist/server/plugins/mcp/auth/token-audience.js +0 -1
@@ -1,5 +1,5 @@
1
- import{McpServer as j}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as D,MCP_TOOL_WORKER_KEY as F}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as K}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as L,stripAuthRequiredMeta as y,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{buildCredentialsToolHint as H,buildSchemeChoiceHint as P,buildUpstreamCredentialFallback as T,buildUpstreamCredentialInputRequired as $,dedupeElicitation as B,isCredentialElicitationDeclined as x,isStatelessRequest as N,schemeLabelOf as v,supportsUrlElicitation as G}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as q,resolveUpstreamApiAuth as V,schemeChoicesOf as W}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as Y,resolveSecretSubject as J}from"../gateway-mcp/subject.js";const Q=6e4;function pe(e,t){return new j({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function me(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,c=N(s.mcpReq),a=i?J(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const d=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await K.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let u;const l=async()=>{u=await d();const m={toolName:r,args:n,context:{...e,upstreamSecrets:u},extra:ne(s)};return await D.exec(F,[m],{timeout:Q})};let p=await l();const f=L(p);if(f.length>0&&i&&!o)return y(R(p,[{type:"text",text:Y}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${c?"2026-07-28":"2025"} clientElicitation=${X(t)}`);const m=await t.getKv(),h=await Z(e,f),k=f.map(O=>z(O,h)),E=ee(u),g=c?await te(e,s,k,o,m,E,h,t):await re(e,k,o,m,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":p=await l();break;case"prependText":p=R(p,[{type:"text",text:g.text},...p.content]);break;case"none":break}}return y(p)}}function R(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function X(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function Z(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await V(e,n));return r}function z(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??q};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function ee(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function M(e,t){return e.status===401&&!t.has(b(e))}function C(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?v(r.schemes,n):void 0}function A(e,t){const r=t.get(e.api);return!r||!e.schemes?.length?[]:W(r,e.schemes)}function I(e,t){return A(e,t).length>1}function w(e,t){return e.map(r=>H(r,C(r,t))).join(`
1
+ import{McpServer as L}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as j,MCP_TOOL_WORKER_KEY as D}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as F}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as H,stripAuthRequiredMeta as q,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{acceptedCredentialsLink as K,buildCredentialsAcceptedHint as N,buildCredentialsToolHint as P,buildSchemeChoiceHint as $,buildUpstreamCredentialFallback as y,buildUpstreamCredentialInputRequired as B,credentialElicitationAnswer as v,dedupeElicitation as x,isStatelessRequest as G,schemeLabelOf as V,supportsUrlElicitation as W}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as T,resolveUpstreamApiAuth as Y,schemeChoicesOf as J}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as Q,resolveSecretSubject as X}from"../gateway-mcp/subject.js";const Z=6e4;function fe(e,t){return new L({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function he(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,u=G(s.mcpReq),o=i?X(e.user,n.sessionHandle):{kind:"anonymous"},l=o.kind==="resolved"?o.subject:void 0;if(o.kind==="invalid")return{content:[{type:"text",text:o.message}],isError:!0};const d=async()=>{if(!(!i||!l||!t?.getKv))try{const p=await t.getKv();return await F.getSecretsForSubject(p,l)}catch(p){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(p)}`);return}};let c;const f=async()=>{c=await d();const p={toolName:r,args:n,context:{...e,upstreamSecrets:c},extra:se(s)};return await j.exec(D,[p],{timeout:Z})};let a=await f();const m=H(a);if(m.length>0&&i&&!l)return q(I(a,[{type:"text",text:Q}]));if(m.length>0&&i&&l&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${u?"2026-07-28":"2025"} clientElicitation=${z(t)}`);const p=await t.getKv(),h=await ee(e,m),k=m.map(O=>te(O,h)),E=re(c),g=u?await ne(e,s,k,l,p,E,h,t):await ie(e,k,l,p,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":a=await f();break;case"prependText":a=I(a,[{type:"text",text:g.text},...a.content]);break;case"none":break}}return q(a)}}function I(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function z(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function ee(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await Y(e,n));return r}function te(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??T};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function re(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function R(e,t){return e.status===401&&!t.has(b(e))}function A(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?V(r.schemes,n):void 0}function M(e,t){const r=t.get(e.api);return!r||!e.schemes?.length?[]:J(r,e.schemes)}function C(e,t){return M(e,t).length>1}function w(e,t){return e.map(r=>P(r,A(r,t))).join(`
2
2
 
3
- `)}function U(e,t,r){const n=e.map(s=>P(s,A(s,r)));return t.length>0&&n.push(w(t,r)),n.join(`
3
+ `)}function U(e,t,r){const n=e.map(s=>$(s,M(s,r)));return t.length>0&&n.push(w(t,r)),n.join(`
4
4
 
5
- `)}function _(e,t,r,n,s){const[i,...c]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??q,d=C(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...d?{schemeLabel:d}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:c.map(u=>u.name)}}}async function te(e,t,r,n,s,i,c,a){if(x(t.mcpReq.inputResponses))return{kind:"none"};const o=r.filter(l=>M(l,i));if(o.length===0)return{kind:"prependText",text:w(r,c)};const d=o.filter(l=>I(l,c));if(d.length>0){const l=r.filter(p=>!d.includes(p));return{kind:"prependText",text:U(d,l,c)}}const u=_(e,o,n,s,c);return G(a?.getClientCapabilities())?{kind:"inputRequired",result:await $(u)}:{kind:"prependText",text:await T(u)}}async function re(e,t,r,n,s,i){const c=t.filter(u=>M(u,s));if(c.length===0)return{kind:"prependText",text:w(t,i)};const a=c.filter(u=>I(u,i));if(a.length>0){const u=t.filter(l=>!a.includes(l));return{kind:"prependText",text:U(a,u,i)}}const o=_(e,c,r,n,i);return{kind:"prependText",text:await B(`${r}:${b(c[0])}`,()=>T(o))}}function ne(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function fe(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,fs:void 0}}export{pe as createMcpServer,me as createToolDispatch,fe as extractSerializableContext};
5
+ `)}function _(e,t,r,n,s){const[i,...u]=t,o=s.get(i.api),l=i.scheme??o?.defaultScheme??T,d=A(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:l,...d?{schemeLabel:d}:{}},auth:o?.schemes[l]??{kind:"raw"},...o?{apiAuth:o}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:u.map(c=>c.name)}}}async function ne(e,t,r,n,s,i,u,o){const l=v(t.mcpReq.inputResponses);if(l==="declined")return{kind:"none"};const d=r.filter(a=>R(a,i));if(d.length===0)return{kind:"prependText",text:w(r,u)};if(l==="accepted"){const a=await K(t.mcpReq.requestState(),{kv:s,subject:n,baseUrl:e.baseUrl??"",apis:d.map(p=>p.api)}),m=a?.apiName??d[0].name;return{kind:"prependText",text:N(m,a?.url)}}const c=d.filter(a=>C(a,u));if(c.length>0){const a=r.filter(m=>!c.includes(m));return{kind:"prependText",text:U(c,a,u)}}const f=_(e,d,n,s,u);return W(o?.getClientCapabilities())?{kind:"inputRequired",result:await B(f)}:{kind:"prependText",text:await y(f)}}async function ie(e,t,r,n,s,i){const u=t.filter(c=>R(c,s));if(u.length===0)return{kind:"prependText",text:w(t,i)};const o=u.filter(c=>C(c,i));if(o.length>0){const c=t.filter(f=>!o.includes(f));return{kind:"prependText",text:U(o,c,i)}}const l=_(e,u,r,n,i);return{kind:"prependText",text:await x(`${r}:${b(u[0])}`,()=>y(l))}}function se(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function ge(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,requestId:e.requestId,messageId:e.messageId,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,fs:void 0}}export{fe as createMcpServer,he as createToolDispatch,ge as extractSerializableContext};
@@ -63,17 +63,6 @@ export type McpEndpoint = OpenAPIOperation & {
63
63
  'x-mcp'?: XMcpConfig;
64
64
  };
65
65
  export type McpMode = 'tools' | 'code';
66
- export type McpUserInfo = {
67
- email?: string;
68
- name?: string;
69
- sub?: string;
70
- aud?: string | string[];
71
- client_id?: string;
72
- scope?: string;
73
- iat?: number;
74
- exp?: number;
75
- [key: string]: unknown;
76
- };
77
66
  export type SemanticSearchResult = {
78
67
  title: string;
79
68
  url: string;
@@ -85,6 +74,8 @@ export type McpToolWorkerResponse = CallToolResult & {
85
74
  };
86
75
  export type ToolArgs = Record<string, unknown>;
87
76
  export type McpToolCallback = ToolCallback<StandardSchemaWithJSON<ToolArgs, ToolArgs>>;
77
+ /** The caller and request fields every MCP telemetry event and audit record carries. */
78
+ export type McpCallAttribution = Pick<McpToolContext, 'client' | 'clientVersion' | 'requestId' | 'messageId'>;
88
79
  export type McpToolExtra = {
89
80
  sessionId?: string;
90
81
  authInfo?: AuthInfo;
@@ -104,6 +95,8 @@ export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | k
104
95
  clientIp?: string;
105
96
  client?: string;
106
97
  clientVersion?: string;
98
+ requestId?: string;
99
+ messageId?: string;
107
100
  upstreamSecrets?: UpstreamSecrets;
108
101
  searchIgnoredRoutes?: string[];
109
102
  internalBaseUrl?: string;
@@ -124,6 +117,7 @@ export type McpToolExecutionParams = {
124
117
  };
125
118
  export type CustomMcpToolsState = {
126
119
  registeredToolNames: string[];
120
+ warnedNoOutputSchemaTools: Set<string>;
127
121
  };
128
122
  export type ToolDefinitionValidationResult = {
129
123
  ok: true;
@@ -1,9 +1,9 @@
1
- import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server/validators/ajv';
1
+ import type { jsonSchemaValidator } from '@modelcontextprotocol/server';
2
2
  /**
3
3
  * Validates tool arguments with the same engine and options the forked SDK
4
4
  * (@redocly/mcp-typescript-sdk) used internally, so migrating to the upstream
5
5
  * v2 SDK does not change which arguments are accepted. The SDK default would
6
6
  * be a lenient draft-2020-12 engine instead.
7
7
  */
8
- export declare const mcpJsonSchemaValidator: AjvJsonSchemaValidator;
8
+ export declare const mcpJsonSchemaValidator: jsonSchemaValidator;
9
9
  //# sourceMappingURL=json-schema-validator.d.ts.map
@@ -1 +1 @@
1
- import{AjvJsonSchemaValidator as o}from"@modelcontextprotocol/server/validators/ajv";import r from"@redocly/ajv";const t=new o(new r({allErrors:!0}));export{t as mcpJsonSchemaValidator};
1
+ import{AjvJsonSchemaValidator as a}from"@modelcontextprotocol/server/validators/ajv";import l from"@redocly/ajv";const c=new a(new l({allErrors:!0})),j={getValidator(r){const o=c.getValidator(r),t=Object.keys(r.properties??{});return t.length===0||r.additionalProperties!==!1?o:n=>{const e=o(n),i=Object.keys(n??{}).filter(s=>!t.includes(s));return e.valid||i.length===0?e:{...e,errorMessage:`${e.errorMessage}. Unknown properties: ${i.join(", ")}. Accepted properties: ${t.join(", ")}.`}}}};export{j as mcpJsonSchemaValidator};
@@ -1 +1 @@
1
- const o="(none)",r="(unparsed)",N=40,i=/^[A-Za-z0-9._\- ]+/,c=/\s+([0-9]\S*).*$/,l=/^[/\s]+v?([0-9][^\s;,)]*)/;function a(e){return E(e.headers.get("user-agent"))}function E(e){if(e==null)return{client:o};const n=i.exec(e)?.[0]??"",t=n.replace(c,"").trim();if(!t)return{client:r};const s=c.exec(n)?.[1]??l.exec(e.slice(n.length))?.[1];return{client:t.replace(/\s+/g,"-").toLowerCase().slice(0,40),clientVersion:s?.slice(0,40)}}export{E as parseUserAgent,a as resolveMcpClient};
1
+ const o="(none)",r="(unparsed)",N=40,i=/^[A-Za-z0-9._\- ]+/,c=/(?<!\s)\s+([0-9]\S*)(?:[^\S\n].*)?$/,l=/^[/\s]+v?([0-9][^\s;,)]*)/;function a(e){return E(e.headers.get("user-agent"))}function E(e){if(e==null)return{client:o};const n=i.exec(e)?.[0]??"",t=n.replace(c,"").trim();if(!t)return{client:r};const s=c.exec(n)?.[1]??l.exec(e.slice(n.length))?.[1];return{client:t.replace(/\s+/g,"-").toLowerCase().slice(0,40),clientVersion:s?.slice(0,40)}}export{E as parseUserAgent,a as resolveMcpClient};
@@ -0,0 +1,9 @@
1
+ import type { RedoclyConfig } from '@redocly/config';
2
+ export type PublicMcpEndpointStatus = 'served' | 'disabled' | 'no-protected-content' | 'anonymous-denied';
3
+ /**
4
+ * Whether `/mcp-public` is served for this config, and why not when it is not.
5
+ * Ignores the `mcp` entitlement, so it is safe in request handlers; build-time callers
6
+ * that need the full answer must also check the entitlement.
7
+ */
8
+ export declare function getPublicMcpEndpointStatus(config: Pick<RedoclyConfig, 'mcp' | 'access'>): PublicMcpEndpointStatus;
9
+ //# sourceMappingURL=public-endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ import{canAnonymousAccessMcpFeature as c}from"../../../utils/rbac/can-anonymous-access-mcp-feature.js";import{shouldHandleMcpAuth as i}from"../../../utils/rbac/should-handle-mcp-auth.js";function d(t){const{mcp:n,access:e}=t;if(n?.hide||n?.docs?.hide||!n?.docs?.publicEndpoint)return"disabled";const o=!!e?.requiresLogin,r=e?.rbac||{};return i(o,r)?c(r,o)?"served":"anonymous-denied":"no-protected-content"}export{d as getPublicMcpEndpointStatus};
@@ -1,8 +1,9 @@
1
- import type { McpServerType } from '../types.js';
1
+ import type { McpCallAttribution, McpServerType, McpToolContext } from '../types.js';
2
2
  /** CloudEvent resource attributes shared by every `mcpServer` telemetry event. */
3
3
  export declare function serverAttributes(serverType: McpServerType): {
4
4
  id: "docs";
5
5
  object: 'mcpServer';
6
6
  uri: string;
7
7
  };
8
+ export declare function callAttribution(context: McpToolContext | undefined): McpCallAttribution;
8
9
  //# sourceMappingURL=telemetry-attributes.d.ts.map
@@ -1 +1 @@
1
- function e(r){return{id:r,object:"mcpServer",uri:`urn:redocly:realm:mcp:server:${r}`}}export{e as serverAttributes};
1
+ function r(e){return{id:e,object:"mcpServer",uri:`urn:redocly:realm:mcp:server:${e}`}}function i(e){return{client:e?.client,clientVersion:e?.clientVersion,requestId:e?.requestId,messageId:e?.messageId}}export{i as callAttribution,r as serverAttributes};
@@ -4,13 +4,6 @@ import type { XMcpConfig, XMcpSection } from '../types.js';
4
4
  export declare function isEndpointHidden(endpoint: {
5
5
  'x-mcp'?: XMcpConfig;
6
6
  } | undefined, section: XMcpSection): boolean;
7
- /**
8
- * Returns false when the endpoint is hidden for `section`; otherwise strips x-mcp from the
9
- * output and returns true.
10
- */
11
- export declare function checkEndpointAndDeleteXMcp(endpoint: {
12
- 'x-mcp'?: XMcpConfig;
13
- }, section: XMcpSection): boolean;
14
7
  /** Whether the definition's info-level x-mcp hides it for `section` (defaults to `docs`). */
15
8
  export declare function isDefinitionHidden(info?: OpenAPIDefinition['info'], section?: XMcpSection): boolean;
16
9
  /** Whether the API explicitly opts into the gateway via `x-mcp.gateway`. */
@@ -1 +1 @@
1
- function n(e,t){return!!e?.["x-mcp"]?.[t]?.hide}function i(e,t){return n(e,t)?!1:(e&&delete e["x-mcp"],!0)}function o(e,t){if(!e)return!1;const r=e["x-mcp"];return!r||typeof r!="object"?!1:t?r[t]?.hide===!0:r.docs?.hide===!0}function c(e){if(!e)return!1;const t=e["x-mcp"];return!!(t&&typeof t=="object"&&t.gateway)}export{i as checkEndpointAndDeleteXMcp,c as hasGatewayConfig,o as isDefinitionHidden,n as isEndpointHidden};
1
+ function r(t,e){return!!t?.["x-mcp"]?.[e]?.hide}function o(t,e){if(!t)return!1;const n=t["x-mcp"];return!n||typeof n!="object"?!1:e?n[e]?.hide===!0:n.docs?.hide===!0}function i(t){if(!t)return!1;const e=t["x-mcp"];return!!(e&&typeof e=="object"&&e.gateway)}export{i as hasGatewayConfig,o as isDefinitionHidden,r as isEndpointHidden};
@@ -1 +1 @@
1
- import{telemetry as h}from"../../../telemetry/index.js";import{McpServerType as c}from"../constants.js";import{EXECUTE_TOOL_NAME as w}from"../codemode/constants.js";import{isPlainObject as p}from"../../../../utils/guards/is-plain-object.js";import{logMcpToolCallAudit as g,reportMcpToolCalled as _,reportMcpToolError as u}from"./mcp-tool-telemetry.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{attachToolFileSystem as E}from"./tool-file-system.js";import{importMcpToolHandlers as b}from"./import-mcp-tool-handlers.js";function A(e){return e.content.map(t=>t.type==="text"?t.text:"")}async function F(e){h.initialize();const{toolName:t,args:o,extra:s}=e,r=E(e.context),n=r?.mcpMode??"tools",a={client:r?.client,clientVersion:r?.clientVersion},d=performance.now();try{const i=await M(t);if(!i)throw new Error(`MCP tool "${t}" is not registered or its module does not export a handler for "${t}". Expected \`export default { '${t}': handler }\` or a single tool definition with \`description\` and \`execute\` as the default export.`);const C=typeof i=="function"?i:i.execute,l=k(t,await C(o,r,s),n),m=Math.round(performance.now()-d),{errorClass:y}=l;delete l.errorClass;const f=l.isError?y??(t===w?"sandbox_error":"tool_error"):void 0,v=t===w&&y==="tool_error",x=A(l),T=x.join("");return g({tool:t,mode:n,serverType:c.Docs,args:o,result:T,errorClass:f,...a}),f?v||u({tool:t,message:x.join(" "),mode:n,serverType:c.Docs,durationMs:m,errorClass:f,...a}):_({tool:t,mode:n,serverType:c.Docs,durationMs:m,outputLength:T.length,...a}),l}catch(i){throw g({tool:t,mode:n,serverType:c.Docs,args:o,errorClass:"server_error",...a}),u({tool:t,message:i instanceof Error?i.message:String(i),mode:n,serverType:c.Docs,durationMs:Math.round(performance.now()-d),stack:i instanceof Error&&i.stack||"",errorClass:"server_error",...a}),i}}function O(e){return"execute"in e&&typeof e.execute=="function"&&"description"in e&&typeof e.description=="string"}async function M(e){const t=(await b())[e];if(!t)return;const{default:o}=await t();return P(o,e)}function P(e,t){return O(e)?e:e[t]}function k(e,t,o){if(j(t))return t;if(typeof t=="string")return{content:[{type:"text",text:t}]};let s;try{s=JSON.stringify(t)}catch(n){throw new Error(`MCP tool "${e}" returned a value that cannot be serialized to JSON: `+(n instanceof Error?n.message:String(n)))}if(s===void 0)throw new Error(`MCP tool "${e}" returned an invalid result.`);const r=o==="code"?JSON.parse(s):void 0;return p(r)?{content:[{type:"text",text:s}],structuredContent:r}:{content:[{type:"text",text:s}]}}const L=new Set(["text","image","audio","resource","resource_link"]);function j(e){if(!p(e))return!1;const{content:t}=e;return Array.isArray(t)&&t.every(o=>p(o)&&L.has(o.type))}async function N(e){h.initialize();const{toolName:t}=e;if(S(t,e.context.metadata))return!1;const o=E(e.context),s=performance.now();try{const r=await M(t);return r?typeof r=="object"&&typeof r.isAvailable=="function"?await r.isAvailable(o):!0:!1}catch(r){throw u({tool:t,message:"Failed to check if MCP tool is available: "+(r instanceof Error?r.message:String(r)),mode:o?.mcpMode??"tools",serverType:c.Docs,durationMs:Math.round(performance.now()-s),stack:r instanceof Error&&r.stack||"",errorClass:"server_error",client:o?.client,clientVersion:o?.clientVersion}),r}}async function U(e){const{toolNames:t,context:o}=e,s=await Promise.all(t.map(r=>N({toolName:r,context:o}).catch(()=>!1)));return Object.fromEntries(t.map((r,n)=>[r,s[n]]))}export{F as executeMcpTool,N as isMcpToolAvailable,U as mcpToolAvailability,P as resolveToolHandler};
1
+ import{telemetry as h}from"../../../telemetry/index.js";import{McpServerType as c}from"../constants.js";import{EXECUTE_TOOL_NAME as w}from"../codemode/constants.js";import{isPlainObject as p}from"../../../../utils/guards/is-plain-object.js";import{logMcpToolCallAudit as g,reportMcpToolCalled as b,reportMcpToolError as u}from"./mcp-tool-telemetry.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{attachToolFileSystem as E}from"./tool-file-system.js";import{callAttribution as M}from"../utils/telemetry-attributes.js";import{importMcpToolHandlers as A}from"./import-mcp-tool-handlers.js";function O(e){return e.content.map(t=>t.type==="text"?t.text:"")}async function X(e){h.initialize();const{toolName:t,args:o,extra:s}=e,r=E(e.context),n=r?.mcpMode??"tools",a=M(r),d=performance.now();try{const i=await C(t);if(!i)throw new Error(`MCP tool "${t}" is not registered or its module does not export a handler for "${t}". Expected \`export default { '${t}': handler }\` or a single tool definition with \`description\` and \`execute\` as the default export.`);const v=typeof i=="function"?i:i.execute,l=L(t,await v(o,r,s),n),m=Math.round(performance.now()-d),{errorClass:y}=l;delete l.errorClass;const f=l.isError?y??(t===w?"sandbox_error":"tool_error"):void 0,_=t===w&&y==="tool_error",x=O(l),T=x.join("");return g({tool:t,mode:n,serverType:c.Docs,args:o,result:T,errorClass:f,...a}),f?_||u({tool:t,message:x.join(" "),mode:n,serverType:c.Docs,durationMs:m,errorClass:f,...a}):b({tool:t,mode:n,serverType:c.Docs,durationMs:m,outputLength:T.length,...a}),l}catch(i){throw g({tool:t,mode:n,serverType:c.Docs,args:o,errorClass:"server_error",...a}),u({tool:t,message:i instanceof Error?i.message:String(i),mode:n,serverType:c.Docs,durationMs:Math.round(performance.now()-d),stack:i instanceof Error&&i.stack||"",errorClass:"server_error",...a}),i}}function P(e){return"execute"in e&&typeof e.execute=="function"&&"description"in e&&typeof e.description=="string"}async function C(e){const t=(await A())[e];if(!t)return;const{default:o}=await t();return k(o,e)}function k(e,t){return P(e)?e:e[t]}function L(e,t,o){if(N(t))return t;if(typeof t=="string")return{content:[{type:"text",text:t}]};let s;try{s=JSON.stringify(t)}catch(n){throw new Error(`MCP tool "${e}" returned a value that cannot be serialized to JSON: `+(n instanceof Error?n.message:String(n)))}if(s===void 0)throw new Error(`MCP tool "${e}" returned an invalid result.`);const r=o==="code"?JSON.parse(s):void 0;return p(r)?{content:[{type:"text",text:s}],structuredContent:r}:{content:[{type:"text",text:s}]}}const j=new Set(["text","image","audio","resource","resource_link"]);function N(e){if(!p(e))return!1;const{content:t}=e;return Array.isArray(t)&&t.every(o=>p(o)&&j.has(o.type))}async function $(e){h.initialize();const{toolName:t}=e;if(S(t,e.context.metadata))return!1;const o=E(e.context),s=performance.now();try{const r=await C(t);return r?typeof r=="object"&&typeof r.isAvailable=="function"?await r.isAvailable(o):!0:!1}catch(r){throw u({tool:t,message:"Failed to check if MCP tool is available: "+(r instanceof Error?r.message:String(r)),mode:o?.mcpMode??"tools",serverType:c.Docs,durationMs:Math.round(performance.now()-s),stack:r instanceof Error&&r.stack||"",errorClass:"server_error",...M(o)}),r}}async function Y(e){const{toolNames:t,context:o}=e,s=await Promise.all(t.map(r=>$({toolName:r,context:o}).catch(()=>!1)));return Object.fromEntries(t.map((r,n)=>[r,s[n]]))}export{X as executeMcpTool,$ as isMcpToolAvailable,Y as mcpToolAvailability,k as resolveToolHandler};
@@ -1,13 +1,11 @@
1
- import type { McpErrorClass, McpMode, McpServerType } from '../types.js';
2
- type McpToolEvent = {
1
+ import type { McpCallAttribution, McpErrorClass, McpMode, McpServerType } from '../types.js';
2
+ type McpToolEvent = McpCallAttribution & {
3
3
  tool: string;
4
4
  mode: McpMode;
5
5
  serverType: McpServerType;
6
6
  durationMs: number;
7
- client?: string;
8
- clientVersion?: string;
9
7
  };
10
- export declare function reportMcpToolCalled({ tool, mode, serverType, durationMs, outputLength, client, clientVersion, }: McpToolEvent & {
8
+ export declare function reportMcpToolCalled({ tool, mode, serverType, durationMs, outputLength, client, clientVersion, requestId, messageId, }: McpToolEvent & {
11
9
  outputLength: number;
12
10
  }): void;
13
11
  /**
@@ -16,12 +14,12 @@ export declare function reportMcpToolCalled({ tool, mode, serverType, durationMs
16
14
  * identifies the invocation. The result body itself is never recorded — a tool can return
17
15
  * credentials no pattern will recognise — so only its digest lands here.
18
16
  */
19
- export declare function logMcpToolCallAudit({ tool, mode, serverType, args, result, errorClass, client, clientVersion, }: Omit<McpToolEvent, 'durationMs'> & {
17
+ export declare function logMcpToolCallAudit({ tool, mode, serverType, args, result, errorClass, client, clientVersion, requestId, messageId, }: Omit<McpToolEvent, 'durationMs'> & {
20
18
  args: unknown;
21
19
  result?: string;
22
20
  errorClass?: McpErrorClass;
23
21
  }): void;
24
- export declare function reportMcpToolError({ tool, mode, serverType, durationMs, message, stack, errorClass, client, clientVersion, }: McpToolEvent & {
22
+ export declare function reportMcpToolError({ tool, mode, serverType, durationMs, message, stack, errorClass, client, clientVersion, requestId, messageId, }: McpToolEvent & {
25
23
  message: string;
26
24
  stack?: string;
27
25
  errorClass: McpErrorClass;
@@ -1 +1 @@
1
- import{telemetry as c}from"../../../telemetry/index.js";import{serverAttributes as d}from"../utils/telemetry-attributes.js";import{EXECUTE_TOOL_NAME as p}from"../codemode/constants.js";import{auditInput as _,auditOutputDigest as f,auditSha256 as g,logAuditRecord as m}from"../audit/audit-log.js";function A({tool:r,mode:t,serverType:o,durationMs:i,outputLength:e,client:s,clientVersion:n}){c.sendMcpToolCalledMessage([{...d(o),tool:r,mode:t,output_length:e,duration_ms:i,client:s,client_version:n}])}function C({tool:r,mode:t,serverType:o,args:i,result:e,errorClass:s,client:n,clientVersion:a}){if(r===p)return;const l=M(i),u=e===void 0?void 0:f(e);m("Record MCP tool call",{tool:r,mode:t,server_type:o,error_class:s,client:n,client_version:a,args_sha256:g(l),args:_(l),result_sha256:u?.sha256,result_bytes:u?.bytes})}function M(r){try{return JSON.stringify(r)??String(r)}catch{return"\xAB[unserializable]\xBB"}}function b({tool:r,mode:t,serverType:o,durationMs:i,message:e,stack:s="",errorClass:n,client:a,clientVersion:l}){c.sendMcpErrorMessage([{...d(o),tool:r,message:e,stack:s,error_class:n,mode:t,duration_ms:i,client:a,client_version:l}])}export{C as logMcpToolCallAudit,A as reportMcpToolCalled,b as reportMcpToolError};
1
+ import{telemetry as p}from"../../../telemetry/index.js";import{serverAttributes as _}from"../utils/telemetry-attributes.js";import{EXECUTE_TOOL_NAME as g}from"../codemode/constants.js";import{auditInput as m,auditOutputDigest as f,auditSha256 as M,logAuditRecord as h}from"../audit/audit-log.js";function b({tool:e,mode:t,serverType:s,durationMs:o,outputLength:r,client:i,clientVersion:n,requestId:a,messageId:l}){p.sendMcpToolCalledMessage([{..._(s),tool:e,mode:t,output_length:r,duration_ms:o,client:i,client_version:n,message_id:l}],{requestId:a})}function v({tool:e,mode:t,serverType:s,args:o,result:r,errorClass:i,client:n,clientVersion:a,requestId:l,messageId:d}){if(e===g)return;const u=y(o),c=r===void 0?void 0:f(r);h("Record MCP tool call",{tool:e,mode:t,server_type:s,error_class:i,client:n,client_version:a,request_id:l,message_id:d,args_sha256:M(u),args:m(u),result_sha256:c?.sha256,result_bytes:c?.bytes})}function y(e){try{return JSON.stringify(e)??String(e)}catch{return"\xAB[unserializable]\xBB"}}function O({tool:e,mode:t,serverType:s,durationMs:o,message:r,stack:i="",errorClass:n,client:a,clientVersion:l,requestId:d,messageId:u}){p.sendMcpErrorMessage([{..._(s),tool:e,message:r,stack:i,error_class:n,mode:t,duration_ms:o,client:a,client_version:l,message_id:u}],{requestId:d})}export{v as logMcpToolCallAudit,b as reportMcpToolCalled,O as reportMcpToolError};
@@ -1 +1 @@
1
- import*as v from"path";import{REDOCLY_ROUTE_RBAC as b,REDOCLY_TEAMS_RBAC as p}from"@redocly/config";import{VERSION_SEPARATOR as M}from"../constants/common.js";import{DEFAULT_LOCALE_PLACEHOLDER as _}from"../../constants/common.js";import{removeTrailingSlash as j}from"../../utils/url/remove-trailing-slash.js";import{isPrimitive as W}from"../../utils/guards/is-primitive.js";import{slash as w}from"../../utils/path/slash.js";import{isAbsoluteUrl as z}from"../../utils/url/is-absolute-url.js";import{normalizeRouteSlug as U}from"../../utils/path/normalize-route-slug.js";import{parsePathVersions as R}from"../../utils/path/parse-path-versions.js";import{logger as A}from"../tools/notifiers/logger.js";import{reporter as S}from"../tools/notifiers/reporter.js";import{shaDirPathShort as C}from"../utils/crypto/sha-dir-path-short.js";import{copyStaticFile as H,FileNotFoundError as E}from"../utils/fs.js";import{isIconPath as J,resolveAssetPath as Y}from"../utils/index.js";import{resolveSrcSet as G}from"../utils/resolve-src-set.js";import{isL10nPath as B}from"../fs/utils/is-l10n-path.js";import{getLocaleFromRelativePath as q}from"../fs/utils/get-locale-from-relative-path.js";async function D(e,s,n,t,a){if(!e)return;const f={...a,ignoreCustomSidebar:!0};if(W(e)){if(typeof e=="string"){const r=F(n.contentDir,s,a,e,t.fs);if(t.fs.exists(r)){if(n.getRouteByFsPath(r))return K({page:e},s,n,t,f);{const g=t.fs.getFileInfo(r);return g?H(n.contentDir,g.realRelativePath,n.outdir):void 0}}}return e}return Array.isArray(e)?I(N(e),s,n,t,f):Object.fromEntries(await Promise.all(Object.entries(e).map(async([r,l])=>[r,await D(l,s,n,t,a)])))}function N(e){return e.map(s=>({...s,items:s.items?N(s.items):void 0}))}async function I(e,s,n,t,a){if(Array.isArray(e))return(await Promise.all(e.map(f=>K(f,s,n,t,a)))).flatMap(f=>f)}async function P(e,s,n,t){let a,f;if(typeof e.icon=="object"){if("srcSet"in e.icon)try{a=await G(e.icon.srcSet,n.fs,{fromFileRelativePath:t.navFile,contentDir:s.contentDir,outdir:s.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`):await S.panicOnBuild(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`)}}else if(typeof e.icon=="string")if(z(e.icon)||J(e.icon))try{f=await Y(e.icon,n.fs,{fromFileRelativePath:t.navFile,contentDir:s.contentDir,outdir:s.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon" from ${t.navFile}: file ${f} does not exist`):await S.panicOnBuild(`Cannot resolve "item.icon" from ${t.navFile}: ${d.message}`)}else f=e.icon;return{icon:f,srcSet:a}}function Q(e){return s=>{if(s.type==="link"||s.type==="group"){const n=s.metadata;return n?Object.entries(e).every(([t,a])=>Array.isArray(a)?a.some(f=>n[t]===f):n[t]===a):!1}return!0}}async function K(e,s,n,t,a){if(e?.directory&&e.items?.length)return{type:"error",label:`Can't have both "directory" and "items" in the nav item: ${JSON.stringify(e)}`};e?.directory&&e?.group&&(e={...e,directory:void 0,items:[{directory:e.directory}]});const f=e?.directory?F(n.contentDir,s,a,e.directory,t.fs):void 0;if(f!==void 0){const i=f===""?"":f+"/",{locale:u,ignoredRoutes:o}=a;let h=n.getAllRoutesForLocale(u).filter(c=>!o?.has(c.baseSlug||"")&&c.fsPath.startsWith(i)&&!c.excludeFromSidebar).sort((c,y)=>c.fsPath===y.fsPath?0:c.baseSlug.localeCompare(y.baseSlug,void 0,{numeric:!0}));const m=e.includeByMetadata?Q(e.includeByMetadata):Boolean;if(!h.length)return[];const $=(await Promise.all(h.map(async c=>{const y=c.versions?.find(x=>x.active),L=y&&{version:y.version,isDefault:y.default,versionFolderId:y.folderId},V=ee(v.posix.relative(f,c.fsPath)),O=c.getSidebar?.(c);return!a.ignoreCustomSidebar&&O?.length?{type:"group",fsPath:c.fsPath,metadata:c.metadata,link:c.slug,routeSlug:c.slug,label:await c.getNavText?.()||c.slug,[p]:c[p],[b]:c[b],sidebarItems:k(O,L,c[p],c[b]),...L,relativePathFromDirectory:v.relative(f,c.fsPath).replace(/@[^/]+\//,"")}:{type:"link",fsPath:c.fsPath,metadata:c.metadata,[p]:c[p],[b]:c[b],label:await c.getNavText?.()||c.slug,link:c.slug,routeSlug:c.slug,...L,relativePathFromDirectory:V}}))).filter(m);return e.flatten?T($,a):Z($,a)}let d=typeof e=="string"?e:e?.page,r,l;if(d){if(d.includes("#")){const[i,u]=d.split("#");u?l=u:A.warn(`Invalid heading anchor format in sidebar: "${u}". Heading anchors should contain only alphanumeric characters, hyphens, and underscores.`),d=i}if(d=j(d),a.locale&&a.locale!==_){const i=U(v.join(a.locale.toLowerCase(),d));r=n.getRouteBySlug(i)}r||(r=n.getRouteBySlug(d)),r||(r=n.getRouteByFsPath(F(n.contentDir,s,a,d,t.fs)))}const g=r?.metadata;if(e?.$ref){let i=F(n.contentDir,s,a,e.$ref,t.fs);if(a.ref!==void 0&&(i=v.posix.join(a.ref,e.$ref)),!t.fs.exists(i))return await S.panicOnBuildContentError(`Failed to load ${i} file. Make sure sidebar $ref path is correct.`),[];const u=await t.cache.load(i,"yaml"),o=v.dirname(i);return await I(u.data,s,n,t,{...a,navFile:i,ref:o})||[]}if(!r){const i=a.excludedFromLinkCheckerPatterns?.catalog.some(o=>o.test(d||"")),u=a.excludedFromLinkCheckerPatterns?.apiFunctions.some(o=>o.test(d||e.href||""));(u||i)&&(e={...e,href:d||e.href,page:void 0,target:e.target??(u?"_blank":void 0)}),await X(e,a,t,s)}if(r&&!e.disconnect&&!a.ignoreCustomSidebar&&(l||r?.getSidebar)){const i=r.versions?.find(o=>o.active),u=i&&{version:i.version,isDefault:i.default,versionFolderId:i.folderId};if(l){let o=[];if(r.getSidebar&&(o=r.getSidebar(r,{...e,...await P(e,n,t,a)}),o&&o.length>0)){const h=o[0];h&&h.link&&(h.link=`${h.link}#${l}`)}if(!o||o.length===0){let h=e.group||e.label||l;o=[{type:"link",fsPath:r.fsPath,metadata:r.metadata,link:`${r.slug}#${l}`,routeSlug:r.slug,label:h,labelTranslationKey:e.labelTranslationKey,...await P(e,n,t,a),[p]:r[p],[b]:{slug:r.slug,fsPath:r.fsPath},...u}]}return k(o,u,r[p],r[b])}if(r?.getSidebar){const o=r.getSidebar(r,{...e,...await P(e,n,t,a)}),h=e.group&&o?.[0]?.routeSlug===r.slug?o.slice(1):o;return k(a.groupCustomSidebars||e.group?[{type:"group",fsPath:r.fsPath,link:r.slug,routeSlug:r.slug,label:e.group||e.label||await r.getNavText?.()||r.slug,items:h,labelTranslationKey:e.labelTranslationKey,metadata:g,badges:e.badges,...await P(e,n,t,a)}]:o,u,r[p],r[b])}}if(r&&!e.group){const i=l?`${r.slug}#${l}`:r.slug;let u=e.label||l||"";u||(u=await r.getNavText?.()||r.slug);const o=r.versions?.find(m=>m.active),h=o&&{version:o.version,isDefault:o.default,versionFolderId:o.folderId};return{type:"link",fsPath:r.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,[p]:e?.rbac||r[p],[b]:{slug:r.slug,fsPath:r.fsPath},label:u,labelTranslationKey:e.labelTranslationKey,link:i,items:await I(e.items,s,n,t,a),separatorLine:e.separatorLine,linePosition:e.linePosition,routeSlug:e.disconnect?void 0:i,external:e.external,target:e.target,badges:e.badges,...await P(e,n,t,a),...h,additionalProps:e.additionalProps}}else if(e?.group){const i=r?.versions?.find(o=>o.active),u=R(a?.navFile);return{type:"group",fsPath:r?.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,version:i?.version||u?.versionName,versionFolderId:i?.folderId||(u?.versionFolderPath?C(u.versionFolderPath):void 0),label:e.group,link:r?.slug,routeSlug:r?.slug,badges:e.badges,labelTranslationKey:e.groupTranslationKey,items:await I(e.items,s,n,t,a),expanded:e.expanded?e.expanded.toString():void 0,selectFirstItemOnExpand:e.selectFirstItemOnExpand,menuStyle:e.menuStyle,separatorLine:e.separatorLine,linePosition:e.linePosition,...await P(e,n,t,a),[p]:e?.rbac,[b]:{slug:r?.slug||"",fsPath:r?.fsPath||""},additionalProps:e.additionalProps}}else{if(e?.href||e?.label)return{type:"link",metadata:g,link:e.href||"",label:e?.label||e?.href||"",labelTranslationKey:e.labelTranslationKey,external:e.external,target:e.target,separatorLine:e.separatorLine,linePosition:e.linePosition,badges:e.badges,...await P(e,n,t,a),[p]:e?.rbac,additionalProps:e.additionalProps};if(e?.separator!=null||e?.separatorLine!=null){const i=R(a?.navFile);return{type:"separator",metadata:g,version:i?.versionName,versionFolderId:i?.versionFolderPath?C(i.versionFolderPath):void 0,label:e.separator,labelTranslationKey:e.separatorTranslationKey,separatorLine:e.separatorLine,linePosition:e.linePosition,...await P(e,n,t,a),[p]:e?.rbac,additionalProps:e.additionalProps}}else{const i=R(a?.navFile);return{type:"error",label:`Can't resolve page: ${JSON.stringify(e)}`,version:i?.versionName,versionFolderId:i?.versionFolderPath?C(i.versionFolderPath):void 0}}}}async function X(e,s,n,t){const{href:a,page:f}=e;if(a||!f)return;const d=F(n.fs.cwd,t,s,f,n.fs),r=n.fs.exists(d),l=await n.isPathIgnored(d),g=(r?"The page is ignored: ":"Can't resolve page: ")+f;(!r||l)&&S.reportBrokenLink({type:"BROKEN_LINK",brokenLinkType:"LINK",title:e.label||e.group||"",link:d,rawLink:f,message:g,sourceFileRelativePath:s.navFile,sourceFileLocation:{line:0}})}function F(e,s,n,t="",a){if(n.ref!==void 0)return w(v.relative(e,v.resolve(e,v.join(n.ref,t))));if(t.startsWith("/")){const f=B(s)?q(s):void 0,d=f?`${a.localizationFolder}/${f}/`:"",r=t.slice(1);return B(r)?r:d+w(r)}return w(v.relative(e,v.resolve(e,s,t)))}function Z(e,s){const n={};for(const r of e){const l=v.dirname(r.relativePathFromDirectory),g=r.version?M+r.version:"",i=v.basename(r.relativePathFromDirectory)+g;d(l,r,i)}const t=f(a(n));return T(t,s);function a(r){const l=[];for(const g of Object.keys(r)){const i=r[g];l.push({...i,items:i.items?a(i.items):void 0})}return l}function f(r){return r.sort((l,g)=>{const i=typeof l=="string"?l.toLowerCase():l.relativePathFromDirectory||l.label||"",u=typeof g=="string"?g.toLowerCase():g.relativePathFromDirectory||g.label||"";return i.startsWith("index.")?-1:u.startsWith("index.")?1:i.localeCompare(u,void 0,{numeric:!0})})}function d(r,l,g){r==="."&&(r="");const i=r.split("/").filter(Boolean);let u=n;for(const o of i){const h=o+(l?.version||"");u[h]||(u[h]={type:"group",version:l?.version,label:o,isDefault:l?.isDefault,versionFolderId:l.versionFolderId,items:{}}),u=u[h].items}u[g]=l}}function T(e,s){return e.flatMap(n=>n?.sidebarItems?s.groupCustomSidebars?{...n,items:n.sidebarItems,sidebarItems:void 0,relativePathFromDirectory:void 0}:n.sidebarItems:{...n,items:n.items?T(n.items,s):void 0})}function k(e,s,n,t){return e.map(a=>({...a,...s,[p]:a[p]||n,[b]:a[b]||t,items:a.type==="group"&&a.items?k(a.items,s,n):a.items}))}function ee(e){return e.replace(/@[^/]+\//,"")}async function Pe(e,s,n,t){const a=(e?.items||[]).filter(r=>r.linkedSidebars?.length).map(r=>({...r,items:void 0})),f=await D(a,s.contentDir,s,n,t),d=new Map;for(const r of f)if(r.linkedSidebars?.length)for(const l of r.linkedSidebars){if(d.has(l)){A.warn(`Only one navbar item can belong to sidebar. "${l}" on 'linkedSidebars' property on "${r.label}" will be ignored.`);continue}d.set(l,{label:r.label,link:r.link})}return d}export{Pe as collectItemsLinkedToSidebars,N as normalizeItems,K as resolveItem,I as resolveItems,D as resolveLinksFromConfig};
1
+ import*as v from"path";import{REDOCLY_ROUTE_RBAC as b,REDOCLY_TEAMS_RBAC as h}from"@redocly/config";import{VERSION_SEPARATOR as M}from"../constants/common.js";import{DEFAULT_LOCALE_PLACEHOLDER as _}from"../../constants/common.js";import{removeTrailingSlash as j}from"../../utils/url/remove-trailing-slash.js";import{isPrimitive as W}from"../../utils/guards/is-primitive.js";import{slash as w}from"../../utils/path/slash.js";import{isAbsoluteUrl as z}from"../../utils/url/is-absolute-url.js";import{normalizeRouteSlug as J}from"../../utils/path/normalize-route-slug.js";import{parsePathVersions as C}from"../../utils/path/parse-path-versions.js";import{logger as A}from"../tools/notifiers/logger.js";import{reporter as S}from"../tools/notifiers/reporter.js";import{shaDirPathShort as R}from"../utils/crypto/sha-dir-path-short.js";import{copyStaticFile as U,FileNotFoundError as E}from"../utils/fs.js";import{isIconPath as H,resolveAssetPath as Y}from"../utils/index.js";import{resolveSrcSet as G}from"../utils/resolve-src-set.js";import{isL10nPath as B}from"../fs/utils/is-l10n-path.js";import{getLocaleFromRelativePath as q}from"../fs/utils/get-locale-from-relative-path.js";async function N(e,i,n,t,a){if(!e)return;const f={...a,ignoreCustomSidebar:!0};if(W(e)){if(typeof e=="string"){const r=F(n.contentDir,i,a,e,t.fs);if(t.fs.exists(r)){if(n.getRouteByFsPath(r))return K({page:e},i,n,t,f);{const g=t.fs.getFileInfo(r);return g?U(n.contentDir,g.realRelativePath,n.outdir):void 0}}}return e}return Array.isArray(e)?I(D(e),i,n,t,f):Object.fromEntries(await Promise.all(Object.entries(e).map(async([r,l])=>[r,await N(l,i,n,t,a)])))}function D(e){return e.map(i=>({...i,items:i.items?D(i.items):void 0}))}async function I(e,i,n,t,a){if(Array.isArray(e))return(await Promise.all(e.map(f=>K(f,i,n,t,a)))).flatMap(f=>f)}async function y(e,i,n,t){let a,f;if(typeof e.icon=="object"){if("srcSet"in e.icon)try{a=await G(e.icon.srcSet,n.fs,{fromFileRelativePath:t.navFile,contentDir:i.contentDir,outdir:i.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`):await S.panicOnBuild(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`)}}else if(typeof e.icon=="string")if(z(e.icon)||H(e.icon))try{f=await Y(e.icon,n.fs,{fromFileRelativePath:t.navFile,contentDir:i.contentDir,outdir:i.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon" from ${t.navFile}: file ${f} does not exist`):await S.panicOnBuild(`Cannot resolve "item.icon" from ${t.navFile}: ${d.message}`)}else f=e.icon;return{icon:f,srcSet:a}}function Q(e){return i=>{if(i.type==="link"||i.type==="group"){const n=i.metadata;return n?Object.entries(e).every(([t,a])=>Array.isArray(a)?a.some(f=>n[t]===f):n[t]===a):!1}return!0}}async function K(e,i,n,t,a){if(e?.tab!==void 0||e?.menu!==void 0){const s=`Navigation tabs ("tab"/"menu") are only allowed at the top level of a sidebars.yaml file: ${JSON.stringify(e)}`;return await S.panicOnBuildContentError(`Invalid nav item in %rp. ${s}`,a.navFile),{type:"error",label:s}}if(e?.directory&&e.items?.length)return{type:"error",label:`Can't have both "directory" and "items" in the nav item: ${JSON.stringify(e)}`};e?.directory&&e?.group&&(e={...e,directory:void 0,items:[{directory:e.directory}]});const f=e?.directory?F(n.contentDir,i,a,e.directory,t.fs):void 0;if(f!==void 0){const s=f===""?"":f+"/",{locale:u,ignoredRoutes:o}=a;let p=n.getAllRoutesForLocale(u).filter(c=>!o?.has(c.baseSlug||"")&&c.fsPath.startsWith(s)&&!c.excludeFromSidebar).sort((c,P)=>c.fsPath===P.fsPath?0:c.baseSlug.localeCompare(P.baseSlug,void 0,{numeric:!0}));const m=e.includeByMetadata?Q(e.includeByMetadata):Boolean;if(!p.length)return[];const T=(await Promise.all(p.map(async c=>{const P=c.versions?.find(x=>x.active),L=P&&{version:P.version,isDefault:P.default,versionFolderId:P.folderId},V=ee(v.posix.relative(f,c.fsPath)),O=c.getSidebar?.(c);return!a.ignoreCustomSidebar&&O?.length?{type:"group",fsPath:c.fsPath,metadata:c.metadata,link:c.slug,routeSlug:c.slug,label:await c.getNavText?.()||c.slug,[h]:c[h],[b]:c[b],sidebarItems:k(O,L,c[h],c[b]),...L,relativePathFromDirectory:v.relative(f,c.fsPath).replace(/@(?<!@[^/]*?@)[^/]+\//,"")}:{type:"link",fsPath:c.fsPath,metadata:c.metadata,[h]:c[h],[b]:c[b],label:await c.getNavText?.()||c.slug,link:c.slug,routeSlug:c.slug,...L,relativePathFromDirectory:V}}))).filter(m);return e.flatten?$(T,a):Z(T,a)}let d=typeof e=="string"?e:e?.page,r,l;if(d){if(d.includes("#")){const[s,u]=d.split("#");u?l=u:A.warn(`Invalid heading anchor format in sidebar: "${u}". Heading anchors should contain only alphanumeric characters, hyphens, and underscores.`),d=s}if(d=j(d),a.locale&&a.locale!==_){const s=J(v.join(a.locale.toLowerCase(),d));r=n.getRouteBySlug(s)}r||(r=n.getRouteBySlug(d)),r||(r=n.getRouteByFsPath(F(n.contentDir,i,a,d,t.fs)))}const g=r?.metadata;if(e?.$ref){let s=F(n.contentDir,i,a,e.$ref,t.fs);if(a.ref!==void 0&&(s=v.posix.join(a.ref,e.$ref)),!t.fs.exists(s))return await S.panicOnBuildContentError(`Failed to load ${s} file. Make sure sidebar $ref path is correct.`),[];const u=await t.cache.load(s,"yaml"),o=v.dirname(s);return await I(u.data,i,n,t,{...a,navFile:s,ref:o})||[]}if(!r){const s=a.excludedFromLinkCheckerPatterns?.catalog.some(o=>o.test(d||"")),u=a.excludedFromLinkCheckerPatterns?.apiFunctions.some(o=>o.test(d||e.href||""));(u||s)&&(e={...e,href:d||e.href,page:void 0,target:e.target??(u?"_blank":void 0)}),await X(e,a,t,i)}if(r&&!e.disconnect&&!a.ignoreCustomSidebar&&(l||r?.getSidebar)){const s=r.versions?.find(o=>o.active),u=s&&{version:s.version,isDefault:s.default,versionFolderId:s.folderId};if(l){let o=[];if(r.getSidebar&&(o=r.getSidebar(r,{...e,...await y(e,n,t,a)}),o&&o.length>0)){const p=o[0];p&&p.link&&(p.link=`${p.link}#${l}`)}if(!o||o.length===0){let p=e.group||e.label||l;o=[{type:"link",fsPath:r.fsPath,metadata:r.metadata,link:`${r.slug}#${l}`,routeSlug:r.slug,label:p,labelTranslationKey:e.labelTranslationKey,...await y(e,n,t,a),[h]:r[h],[b]:{slug:r.slug,fsPath:r.fsPath},...u}]}return k(o,u,r[h],r[b])}if(r?.getSidebar){const o=r.getSidebar(r,{...e,...await y(e,n,t,a)}),p=e.group&&o?.[0]?.routeSlug===r.slug?o.slice(1):o;return k(a.groupCustomSidebars||e.group?[{type:"group",fsPath:r.fsPath,link:r.slug,routeSlug:r.slug,label:e.group||e.label||await r.getNavText?.()||r.slug,items:p,labelTranslationKey:e.labelTranslationKey,metadata:g,badges:e.badges,...await y(e,n,t,a)}]:o,u,r[h],r[b])}}if(r&&!e.group){const s=l?`${r.slug}#${l}`:r.slug;let u=e.label||l||"";u||(u=await r.getNavText?.()||r.slug);const o=r.versions?.find(m=>m.active),p=o&&{version:o.version,isDefault:o.default,versionFolderId:o.folderId};return{type:"link",fsPath:r.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,[h]:e?.rbac||r[h],[b]:{slug:r.slug,fsPath:r.fsPath},label:u,labelTranslationKey:e.labelTranslationKey,link:s,items:await I(e.items,i,n,t,a),separatorLine:e.separatorLine,linePosition:e.linePosition,routeSlug:e.disconnect?void 0:s,external:e.external,target:e.target,badges:e.badges,...await y(e,n,t,a),...p,additionalProps:e.additionalProps}}else if(e?.group){const s=r?.versions?.find(o=>o.active),u=C(a?.navFile);return{type:"group",fsPath:r?.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,version:s?.version||u?.versionName,versionFolderId:s?.folderId||(u?.versionFolderPath?R(u.versionFolderPath):void 0),label:e.group,link:r?.slug,routeSlug:r?.slug,badges:e.badges,labelTranslationKey:e.groupTranslationKey,items:await I(e.items,i,n,t,a),expanded:e.expanded?e.expanded.toString():void 0,selectFirstItemOnExpand:e.selectFirstItemOnExpand,menuStyle:e.menuStyle,separatorLine:e.separatorLine,linePosition:e.linePosition,...await y(e,n,t,a),[h]:e?.rbac,[b]:{slug:r?.slug||"",fsPath:r?.fsPath||""},additionalProps:e.additionalProps}}else{if(e?.href||e?.label)return{type:"link",metadata:g,link:e.href||"",label:e?.label||e?.href||"",labelTranslationKey:e.labelTranslationKey,external:e.external,target:e.target,separatorLine:e.separatorLine,linePosition:e.linePosition,badges:e.badges,...await y(e,n,t,a),[h]:e?.rbac,additionalProps:e.additionalProps};if(e?.separator!=null||e?.separatorLine!=null){const s=C(a?.navFile);return{type:"separator",metadata:g,version:s?.versionName,versionFolderId:s?.versionFolderPath?R(s.versionFolderPath):void 0,label:e.separator,labelTranslationKey:e.separatorTranslationKey,separatorLine:e.separatorLine,linePosition:e.linePosition,...await y(e,n,t,a),[h]:e?.rbac,additionalProps:e.additionalProps}}else{const s=C(a?.navFile);return{type:"error",label:`Can't resolve page: ${JSON.stringify(e)}`,version:s?.versionName,versionFolderId:s?.versionFolderPath?R(s.versionFolderPath):void 0}}}}async function X(e,i,n,t){const{href:a,page:f}=e;if(a||!f)return;const d=F(n.fs.cwd,t,i,f,n.fs),r=n.fs.exists(d),l=await n.isPathIgnored(d),g=(r?"The page is ignored: ":"Can't resolve page: ")+f;(!r||l)&&S.reportBrokenLink({type:"BROKEN_LINK",brokenLinkType:"LINK",title:e.label||e.group||"",link:d,rawLink:f,message:g,sourceFileRelativePath:i.navFile,sourceFileLocation:{line:0}})}function F(e,i,n,t="",a){if(n.ref!==void 0)return w(v.relative(e,v.resolve(e,v.join(n.ref,t))));if(t.startsWith("/")){const f=B(i)?q(i):void 0,d=f?`${a.localizationFolder}/${f}/`:"",r=t.slice(1);return B(r)?r:d+w(r)}return w(v.relative(e,v.resolve(e,i,t)))}function Z(e,i){const n={};for(const r of e){const l=v.dirname(r.relativePathFromDirectory),g=r.version?M+r.version:"",s=v.basename(r.relativePathFromDirectory)+g;d(l,r,s)}const t=f(a(n));return $(t,i);function a(r){const l=[];for(const g of Object.keys(r)){const s=r[g];l.push({...s,items:s.items?a(s.items):void 0})}return l}function f(r){return r.sort((l,g)=>{const s=typeof l=="string"?l.toLowerCase():l.relativePathFromDirectory||l.label||"",u=typeof g=="string"?g.toLowerCase():g.relativePathFromDirectory||g.label||"";return s.startsWith("index.")?-1:u.startsWith("index.")?1:s.localeCompare(u,void 0,{numeric:!0})})}function d(r,l,g){r==="."&&(r="");const s=r.split("/").filter(Boolean);let u=n;for(const o of s){const p=o+(l?.version||"");u[p]||(u[p]={type:"group",version:l?.version,label:o,isDefault:l?.isDefault,versionFolderId:l.versionFolderId,items:{}}),u=u[p].items}u[g]=l}}function $(e,i){return e.flatMap(n=>n?.sidebarItems?i.groupCustomSidebars?{...n,items:n.sidebarItems,sidebarItems:void 0,relativePathFromDirectory:void 0}:n.sidebarItems:{...n,items:n.items?$(n.items,i):void 0})}function k(e,i,n,t){return e.map(a=>({...a,...i,[h]:a[h]||n,[b]:a[b]||t,items:a.type==="group"&&a.items?k(a.items,i,n):a.items}))}function ee(e){return e.replace(/@(?<!@[^/]*?@)[^/]+\//,"")}async function ye(e,i,n,t){const a=(e?.items||[]).filter(r=>r.linkedSidebars?.length).map(r=>({...r,items:void 0})),f=await N(a,i.contentDir,i,n,t),d=new Map;for(const r of f)if(r.linkedSidebars?.length)for(const l of r.linkedSidebars){if(d.has(l)){A.warn(`Only one navbar item can belong to sidebar. "${l}" on 'linkedSidebars' property on "${r.label}" will be ignored.`);continue}d.set(l,{label:r.label,link:r.link})}return d}export{ye as collectItemsLinkedToSidebars,D as normalizeItems,K as resolveItem,I as resolveItems,N as resolveLinksFromConfig};
@@ -1 +1 @@
1
- import{writeFileSync as D}from"node:fs";import L from"path";import{SCORECARD_OUTPUT_FILE_NAME as w}from"../../constants/common.js";import{mapObject as E}from"../../../utils/object/map-object.js";import{envConfig as A}from"../../config/env-config.js";import{removeLeadingSlash as j}from"../../../utils/url/remove-leading-slash.js";import{combineUrls as O}from"@redocly/theme/core/utils";import{logger as _}from"../../tools/notifiers/logger.js";import{getRouteSlugToCatalogSlugMap as F}from"../../utils/catalog-classic/get-route-slug-to-catalog-slug-map.js";import{deepEqual as I}from"../../../utils/object/deep-equal.js";import{ensureDir as N}from"../../utils/index.js";import{getTemplatePath as q}from"./get-template-path.js";import{getAllRuleNames as U}from"./lint.js";import{getScorecardConfig as T}from"./get-scorecard-config.js";import{getScorecardSlug as k}from"./shared-utils.js";import{scorecardConfigLoader as M}from"./loaders/scorecard-config.js";import{scorecardLoader as W}from"./loaders/scorecard.js";import{computeScorecard as B}from"./compute-scorecard.js";import{telemetryTraceStep as J}from"../../../cli/telemetry/helpers/trace-step.js";const $="scorecardClassic";let u={},R={};async function ne({id:b,requiredEntitlements:P,loadersPrefix:v=""}){let p=null,y=null,h=!1;return{id:b??"scorecardClassic",requiredEntitlements:P??["scorecard"],loaders:{[`${v}scorecard-config`]:M,[`${v}scorecard`]:W},async processContent(r,l){await J("com.redocly.build.plugin.scorecardClassic",async S=>{const a=r.createTemplate($,q("./template/index.js")),g=await l.getConfig(),m=T(g),f=g?.reunite??{},i=[()=>p===null,()=>!I(u,m),()=>!I(R,f)].some(e=>e());u=m,S?.setAttribute("config",JSON.stringify(u||{})),R=f;const n=g.catalogClassic??{},c=u.levels||[];if(c.length<1)throw Error("Invalid configuration of levels config");i&&(p=await B({actions:r,context:l,scorecardConfig:u,reuniteConfig:R}));const{data:{configs:o}}=await l.cache.load("",`${v}scorecard-config`),{perLevel:d,all:s}=U(o);y={levelNames:c.map(e=>e.name),rules:s,rulesPerLevel:d};for(const[e,t]of Object.entries(n)){const C=O(t.slug,"scorecard/");r.addRoute({duplicateInAllLocales:!0,slug:C,fsPath:O(t.slug,"scorecard/"),templateId:a,hasClientRoutes:!0,excludeFromSidebar:!0,serverPropsGetterIds:[],sharedData:[{id:"scorecard",key:"scorecard"},{key:"catalog",id:"catalog-"+e}],getNavText:()=>Promise.resolve(t.title||"API design scorecard"),getStaticData:async()=>({props:{catalogId:e,catalogConfig:{...t,items:void 0},scorecardConfig:u,scorecardInfo:y}})})}})},afterRoutesCreated:async(r,l)=>{const S=await l.getConfig(),a=S.catalogClassic??{},g=T(S);if(Object.keys(a).length){const i=Object.keys(a).length>1?await F(r,l,a):null,n={};for(const[c,o]of Object.entries(p||{})){const d=r.getRouteByFsPath(c),s=d?.slug;if(s){if(d&&!g.ignoreMetadata){const e=i?i.get(s)??Object.values(a)[0].slug:Object.values(a)[0].slug,t=O(e,"scorecard/");d.metadata={...d.metadata,scorecardStatus:o.status,scorecardLevel:o.scorecardLevel,scorecardLevelIdx:o.scorecardLevelIdx,scorecardLevels:E(o.levels,C=>({uniqueErrors:C.uniqueErrors,uniqueWarnings:C.uniqueWarnings})),scoreCardSlug:t+"apis/"+encodeURIComponent(j(s))}}if(n[s]={...o,levels:E(o.levels,e=>({...e,problems:e.problems.map(t=>({ruleId:t.ruleId,severity:t.severity}))}))},!h){const e=L.resolve(r.outdir,"_scorecard",k(s));D(N(e),JSON.stringify(o))}}}await r.createSharedData("scorecard",n)}const m={};for(const[i,n]of Object.entries(p||{})){const c=r.getRouteByFsPath(i)?.slug;c&&(m[c]=n)}const f=A.REDOCLY_METADATA_OUTPUT_FOLDER;!h&&f&&(_.info("Writing scorecard data..."),D(L.join(f,w),JSON.stringify({scorecardData:m,...y}))),h=!0}}}export{ne as scorecardClassicPlugin};
1
+ import{writeFileSync as R}from"node:fs";import I from"path";import{SCORECARD_OUTPUT_FILE_NAME as w}from"../../constants/common.js";import{mapObject as L}from"../../../utils/object/map-object.js";import{envConfig as A}from"../../config/env-config.js";import{removeLeadingSlash as j}from"../../../utils/url/remove-leading-slash.js";import{combineUrls as O}from"@redocly/theme/core/utils";import{logger as _}from"../../tools/notifiers/logger.js";import{getRouteSlugToCatalogSlugMap as F}from"../../utils/catalog-classic/get-route-slug-to-catalog-slug-map.js";import{getCatalogSharedDataId as N}from"../../utils/catalog-classic/get-catalog-shared-data-id.js";import{deepEqual as E}from"../../../utils/object/deep-equal.js";import{ensureDir as q}from"../../utils/index.js";import{getTemplatePath as U}from"./get-template-path.js";import{getAllRuleNames as k}from"./lint.js";import{getScorecardConfig as T}from"./get-scorecard-config.js";import{getScorecardSlug as M}from"./shared-utils.js";import{scorecardConfigLoader as W}from"./loaders/scorecard-config.js";import{scorecardLoader as B}from"./loaders/scorecard.js";import{computeScorecard as J}from"./compute-scorecard.js";import{telemetryTraceStep as $}from"../../../cli/telemetry/helpers/trace-step.js";const x="scorecardClassic";let u={},D={};async function ue({id:b,requiredEntitlements:P,loadersPrefix:v=""}){let p=null,y=null,h=!1;return{id:b??"scorecardClassic",requiredEntitlements:P??["scorecard"],loaders:{[`${v}scorecard-config`]:W,[`${v}scorecard`]:B},async processContent(r,l){await $("com.redocly.build.plugin.scorecardClassic",async S=>{const a=r.createTemplate(x,U("./template/index.js")),g=await l.getConfig(),m=T(g),f=g?.reunite??{},i=[()=>p===null,()=>!E(u,m),()=>!E(D,f)].some(e=>e());u=m,S?.setAttribute("config",JSON.stringify(u||{})),D=f;const n=g.catalogClassic??{},c=u.levels||[];if(c.length<1)throw Error("Invalid configuration of levels config");i&&(p=await J({actions:r,context:l,scorecardConfig:u,reuniteConfig:D}));const{data:{configs:t}}=await l.cache.load("",`${v}scorecard-config`),{perLevel:d,all:s}=k(t);y={levelNames:c.map(e=>e.name),rules:s,rulesPerLevel:d};for(const[e,o]of Object.entries(n)){const C=O(o.slug,"scorecard/");r.addRoute({duplicateInAllLocales:!0,slug:C,fsPath:O(o.slug,"scorecard/"),templateId:a,hasClientRoutes:!0,excludeFromSidebar:!0,serverPropsGetterIds:[],sharedData:[{id:"scorecard",key:"scorecard"},{key:"catalog",id:N(e)}],getNavText:()=>Promise.resolve(o.title||"API design scorecard"),getStaticData:async()=>({props:{catalogId:e,catalogConfig:{...o,items:void 0},scorecardConfig:u,scorecardInfo:y}})})}})},afterRoutesCreated:async(r,l)=>{const S=await l.getConfig(),a=S.catalogClassic??{},g=T(S);if(Object.keys(a).length){const i=Object.keys(a).length>1?await F(r,l,a):null,n={};for(const[c,t]of Object.entries(p||{})){const d=r.getRouteByFsPath(c),s=d?.slug;if(s){if(d&&!g.ignoreMetadata){const e=i?i.get(s)??Object.values(a)[0].slug:Object.values(a)[0].slug,o=O(e,"scorecard/");d.metadata={...d.metadata,scorecardStatus:t.status,scorecardLevel:t.scorecardLevel,scorecardLevelIdx:t.scorecardLevelIdx,scorecardLevels:L(t.levels,C=>({uniqueErrors:C.uniqueErrors,uniqueWarnings:C.uniqueWarnings})),scoreCardSlug:o+"apis/"+encodeURIComponent(j(s))}}if(n[s]={...t,levels:L(t.levels,e=>({...e,problems:e.problems.map(o=>({ruleId:o.ruleId,severity:o.severity}))}))},!h){const e=I.resolve(r.outdir,"_scorecard",M(s));R(q(e),JSON.stringify(t))}}}await r.createSharedData("scorecard",n)}const m={};for(const[i,n]of Object.entries(p||{})){const c=r.getRouteByFsPath(i)?.slug;c&&(m[c]=n)}const f=A.REDOCLY_METADATA_OUTPUT_FOLDER;!h&&f&&(_.info("Writing scorecard data..."),R(I.join(f,w),JSON.stringify({scorecardData:m,...y}))),h=!0}}}export{ue as scorecardClassicPlugin};
@@ -1 +1 @@
1
- import{useMemo as p,useState as H,useCallback as J}from"react";import{isDefined as U}from"../../../../utils/guards/is-defined.js";import{useCatalogClassic as G}from"../../../../client/app/hooks";import{usePageSharedData as L}from"../../../../client/providers/page-data/hooks";import{NON_CONFORMANT as v,OTHER_TEAMS_LABEL as K}from"./utils";function j(h,d){return Object.entries(h).find(([g])=>d.startsWith(g))?.[1]}function ee(h){const{catalogConfig:d,scorecardConfig:g,scorecardInfo:c}=h.pageProps,C=L("catalog"),S=C.some(e=>e.metadata?.publishedAt||e.metadata?.createdAt),A=g.teamMetadataProperty?.label||"Team",f=g.teamMetadataProperty?.property||"team",y=g.teamMetadataProperty?.default,T=C.some(e=>e.metadata?.[f]||e.metadata?.owner),k=p(()=>({...d,filters:[{title:"Scorecard level",property:"scorecardLevel",options:[v,...c.levelNames],type:"checkboxes"},S?{title:"Published date",property:"publishedAt",type:"date-range"}:void 0,T&&!d.filters?.find(e=>e.property===f)?{title:A,property:f,type:"select",...y&&{missingCategoryName:y}}:void 0,...d.filters||[]].filter(U)}),[d,T,S,A,y,f,c.levelNames]),N=L("scorecard"),q=C.filter(e=>!!j(N,e.link||"")),{filterTerm:M,setFilterTerm:D,groups:P,filters:E}=G(k,q),u=p(()=>P.flatMap(e=>e.items).map(e=>({api:{...e,publishedAt:e.publishedAt||e.createdAt,team:e[f]||e.owner},scorecard:j(N,e.link)})).filter(e=>e.scorecard),[JSON.stringify(P),N,f]),w=c.levelNames,z=p(()=>{const e={total:u.length,levels:{}};return[v,...w].forEach(r=>{e.levels[r]=u.filter(s=>s.scorecard?.scorecardLevel===r).length}),e},[u,w]),O=p(()=>w.map(e=>{const r={error:new Set,warn:new Set},s={errors:0,warnings:0};for(const t of u){if(!t.scorecard)continue;const o=t.scorecard.levels[e];if(o){s.errors+=o.errors||0,s.warnings+=o.warnings||0;for(const n of o.problems)r[n.severity]?.add(n.ruleId)}}return{name:e,count:s,uniqueCount:{errors:r.error.size,warnings:r.warn.size}}}),[u,w]),R=p(()=>O.reduce((e,r)=>e+r.count.errors+r.count.warnings,0),[O]),V=p(()=>{const e={};for(const r of c.rules)e[r]={count:0,apis:[],ruleId:r,status:0,apisCount:0,warningApisCount:0,errorApisCount:0,teams:{},levels:c.levelNames.reduce((s,t)=>(s[t]={warnings:0,errors:0},s),{})};for(const r of u){if(!r.scorecard)continue;const{scorecard:s,api:t}=r,o=new Set;for(const n of Object.keys(s?.levels||{})){const l=s.levels[n];for(const m of l?.problems||[]){const a=m.ruleId;if(!o.has(a))if(e[a]=e[a]||{count:0,apis:[],ruleId:a,status:0,apisCount:0,levels:{}},e[a].count++,typeof t.team=="string"&&(e[a].teams[t.team]=(e[a].teams[t.team]||0)+1),e[a].levels[n]=e[a].levels[n]||{warnings:0,errors:0},m.severity==="error"?(e[a].levels[n].errors++,e[a].errorApisCount++):(e[a].levels[n].warnings++,e[a].warningApisCount++),!e[a].apis.find(b=>b.link===t.link))e[a].apis.push({...t,count:1,severity:m.severity,problems:[m]});else{const b=e[a].apis.find(_=>_.link===t.link);b&&(b.count++,b.problems.push(m))}}for(const m of l?.problems||[])o.add(m.ruleId)}}for(const r of Object.values(e))r.apisCount=r.apis.length,r.status=r.apisCount>0?1:0,r.warningApisCount=r.apis.filter(s=>["warn","warning"].includes(s.severity)).length,r.errorApisCount=r.apis.filter(s=>s.severity==="error").length;return Object.values(e).sort((r,s)=>{let t=r.ruleId,o=s.ruleId;return t<o?-1:t>o?1:0})},[u,c.levelNames,c.rules]),[i,B]=H({property:"below",direction:"desc"}),W=J(e=>{i.property===e?B(r=>({...r,direction:r.direction==="asc"?"desc":"asc"})):B({property:e,direction:"asc"})},[i]),{sortedStatsByTeam:x,statsByTeam:I}=p(()=>{const e={},r={};for(const s of u){if(!s.scorecard)continue;const{api:t}=s,o=t.team?String(t.team):y||K;if(!o)continue;e[o]=e[o]||{team:o,below:0,minimum:0,highest:0,levels:{}};const n=r[o]=r[o]||{};for(const l of[v,...c.levelNames]){e[o].levels[l]=e[o].levels[l]||{errors:0,warnings:0,uniqueErrors:0,uniqueWarnings:0,apis:0},n[l]=n[l]||{error:new Set,warn:new Set},e[o].levels[l].errors+=s.scorecard?.levels[l]?.errors||0,e[o].levels[l].warnings+=s.scorecard?.levels[l]?.warnings||0,e[o].levels[l].apis+=s.scorecard.scorecardLevel===l?1:0;for(const m of s.scorecard?.levels[l]?.problems||[])n[l][m.severity]?.add(m.ruleId)}}for(const s of Object.keys(e))for(const t of Object.keys(e[s].levels))e[s].levels[t].uniqueErrors=r[s][t].error.size,e[s].levels[t].uniqueWarnings=r[s][t].warn.size;return{sortedStatsByTeam:Object.values(e).sort((s,t)=>{let o=s[i.property],n=t[i.property];return["team","below","minimum","highest"].includes(i.property)||(o=s.levels[i.property].errors*1e3+s.levels[i.property].warnings,n=t.levels[i.property].errors*1e3+t.levels[i.property].warnings),o<n?i.direction==="asc"?-1:1:o>n?i.direction==="asc"?1:-1:0}),statsByTeam:e}},[u,c.levelNames,i.direction,i.property,y]),F=p(()=>Object.values(I).sort((e,r)=>r.levels[v].apis-e.levels[v].apis).filter(e=>e.levels[v].apis>0),[I]);return{apis:u,summary:z,problemsByStatus:O,totalProblems:R,problemsByRule:V,sortedStatsByTeam:x,handleSortRulesTeams:W,nonConformantByTeam:F,filterTerm:M,setFilterTerm:D,groups:P,filters:E,scorecardInfo:c,catalogConfig:k,hasTeam:T,hasPublishedAt:S,teamLabel:A,teamProperty:f}}export{ee as useData};
1
+ import{useMemo as p,useState as H,useCallback as U}from"react";import{isDefined as G}from"../../../../utils/guards/is-defined.js";import{useCatalogClassic as J}from"../../../../client/app/hooks";import{usePageSharedData as L}from"../../../../client/providers/page-data/hooks";import{NON_CONFORMANT as v,OTHER_TEAMS_LABEL as K}from"./utils";function j(S,d){return Object.entries(S).find(([g])=>d.startsWith(g))?.[1]}function ee(S){const{catalogConfig:d,scorecardConfig:g,scorecardInfo:c}=S.pageProps,w=L("catalog"),A=w.some(e=>e.metadata?.publishedAt||e.metadata?.createdAt),T=g.teamMetadataProperty?.label||"Team",f=g.teamMetadataProperty?.property||"team",y=g.teamMetadataProperty?.default,P=w.some(e=>e.metadata?.[f]||e.metadata?.owner),k=p(()=>({...d,filters:[{title:"Scorecard level",property:"scorecardLevel",options:[v,...c.levelNames],type:"checkboxes"},A?{title:"Published date",property:"publishedAt",type:"date-range"}:void 0,P&&!d.filters?.find(e=>e.property===f)?{title:T,property:f,type:"select",...y&&{missingCategoryName:y}}:void 0,...d.filters||[]].filter(G)}),[d,P,A,T,y,f,c.levelNames]),h=L("scorecard"),q=p(()=>w.filter(e=>!!j(h,e.link||"")),[w,h]),{filterTerm:M,setFilterTerm:D,groups:N,filters:E}=J(k,q),u=p(()=>N.flatMap(e=>e.items).map(e=>({api:{...e,publishedAt:e.publishedAt||e.createdAt,team:e[f]||e.owner},scorecard:j(h,e.link)})).filter(e=>e.scorecard),[N,h,f]),C=c.levelNames,z=p(()=>{const e={total:u.length,levels:{}};return[v,...C].forEach(r=>{e.levels[r]=u.filter(s=>s.scorecard?.scorecardLevel===r).length}),e},[u,C]),O=p(()=>C.map(e=>{const r={error:new Set,warn:new Set},s={errors:0,warnings:0};for(const t of u){if(!t.scorecard)continue;const o=t.scorecard.levels[e];if(o){s.errors+=o.errors||0,s.warnings+=o.warnings||0;for(const n of o.problems)r[n.severity]?.add(n.ruleId)}}return{name:e,count:s,uniqueCount:{errors:r.error.size,warnings:r.warn.size}}}),[u,C]),R=p(()=>O.reduce((e,r)=>e+r.count.errors+r.count.warnings,0),[O]),V=p(()=>{const e={};for(const r of c.rules)e[r]={count:0,apis:[],ruleId:r,status:0,apisCount:0,warningApisCount:0,errorApisCount:0,teams:{},levels:c.levelNames.reduce((s,t)=>(s[t]={warnings:0,errors:0},s),{})};for(const r of u){if(!r.scorecard)continue;const{scorecard:s,api:t}=r,o=new Set;for(const n of Object.keys(s?.levels||{})){const l=s.levels[n];for(const m of l?.problems||[]){const a=m.ruleId;if(!o.has(a))if(e[a]=e[a]||{count:0,apis:[],ruleId:a,status:0,apisCount:0,levels:{}},e[a].count++,typeof t.team=="string"&&(e[a].teams[t.team]=(e[a].teams[t.team]||0)+1),e[a].levels[n]=e[a].levels[n]||{warnings:0,errors:0},m.severity==="error"?(e[a].levels[n].errors++,e[a].errorApisCount++):(e[a].levels[n].warnings++,e[a].warningApisCount++),!e[a].apis.find(b=>b.link===t.link))e[a].apis.push({...t,count:1,severity:m.severity,problems:[m]});else{const b=e[a].apis.find(_=>_.link===t.link);b&&(b.count++,b.problems.push(m))}}for(const m of l?.problems||[])o.add(m.ruleId)}}for(const r of Object.values(e))r.apisCount=r.apis.length,r.status=r.apisCount>0?1:0,r.warningApisCount=r.apis.filter(s=>["warn","warning"].includes(s.severity)).length,r.errorApisCount=r.apis.filter(s=>s.severity==="error").length;return Object.values(e).sort((r,s)=>{let t=r.ruleId,o=s.ruleId;return t<o?-1:t>o?1:0})},[u,c.levelNames,c.rules]),[i,B]=H({property:"below",direction:"desc"}),W=U(e=>{i.property===e?B(r=>({...r,direction:r.direction==="asc"?"desc":"asc"})):B({property:e,direction:"asc"})},[i]),{sortedStatsByTeam:x,statsByTeam:I}=p(()=>{const e={},r={};for(const s of u){if(!s.scorecard)continue;const{api:t}=s,o=t.team?String(t.team):y||K;if(!o)continue;e[o]=e[o]||{team:o,below:0,minimum:0,highest:0,levels:{}};const n=r[o]=r[o]||{};for(const l of[v,...c.levelNames]){e[o].levels[l]=e[o].levels[l]||{errors:0,warnings:0,uniqueErrors:0,uniqueWarnings:0,apis:0},n[l]=n[l]||{error:new Set,warn:new Set},e[o].levels[l].errors+=s.scorecard?.levels[l]?.errors||0,e[o].levels[l].warnings+=s.scorecard?.levels[l]?.warnings||0,e[o].levels[l].apis+=s.scorecard.scorecardLevel===l?1:0;for(const m of s.scorecard?.levels[l]?.problems||[])n[l][m.severity]?.add(m.ruleId)}}for(const s of Object.keys(e))for(const t of Object.keys(e[s].levels))e[s].levels[t].uniqueErrors=r[s][t].error.size,e[s].levels[t].uniqueWarnings=r[s][t].warn.size;return{sortedStatsByTeam:Object.values(e).sort((s,t)=>{let o=s[i.property],n=t[i.property];return["team","below","minimum","highest"].includes(i.property)||(o=s.levels[i.property].errors*1e3+s.levels[i.property].warnings,n=t.levels[i.property].errors*1e3+t.levels[i.property].warnings),o<n?i.direction==="asc"?-1:1:o>n?i.direction==="asc"?1:-1:0}),statsByTeam:e}},[u,c.levelNames,i.direction,i.property,y]),F=p(()=>Object.values(I).sort((e,r)=>r.levels[v].apis-e.levels[v].apis).filter(e=>e.levels[v].apis>0),[I]);return{apis:u,summary:z,problemsByStatus:O,totalProblems:R,problemsByRule:V,sortedStatsByTeam:x,handleSortRulesTeams:W,nonConformantByTeam:F,filterTerm:M,setFilterTerm:D,groups:N,filters:E,scorecardInfo:c,catalogConfig:k,hasTeam:P,hasPublishedAt:A,teamLabel:T,teamProperty:f}}export{ee as useData};
@@ -5,7 +5,7 @@ import d from"picomatch";import{dirname as T,resolve as $}from"node:path";import
5
5
  `),s.details&&t.push(`${s.details}
6
6
 
7
7
  `),s.sections.forEach(o=>{if(!o.llmstxts.length){g.warn(`llms.txt: No links found for section "${o.title}". Please check the includeFiles/excludeFiles patterns.`);return}t.push(`## ${o.title}
8
- `),o.description?t.push(`${o.description.replace(/\n+$/,"")}
8
+ `),o.description?t.push(`${o.description.replace(/(?<!\n)\n+$/,"")}
9
9
 
10
10
  `):t.push(`
11
11
  `),o.llmstxts.forEach(c=>{t.push(` - ${M({title:c.title,description:c.description,slug:I(c.slug),siteUrl:l})}`)}),t.push(`
@@ -1,3 +1,7 @@
1
- import{writeFileSync as tt}from"node:fs";import*as u from"path";import{removeMarkdocTags as et}from"../../../markdoc/helpers/remove-markdoc-tags.js";import{withoutHash as ot}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as rt,CONFIG_FILE_NAME as K}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as at}from"../../constants/common.js";import{findDeepFirst as M}from"../../../utils/tree/find-deep-first.js";import{isDefined as X}from"../../../utils/guards/is-defined.js";import{partition as it}from"../../../utils/array/partition.js";import{collectPropValueDeep as N}from"../../../utils/tree/collect-prop-value-deep.js";import{envConfig as nt}from"../../config/env-config.js";import{isLocalLink as st}from"../../../utils/path/is-local-link.js";import{normalizeRouteSlug as Y}from"../../../utils/path/normalize-route-slug.js";import{slash as lt}from"../../../utils/path/slash.js";import{parsePathVersions as ct}from"../../../utils/path/parse-path-versions.js";import{reporter as k}from"../../tools/notifiers/reporter.js";import{logger as B}from"../../tools/notifiers/logger.js";import{sha1 as ft}from"../../utils/crypto/sha1.js";import{collectItemsLinkedToSidebars as dt,resolveItems as J}from"../nav-utils.js";import{getExcludedFromLinkCheckerPatterns as ut,getSidebarReferences as mt,hasCircularDependency as gt}from"./utils.js";import{getLocaleFromRelativePath as pt}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as ht}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as St}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as yt}from"../../../cli/telemetry/helpers/trace-step.js";import{isPathIgnored as Ft}from"../../utils/paths.js";const It=180,bt=170,Dt=10;async function Jt({contentDir:f}){return{id:"sidebars",async afterRoutesCreated(o,i){await yt("com.redocly.build.plugin.sidebars",async()=>{const{cache:p,fs:d}=i,b=o.getConfig(),D=new Map,P=new Set,x=[E,...d.localeFolders],$=o.getGlobalData()[St]||{},j=new Map;let R=d.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!Ft(t,b.ignore??[])&&t);const G=await mt(i,f,R),Q=it(R.filter(t=>!G.has(t)),t=>{const l=ct(t);return l?`@versioned/${l.versionFolderPath}\0${l.filePathInVersion}`:t}),_=ut(b),Z=await dt(b?.navbar,o,i,{navFile:K,excludedFromLinkCheckerPatterns:_});let C;const T=gt(G);T&&Array.isArray(T)&&await k.panicOnBuildContentError(`Sidebar references have circular dependency. Please check your sidebar files.
2
- Circular dependency chain: ${T.reverse().join(" -> ")}
3
- `);for(const t of Q){const l=(await Promise.all(t.map(async n=>{const e=(await p.load(n,"yaml")).data;if(!Array.isArray(e)){await k.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',n,d,n,typeof e);return}return{items:e,sidebarRelativePath:n,locale:pt(n)}}))).filter(X),a=(await A(l))?.firstLink;C||(C=a)}const H=Object.entries(b?.catalogClassic??{});for(const t of x){for(const[e,c]of H)await z(e,c,t);const l={},a=new Set,n=o.getAllRoutesForLocale(t);for(const e of n)if(W(e)&&e.fsPath&&!a.has(e.fsPath)){a.add(e.fsPath);let s=u.posix.dirname(e.fsPath);const h=u.parse(s).root;do l[s]=(l[s]||0)+1,s=u.dirname(s);while(s&&s!="."&&h!=s)}for(const e of n){if(D.has(e.slug))continue;const c=W(e),s=u.dirname(e.fsPath),h=l[s]===1,m=vt(e.baseSlug||e.slug);c&&h?await A([{items:[{directory:s}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}]):e.getSidebar!==void 0&&await A([{items:[{page:e.fsPath}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}])}for(const[e,c]of H)await z(e,c,t,!0)}if(R.length===0)for(const t of x){B.verbose("Creating default sidebar");const l=t===E,a=`sidebars.yaml${l?"":"_"+t}`,n=l?"":`${d.localizationFolder}/${t}`,e=(await A([{items:[{directory:`./${n}`}],sidebarRelativePath:a,locale:t,ignoredRoutes:P}]))?.firstLink;C||(C=e)}if(!o.getRouteBySlug("/")&&!o.getConfig().redirects?.["/"]){const l=o.getAllRoutes().find(n=>!ht(n.slug)),a=C?C.link:l?.baseSlug??null;if(a){const n=ot(a);o.addRedirect("/",{to:n,type:302}),B.info("Creating default redirect for index page => %s",n)}}const U=nt.REDOCLY_METADATA_OUTPUT_FOLDER;U&&(B.info("Writing catalog data..."),tt(u.join(U,at),JSON.stringify(Object.fromEntries(j.entries()))));function W(t){return P.has(t.slug)||$[t.fsPath]}async function A(t){if(t.length===0)return;const a=(await Promise.all(t.map(async({items:m,locale:I,sidebarRelativePath:g,ignoredRoutes:L})=>{const r=await J(m,u.dirname(u.join(f,g)),o,i,{locale:I,ignoredRoutes:L,navFile:g,excludedFromLinkCheckerPatterns:_});if(!r){await k.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",g);return}return r}))).flat().filter(X),n=N(a,"routeSlug"),e=t[0].sidebarRelativePath,c=q(e),s=new Set;for(const m of n){const I=o.getRouteBySlug(m)?.fsPath??"",g=$[I];g&&(Array.from(s).find(r=>r.key===g.key&&r.version===g.version)||s.add(g)),o.addRouteSharedData(m,"sidebar",c),D.set(Y(m),a)}const h=s.size===1?Array.from(s)[0]:void 0;return await o.createSharedData(c,{relatedNavbarItem:Z?.get(e),items:a,catalogEntity:h?{key:h.key,version:h.version}:void 0}),{firstLink:M(a,m=>!!m.link),resolved:a}}async function z(t,l,a,n=!1){const e=structuredClone(l);a&&a!==E&&e.items.forEach(r=>{r.directory=u.posix.join(d.localizationFolder||"",a,r.directory||"")});let c=await J(e.items,f,o,i,{groupCustomSidebars:!0,locale:a,navFile:K,excludedFromLinkCheckerPatterns:_});if(!c){await k.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}Ct(c);const s=a===E?"":"/"+a.toLowerCase(),h=a===E?"":`-${a}`,m=Y(u.posix.join(s,e.slug));if(n)for(const r of c){const S=M(r.items||[],F=>!!F.routeSlug);if(!S?.routeSlug)continue;const y=D.get(S.routeSlug);if(!y)continue;const O=N(y,"routeSlug"),w="current-catalog-info-"+r.routeSlug+h,v={catalog:{label:e.title,titleTranslationKey:e.titleTranslationKey,link:m,icon:e?.icon},item:{label:r.metadata?.title,link:r.link,icon:r.icon}};await o.createSharedData(w,v);for(const F of O)o.addRouteSharedData(F,"current-catalog-info",w),P.add(F);const V=M(y,F=>!!F.link&&!F.external&&st(F.link)&&(!r.version||F.version===r.version));V&&(r.sidebar=[{...V,items:void 0}])}const I={},g=new Set;for(const r of c){if(!(r.routeSlug||r.sidebar?.[0]?.routeSlug)||!r.fsPath||g.has(r.fsPath))continue;g.add(r.fsPath);const y=u.dirname(r.fsPath);I[y]=(I[y]||0)+1}if(n){const r=await o.createSharedData("catalog-"+t+h,c.flatMap(S=>{const y=u.dirname(S.fsPath??""),O=I[y]===1,w=v=>({...v,fsPath:O?y:v.fsPath??""});return S.type==="group"&&S.items?.every(v=>v.type==="group")?(S.items||[]).map(w):w(S)}));o.addRouteSharedData(m,"catalog",r),Pt(a,c,j,I)}const L=N(c,"routeSlug");for(const r of L)P.add(r)}})}}}function Pt(f,o,i,p){if(f===E)for(const d of o){const b=d.routeSlug||d.sidebar?.[0]?.routeSlug;if(!b||!d.fsPath)continue;const D=u.dirname(d.fsPath),P=p[D]===1;i.set(b,{rootFileFsPath:d.fsPath,fsPath:P?D:d.fsPath,metadata:d.metadata||{},title:d.metadata?.title||d.label||"Untitled",version:d.version||"latest"})}}function Ct(f){const o=i=>{typeof i.metadata?.description=="string"&&(i.metadata={...i.metadata,description:et(i.metadata.description)})};for(const i of f)if(i.routeSlug)o(i);else for(const p of i.items||[])o(p)}function q(f){return rt+lt(f)}async function qt(f,o,i){const p=u.posix.join(u.dirname(f),o);return await i.exists(p)?q(p):(await k.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",f,i,f,o),null)}function vt(f){const o=f.replaceAll("/","_");if(o.length>It){const i=o.slice(0,bt),p=ft(f).slice(0,Dt).replaceAll("/","_");return i+p}else return o}export{qt as resolveSidebarId,Jt as sidebarsPlugin,Ct as stripMarkdocFromDescriptions};
1
+ import{writeFileSync as at}from"node:fs";import*as g from"path";import{removeMarkdocTags as nt}from"../../../markdoc/helpers/remove-markdoc-tags.js";import{withoutHash as it}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as st,CONFIG_FILE_NAME as Y}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as lt}from"../../constants/common.js";import{findDeepFirst as B}from"../../../utils/tree/find-deep-first.js";import{isDefined as M}from"../../../utils/guards/is-defined.js";import{partition as ct}from"../../../utils/array/partition.js";import{collectPropValueDeep as N}from"../../../utils/tree/collect-prop-value-deep.js";import{envConfig as ft}from"../../config/env-config.js";import{isLocalLink as ut}from"../../../utils/path/is-local-link.js";import{normalizeRouteSlug as J}from"../../../utils/path/normalize-route-slug.js";import{slash as dt}from"../../../utils/path/slash.js";import{parsePathVersions as mt}from"../../../utils/path/parse-path-versions.js";import{reporter as I}from"../../tools/notifiers/reporter.js";import{logger as $}from"../../tools/notifiers/logger.js";import{sha1 as gt}from"../../utils/crypto/sha1.js";import{getCatalogSharedDataId as pt}from"../../utils/catalog-classic/get-catalog-shared-data-id.js";import{collectItemsLinkedToSidebars as ht,resolveItems as q}from"../nav-utils.js";import{getExcludedFromLinkCheckerPatterns as yt,getSidebarReferences as St,hasCircularDependency as bt}from"./utils.js";import{collectTabRoutes as vt,findDuplicateRoutes as It,hasTabs as Dt,resolveTabs as Ft,tabsAsGroups as Ct,validateTabs as wt}from"./tabs.js";import{getLocaleFromRelativePath as Pt}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as Et}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as Rt}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as At}from"../../../cli/telemetry/helpers/trace-step.js";import{isPathIgnored as kt}from"../../utils/paths.js";const Lt=180,Tt=170,_t=10;async function ce({contentDir:u}){return{id:"sidebars",async afterRoutesCreated(a,c){await At("com.redocly.build.plugin.sidebars",async()=>{const{cache:h,fs:d}=c,D=a.getConfig(),F=new Map,C=new Set,G=[E,...d.localeFolders],x=a.getGlobalData()[Rt]||{},j=new Map;let L=d.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!kt(t,D.ignore??[])&&t);const H=await St(c,u,L),Z=ct(L.filter(t=>!H.has(t)),t=>{const i=mt(t);return i?`@versioned/${i.versionFolderPath}\0${i.filePathInVersion}`:t}),T=yt(D),tt=await ht(D?.navbar,a,c,{navFile:Y,excludedFromLinkCheckerPatterns:T});let w;const _=bt(H);_&&Array.isArray(_)&&await I.panicOnBuildContentError(`Sidebar references have circular dependency. Please check your sidebar files.
2
+ Circular dependency chain: ${_.reverse().join(" -> ")}
3
+ `);for(const t of Z){const i=(await Promise.all(t.map(async r=>{const e=(await h.load(r,"yaml")).data;if(!Array.isArray(e)){await I.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',r,d,r,typeof e);return}return{items:e,sidebarRelativePath:r,locale:Pt(r)}}))).filter(M),o=(await A(i))?.firstLink;w||(w=o)}const U=Object.entries(D?.catalogClassic??{});for(const t of G){for(const[e,s]of U)await K(e,s,t);const i={},o=new Set,r=a.getAllRoutesForLocale(t);for(const e of r)if(z(e)&&e.fsPath&&!o.has(e.fsPath)){o.add(e.fsPath);let l=g.posix.dirname(e.fsPath);const f=g.parse(l).root;do i[l]=(i[l]||0)+1,l=g.dirname(l);while(l&&l!="."&&f!=l)}for(const e of r){if(F.has(e.slug))continue;const s=z(e),l=g.dirname(e.fsPath),f=i[l]===1,m=Mt(e.baseSlug||e.slug);s&&f?await A([{items:[{directory:l}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}]):e.getSidebar!==void 0&&await A([{items:[{page:e.fsPath}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}])}for(const[e,s]of U)await K(e,s,t,!0)}if(L.length===0)for(const t of G){$.verbose("Creating default sidebar");const i=t===E,o=`sidebars.yaml${i?"":"_"+t}`,r=i?"":`${d.localizationFolder}/${t}`,e=(await A([{items:[{directory:`./${r}`}],sidebarRelativePath:o,locale:t,ignoredRoutes:C}]))?.firstLink;w||(w=e)}if(!a.getRouteBySlug("/")&&!a.getConfig().redirects?.["/"]){const i=a.getAllRoutes().find(r=>!Et(r.slug)),o=w?w.link:i?.baseSlug??null;if(o){const r=it(o);a.addRedirect("/",{to:r,type:302}),$.info("Creating default redirect for index page => %s",r)}}const W=ft.REDOCLY_METADATA_OUTPUT_FOLDER;W&&($.info("Writing catalog data..."),at(g.join(W,lt),JSON.stringify(Object.fromEntries(j.entries()))));function z(t){return C.has(t.slug)||x[t.fsPath]}async function A(t){if(t.length===0)return;const i=t.map(({items:e})=>Dt(e)),o=i.some(Boolean);if(o&&!i.every(Boolean)){await I.panicOnBuildContentError("Versioned copies of %rp must either all use navigation tabs or none of them",t[0].sidebarRelativePath);return}const r=o?await ot(t):await et(t);if(r)return rt(t[0].sidebarRelativePath,r)}async function et(t){const o=(await Promise.all(t.map(async({items:r,locale:e,sidebarRelativePath:s,ignoredRoutes:l})=>{const{fromDir:f,resolveOptions:m}=V(s,e,l),p=await q(r,f,a,c,m);if(!p){await I.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",s);return}return p}))).flat().filter(M);return{routeOwners:N(o,"routeSlug").map(r=>({routeSlug:r,items:o})),sharedData:{items:o},navItems:o}}async function ot(t){const i=t[0].sidebarRelativePath,r=(await Promise.all(t.map(async({items:l,locale:f,sidebarRelativePath:m,ignoredRoutes:p})=>{const y=wt(l);if(y.length){await I.panicOnBuildContentError(`Invalid navigation tabs in %rp:
4
+ - ${y.join(`
5
+ - `)}`,m);return}const{fromDir:k,resolveOptions:n}=V(m,f,p);return Ft(l,k,a,c,n)}))).flat().filter(M),e=vt(r),s=It(e);if(s.length){await I.panicOnBuildContentError(`Navigation tabs conflict in %rp. A route can belong to one tab only:
6
+ - ${s.map(({routeSlug:l,owners:f})=>`${l} is claimed by ${f.map(m=>`"${m}"`).join(" and ")}`).join(`
7
+ - `)}`,i);return}return{routeOwners:e,sharedData:{items:[],tabs:r},navItems:Ct(r)}}function V(t,i,o){return{fromDir:g.dirname(g.join(u,t)),resolveOptions:{locale:i,ignoredRoutes:o,navFile:t,excludedFromLinkCheckerPatterns:T}}}async function rt(t,{routeOwners:i,sharedData:o,navItems:r}){const e=Q(t),s=new Set;for(const{routeSlug:f,items:m}of i){const p=a.getRouteBySlug(f)?.fsPath??"",y=x[p];y&&(Array.from(s).find(n=>n.key===y.key&&n.version===y.version)||s.add(y)),a.addRouteSharedData(f,"sidebar",e),F.set(J(f),m)}const l=s.size===1?Array.from(s)[0]:void 0;return await a.createSharedData(e,{relatedNavbarItem:tt?.get(t),...o,catalogEntity:l?{key:l.key,version:l.version}:void 0}),{firstLink:B(r,f=>!!f.link),resolved:r}}async function K(t,i,o,r=!1){const e=structuredClone(i);o&&o!==E&&e.items.forEach(n=>{n.directory=g.posix.join(d.localizationFolder||"",o,n.directory||"")});let s=await q(e.items,u,a,c,{groupCustomSidebars:!0,locale:o,navFile:Y,excludedFromLinkCheckerPatterns:T});if(!s){await I.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}Bt(s);const l=o===E?"":"/"+o.toLowerCase(),f=o===E?"":`-${o}`,m=J(g.posix.join(l,e.slug));if(r)for(const n of s){const S=B(n.items||[],v=>!!v.routeSlug);if(!S?.routeSlug)continue;const b=F.get(S.routeSlug);if(!b)continue;const O=N(b,"routeSlug"),R="current-catalog-info-"+n.routeSlug+f,P={catalog:{label:e.title,titleTranslationKey:e.titleTranslationKey,link:m,icon:e?.icon},item:{label:n.metadata?.title,link:n.link,icon:n.icon}};await a.createSharedData(R,P);for(const v of O)a.addRouteSharedData(v,"current-catalog-info",R),C.add(v);const X=B(b,v=>!!v.link&&!v.external&&ut(v.link)&&(!n.version||v.version===n.version));X&&(n.sidebar=[{...X,items:void 0}])}const p={},y=new Set;for(const n of s){if(!(n.routeSlug||n.sidebar?.[0]?.routeSlug)||!n.fsPath||y.has(n.fsPath))continue;y.add(n.fsPath);const b=g.dirname(n.fsPath);p[b]=(p[b]||0)+1}if(r){const n=await a.createSharedData(pt(t,f),s.flatMap(S=>{const b=g.dirname(S.fsPath??""),O=p[b]===1,R=P=>({...P,fsPath:O?b:P.fsPath??""});return S.type==="group"&&S.items?.every(P=>P.type==="group")?(S.items||[]).map(R):R(S)}));a.addRouteSharedData(m,"catalog",n),Ot(o,s,j,p)}const k=N(s,"routeSlug");for(const n of k)C.add(n)}})}}}function Ot(u,a,c,h){if(u===E)for(const d of a){const D=d.routeSlug||d.sidebar?.[0]?.routeSlug;if(!D||!d.fsPath)continue;const F=g.dirname(d.fsPath),C=h[F]===1;c.set(D,{rootFileFsPath:d.fsPath,fsPath:C?F:d.fsPath,metadata:d.metadata||{},title:d.metadata?.title||d.label||"Untitled",version:d.version||"latest"})}}function Bt(u){const a=c=>{typeof c.metadata?.description=="string"&&(c.metadata={...c.metadata,description:nt(c.metadata.description)})};for(const c of u)if(c.routeSlug)a(c);else for(const h of c.items||[])a(h)}function Q(u){return st+dt(u)}async function fe(u,a,c){const h=g.posix.join(g.dirname(u),a);return await c.exists(h)?Q(h):(await I.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",u,c,u,a),null)}function Mt(u){const a=u.replaceAll("/","_");if(a.length>Lt){const c=a.slice(0,Tt),h=gt(u).slice(0,_t).replaceAll("/","_");return c+h}else return a}export{fe as resolveSidebarId,ce as sidebarsPlugin,Bt as stripMarkdocFromDescriptions};
@@ -0,0 +1,19 @@
1
+ import type { NavItem, ResolvedNavItem, ResolvedTab } from '@redocly/config';
2
+ import type { LifecycleContext, ResolveItemsOptions } from '../../types';
3
+ import type { ResolveLinkContext } from '../nav-utils';
4
+ export type TabRoute = {
5
+ routeSlug: string;
6
+ owner: string;
7
+ items: ResolvedNavItem[];
8
+ };
9
+ export declare function hasTabs(items: NavItem[] | undefined): boolean;
10
+ export declare function makeTabId(index: number, label: string): string;
11
+ export declare function validateTabs(sidebarItems: NavItem[]): string[];
12
+ export declare function resolveTabs(items: NavItem[], fromDir: string, actions: ResolveLinkContext, context: LifecycleContext, options: ResolveItemsOptions): Promise<ResolvedTab[]>;
13
+ export declare function collectTabRoutes(tabs: ResolvedTab[]): TabRoute[];
14
+ export declare function findDuplicateRoutes(routes: TabRoute[]): Array<{
15
+ routeSlug: string;
16
+ owners: string[];
17
+ }>;
18
+ export declare function tabsAsGroups(tabs: ResolvedTab[]): ResolvedNavItem[];
19
+ //# sourceMappingURL=tabs.d.ts.map
@@ -0,0 +1 @@
1
+ import{REDOCLY_ROUTE_RBAC as p,REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{collectPropValueDeep as v}from"../../../utils/tree/collect-prop-value-deep.js";import{isDefined as T}from"../../../utils/guards/is-defined.js";import{resolveItem as $,resolveItems as w}from"../nav-utils.js";function F(n){return Array.isArray(n)&&n.some(b)}function I(n,e){const a=e.normalize("NFKD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");return`${n}-${a||"tab"}`}function x(n){const e=[],a=n.filter(o=>!b(o));a.length&&e.push(`when a sidebar uses tabs, every top-level entry must be a tab; found ${a.length} other entr${a.length===1?"y":"ies"}: ${JSON.stringify(a)}`);for(const{tab:o,page:i,menu:r,items:f,$ref:t,directory:l,group:s,href:m}of n.filter(b)){const u=`tab "${o}"`;if(r!==void 0&&!Array.isArray(r)){e.push(`${u} "menu" must be a list of entries`);continue}i?.includes("#")&&e.push(`${u} page must not contain a heading anchor`),r&&f?e.push(`${u} cannot have both "menu" and "items"`):r&&i?e.push(`${u} has "menu" and cannot also have "page"`):!r&&!i&&e.push(`${u} needs "page" or "menu"`),(t||l||s||m)&&e.push(`${u} accepts only "page", "items", "menu" and "rbac"; move "$ref"/"directory"/"group"/"href" into "items"`),r?.length===0&&e.push(`${u} has an empty "menu"`),r?.forEach((d,y)=>{const h=`menu entry ${y+1} of ${u}`;d?.page||e.push(`${h} needs "page"`),d?.page?.includes("#")&&e.push(`${h} page must not contain a heading anchor`)});const g=[...r??[],...f??[]];v(g,"tab").length&&e.push(`${u} contains a nested "tab"; tabs are only allowed at the top level`),v(g,"menu").length&&e.push(`${u} contains a nested "menu"; "menu" is only allowed directly on a tab`)}return e}async function C(n,e,a,o,i){const r=[];for(const[f,t]of n.filter(b).entries()){const l=I(f,t.tab);if(t.menu){const g=(await Promise.all(t.menu.map((y,h)=>A(y,l,h,e,a,o,i)))).filter(T),d=t.icon?S(await $({group:t.tab,icon:t.icon,items:[]},e,a,o,i)):void 0;r.push({type:"tab",tabId:l,label:t.tab,labelTranslationKey:t.tabTranslationKey,menu:g,icon:d?.icon,srcSet:d?.srcSet,[c]:t.rbac});continue}const s=S(await $({group:t.tab,rbac:t.rbac,page:t.page,icon:t.icon,items:[]},e,a,o,i)),m=s?.routeSlug?a.getRouteBySlug(s.routeSlug):void 0,u=await w(t.items,e,a,o,i)??[];r.push({type:"tab",tabId:l,label:t.tab,labelTranslationKey:t.tabTranslationKey,link:s?.link,routeSlug:s?.routeSlug,fsPath:s?.fsPath,icon:s?.icon,srcSet:s?.srcSet,items:[...s?.items??[],...u],...k(m?.versions,s),[c]:t.rbac??s?.[c],[p]:s?.[p]})}return r}function M(n){return n.flatMap(e=>e.menu?e.menu.flatMap(a=>R(`${e.label} > ${a.label}`,a.routeSlug,a.items)):R(e.label,e.routeSlug,e.items??[]))}function N(n){const e=new Map;for(const{routeSlug:a,owner:o}of n){const i=a.split("#")[0],r=e.get(i)??new Set;r.add(o),e.set(i,r)}return[...e.entries()].filter(([,a])=>a.size>1).map(([a,o])=>({routeSlug:a,owners:[...o]}))}function O(n){return n.map(e=>({type:"group",label:e.label,labelTranslationKey:e.labelTranslationKey,link:e.link,routeSlug:e.routeSlug,fsPath:e.fsPath,version:e.version,isDefault:e.isDefault,versionFolderId:e.versionFolderId,items:e.menu??e.items??[],[c]:e[c],[p]:e[p]}))}function b(n){return typeof n?.tab=="string"}async function A(n,e,a,o,i,r,f){const t=S(await $({...n,group:n.label||n.page,items:[]},o,i,r,f));if(!t?.link)return;const l=t.routeSlug?i.getRouteBySlug(t.routeSlug):void 0,s=n.label||await l?.getNavText?.()||t.link,m=await w(n.items,o,i,r,f)??[],u=[...t.items??[],...m];return{type:"link",tabId:`${e}/${I(a,s)}`,label:s,labelTranslationKey:n.labelTranslationKey,link:t.link,routeSlug:t.routeSlug,fsPath:t.fsPath,metadata:t.metadata,icon:t.icon,srcSet:t.srcSet,badges:t.badges,items:u,...k(l?.versions,t),[c]:n.rbac??l?.[c]??t[c],[p]:t[p]}}function S(n){const e=Array.isArray(n)?n[0]:n;return e?.type==="group"?e:void 0}function k(n,e){const a=n?.find(o=>o.active);return a?{version:a.version,isDefault:a.default,versionFolderId:a.folderId}:e?.version===void 0?{}:{version:e.version,isDefault:e.isDefault,versionFolderId:e.versionFolderId}}function R(n,e,a){return[e,...v(a,"routeSlug")].filter(T).map(o=>({routeSlug:o,owner:n,items:a}))}export{M as collectTabRoutes,N as findDuplicateRoutes,F as hasTabs,I as makeTabId,C as resolveTabs,O as tabsAsGroups,x as validateTabs};
@@ -1 +1 @@
1
- import{DEFAULT_SSO_IDP_TITLE as A}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as I}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as C}from"../../tools/notifiers/logger.js";const O="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function S(T){return{id:"sso",async processContent(i){await I("com.redocly.build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&C.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=O,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n};t&&(p.login_idps=t);const m={oidc:{title:A,type:"OIDC",configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid","offline"],authorizationRequestCustomParams:p,audience:"{{ process.env.ORGANIZATION_ID }}",introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{S as ssoPlugin};
1
+ import{AuthProviderType as A}from"@redocly/config";import{DEFAULT_SSO_IDP_TITLE as I}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as C}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as O}from"../../tools/notifiers/logger.js";const T="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function U(h){return{id:"sso",async processContent(i){await C("com.redocly.build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&O.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=T,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n};t&&(p.login_idps=t);const m={oidc:{title:I,type:A.OIDC,configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid","offline"],authorizationRequestCustomParams:p,audience:["{{ process.env.ORGANIZATION_ID }}"],introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{U as ssoPlugin};
@@ -1 +1 @@
1
- import A from"@markdoc/markdoc";import{parseAndResolveMarkdoc as T}from"./plugins/markdown/compiler.js";import{getPathnameForLocale as M}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as O,MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as k}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{isObject as L}from"../utils/guards/is-object.js";import{mapObject as H}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as D}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as G}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as B}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{SandboxContext as I}from"./utils/sandbox-context.js";import{writeSharedData as N}from"./utils/index.js";import{renderComponents as V}from"./ssr/render.js";import{readStaticData as q,writeStaticData as U}from"./utils/static-data.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as v}from"./entitlements/entitlements-provider.js";import{isL10nPath as x}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as K}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as W}from"./utils/redirects/find-redirect.js";import{followRedirectChain as $}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as z}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Y}from"../cli/telemetry/helpers/trace-step.js";const E={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},P="PLAN_GATES",Z=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Me="userDefinedApiFunctions";class b{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;skills=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#o=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#i;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#n;userCodeReady;#s=Promise.resolve();#c;#l=Promise.resolve();#d;#u=Promise.resolve();#h;#e=!1;#r=0;#f=0;#a=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:r}){this.#i=s,this.outdir=e,this.serverMode=t,this.serverOutDir=r,I.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(a=>{this.#n=a})}on(e,s){const t=this.listeners.get(e);t?t.add(s):this.listeners.set(e,new Set([s]))}queueEvent=(e,s,...t)=>{this.#a.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const r of this.listeners.get(e)||new Set)s?r(s,...t):r(...t)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#l,this.#u])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#a.values())this.runListeners(...e);this.#a.clear()}startEsbuildRun(){this.#l=new Promise(e=>{this.#d=e})}finishEsbuildRun(){this.#d?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#u=new Promise(e=>{this.#h=e}))}noteRequestHandlersEntryBuildStart(){this.#f=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#f||(this.#e=!1,this.#h?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#i}markUserCodeReady(){this.#n?.(!0)}async reloadMarkdocOptions(){await Y("com.redocly.build.reloadMarkdocOptions",async()=>{const e=v.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!0));this.#o={...s,tags:t}})}get markdocOptions(){return{...this.#o,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const s=this.globalData,t={...this.globalData,...e};this.globalData=t,JSON.stringify(t)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,t)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:r})=>{const{data:{info:a,ast:i},compoundHash:l}=await T(e,this.markdocOptions,{actions:this,context:s},r);for(const o of a.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,o,o);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(o),this.sharedDataDeps.set(n,c)}}for(const o of a.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(o),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(o),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&a.partials?.length)for(const o of t.routeSlugs){const n=this.routesPartials.get(o)||[];for(const c of a.partials)n.includes(c)||n.push(c);this.routesPartials.set(o,n)}return{info:a,ast:i,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);for(const l of s)for(const o in this.replacedEnvVars)if(o===l||o.startsWith(`${l}:`)){const n=o.split(":"),{error:c,value:d}=y(e,n);(c||d!==this.replacedEnvVars[o].replaced)&&delete this.replacedEnvVars[o]}const{resolvedObj:t,unsetEnvVars:r,replacedValues:a}=J(e);for(const l of r)this.unsetEnvVars.add(l);Object.assign(this.replacedEnvVars,a);const i=t.seo?.siteUrl?.trim();i&&(t.seo={...t.seo,siteUrl:URL.canParse(i)?new URL(i).origin:D(i)}),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!v.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const i=h(e).toLowerCase();this.config.redirects[i]=s;const{trackOriginalSource:l=!0}=t,o=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(o)&&!o.includes(i)&&o.push(i),i.endsWith("*")&&z(this.config.wildcardRedirectsTree,i)};getRedirect=e=>{const s=h(e).toLowerCase(),t=W(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(S(t.to)){const r=h(t.to).toLowerCase();if(!r.endsWith("*")&&$(r,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:t.to,type:t.type}};createSharedData=async(e,s,t)=>{if(t&&this.#t[e]===t)return e;const r=JSON.stringify(s),a=t??G(r);return this.#t[e]===a||(this.#t[e]=a,await N(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const r=D(e),a=this.routesSharedData.get(r)||{};a[s]=t,this.routesSharedData.set(r,a),u.verbose(`Adding shared data to ${e}, ${s}, ${t}`)};getRouteSharedDataByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=e=>{const s=this.getGlobalConfig(m)||{},t=this.routesPartials.get(e);if(!t||t.length===0)return{};const r=this.getGlobalConfig(k)||{},a=new Set(t),i=Array.from(t);for(let o=0;o<i.length;o++){const n=i[o],c=r[n]?.partials??[];for(const d of c)a.has(d)||(a.add(d),i.push(d))}const l={};for(const o of a)s[o]&&(l[o]=s[o]);return l};addRoute=e=>{const t={...K(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(a=>({code:a,name:a}));for(const a of r){const i=M(e,g,a.code,r);this.addRouteSharedData(i,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s){const r=this.mcpToolHandlers.get(t.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',t.name,e,r.importPath),this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const s of e){const t=this.mcpToolHandlers.get(s);t&&this.mcpToolHandlers.set(s,{...t,hasAvailabilityGate:!0})}};addSkills=e=>{for(const s of e)this.skills.set(s.slug,s),u.verbose("Discovered skill %s",s.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const s of e)this.mcpToolHandlers.delete(s)};addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(i=>i.name.toLowerCase())),a=[...(this.config.responseHeaders[e]??[]).filter(i=>!t.has(i.name.toLowerCase())),...s];this.config.responseHeaders[e]=a};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,r=this.getRedirect(e);return t&&r?this.routesBySlug.get(h(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!S(s.to))return!0;const t=h(s.to);return this.routesBySlug.has(t)};getRoutesByTemplateId=e=>this.newRoutes.filter(s=>s.templateId===e);getAllRoutesForLocale=(e=g)=>{const s=Array.from(this.routesBySlug.values()),t=e.toLowerCase();return s.filter(r=>e===g?!x(r.fsPath):r.slug.startsWith(`/${t}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,s)=>(this.templates.set(e,s),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,s)=>(this.apiRoutesRequestHandlers.set(e,s),e);clearRequestHandlersByPrefix=e=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(e)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(e,s)=>(this.serverPropsGetters.set(e,s),e);registerPagePropsGetter=(e,s)=>{this.pagePropsGetters.set(e,s)};async writeRouteStaticData(e,s){const t=await this.resolveRouteStaticData(e,s,!1);t&&U(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return q(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},a=await e.getStaticData?.(e,r)||{},i=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>i.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const o=this.getGlobalConfig("seo"),n=a?.frontmatter||{};return{...a,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...a.props,dynamicMarkdocComponents:Array.from(i),metadata:{...a?.props?.metadata,...e.metadata},seo:{title:O,...o,...a.props?.seo,siteUrl:o?.siteUrl},compilationErrors:this.compilationErrors},lastModified:t||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,s){if(!e?.length)return;const t=typeof e[0]=="string"?e.join(""):V(e);t&&(s==="head"?this.ssr.headTags.push(t):s==="preBody"?this.ssr.preBodyTags.push(t):this.ssr.postBodyTags.push(t))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,r]of Object.entries(E))switch(r){case"map":{const a=Array.from(this[t].entries());e.push([t,a]);break}case"object":if(t==="config"){e.push([t,await this.getConfigWithEnvPlaceholders()]);break}e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[P]=_.PLAN_GATES,s}static fromJson(e,s){const t=new b(s);for(const[a,i]of Object.entries(E))switch(i){case"map":t[a]=new Map(e[a]);break;case"object":if(a==="config"){t.setGlobalConfig(e[a]);break}t[a]=e[a];break;default:throw new Error("Invalid format")}t.config[m]=Q(t.config[m]||{});const r=e[P];return r&&B("PLAN_GATES",r),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],r=s.split(":"),a=r.pop(),{error:i,value:l}=y(e,r);if(i||!L(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[a]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Z.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await w.panicOnBuildContentError(s)}}function Q(C){return H(C,e=>A.Ast.fromJSON(JSON.stringify(e)))}export{b as Store,Me as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
1
+ import A from"@markdoc/markdoc";import{parseAndResolveMarkdoc as T}from"./plugins/markdown/compiler.js";import{getPathnameForLocale as M}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as O,MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as k}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{isObject as L}from"../utils/guards/is-object.js";import{mapObject as H}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as D}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as G}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as B}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{SandboxContext as I}from"./utils/sandbox-context.js";import{writeSharedData as N}from"./utils/index.js";import{renderComponents as V}from"./ssr/render.js";import{readStaticData as q,writeStaticData as U}from"./utils/static-data.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as v}from"./entitlements/entitlements-provider.js";import{isRouteReserved as x}from"./plugins/get-reserved-routes.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as J}from"./utils/globs.js";import{replaceEnvVariablesDeep as W}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as $}from"./utils/redirects/find-redirect.js";import{followRedirectChain as z}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as Y}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Z}from"../cli/telemetry/helpers/trace-step.js";const E={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map"},P="PLAN_GATES",Q=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],ke="userDefinedApiFunctions";class b{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;skills=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#a=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#i;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#n;userCodeReady;#s=Promise.resolve();#c;#l=Promise.resolve();#d;#u=Promise.resolve();#h;#e=!1;#r=0;#f=0;#o=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:r}){this.#i=s,this.outdir=e,this.serverMode=t,this.serverOutDir=r,I.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(o=>{this.#n=o})}on(e,s){const t=this.listeners.get(e);t?t.add(s):this.listeners.set(e,new Set([s]))}queueEvent=(e,s,...t)=>{this.#o.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const r of this.listeners.get(e)||new Set)s?r(s,...t):r(...t)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#l,this.#u])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#o.values())this.runListeners(...e);this.#o.clear()}startEsbuildRun(){this.#l=new Promise(e=>{this.#d=e})}finishEsbuildRun(){this.#d?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#u=new Promise(e=>{this.#h=e}))}noteRequestHandlersEntryBuildStart(){this.#f=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#f||(this.#e=!1,this.#h?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#i}markUserCodeReady(){this.#n?.(!0)}async reloadMarkdocOptions(){await Z("com.redocly.build.reloadMarkdocOptions",async()=>{const e=v.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!0));this.#a={...s,tags:t}})}get markdocOptions(){return{...this.#a,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const s=this.globalData,t={...this.globalData,...e};this.globalData=t,JSON.stringify(t)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,t)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:r})=>{const{data:{info:o,ast:i},compoundHash:l}=await T(e,this.markdocOptions,{actions:this,context:s},r);for(const a of o.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,a,a);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(a),this.sharedDataDeps.set(n,c)}}for(const a of o.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(a),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(a),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&o.partials?.length)for(const a of t.routeSlugs){const n=this.routesPartials.get(a)||[];for(const c of o.partials)n.includes(c)||n.push(c);this.routesPartials.set(a,n)}return{info:o,ast:i,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);for(const l of s)for(const a in this.replacedEnvVars)if(a===l||a.startsWith(`${l}:`)){const n=a.split(":"),{error:c,value:d}=y(e,n);(c||d!==this.replacedEnvVars[a].replaced)&&delete this.replacedEnvVars[a]}const{resolvedObj:t,unsetEnvVars:r,replacedValues:o}=W(e);for(const l of r)this.unsetEnvVars.add(l);Object.assign(this.replacedEnvVars,o);const i=t.seo?.siteUrl?.trim();i&&(t.seo={...t.seo,siteUrl:URL.canParse(i)?new URL(i).origin:D(i)}),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!v.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const i=h(e).toLowerCase();this.config.redirects[i]=s;const{trackOriginalSource:l=!0}=t,a=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(a)&&!a.includes(i)&&a.push(i),i.endsWith("*")&&Y(this.config.wildcardRedirectsTree,i)};getRedirect=e=>{const s=h(e).toLowerCase(),t=$(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(S(t.to)){const r=h(t.to).toLowerCase();if(!r.endsWith("*")&&z(r,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:t.to,type:t.type}};createSharedData=async(e,s,t)=>{if(t&&this.#t[e]===t)return e;const r=JSON.stringify(s),o=t??G(r);return this.#t[e]===o||(this.#t[e]=o,await N(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const r=D(e),o=this.routesSharedData.get(r)||{};o[s]=t,this.routesSharedData.set(r,o),u.verbose(`Adding shared data to ${e}, ${s}, ${t}`)};getRouteSharedDataByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=e=>{const s=this.getGlobalConfig(m)||{},t=this.routesPartials.get(e);if(!t||t.length===0)return{};const r=this.getGlobalConfig(k)||{},o=new Set(t),i=Array.from(t);for(let a=0;a<i.length;a++){const n=i[a],c=r[n]?.partials??[];for(const d of c)o.has(d)||(o.add(d),i.push(d))}const l={};for(const a of o)s[a]&&(l[a]=s[a]);return l};addRoute=e=>{const t={...J(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(o=>({code:o,name:o}));for(const o of r){const i=M(e,g,o.code,r);this.addRouteSharedData(i,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s){const r=this.mcpToolHandlers.get(t.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',t.name,e,r.importPath),this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const s of e){const t=this.mcpToolHandlers.get(s);t&&this.mcpToolHandlers.set(s,{...t,hasAvailabilityGate:!0})}};addSkills=e=>{for(const s of e)this.skills.set(s.slug,s),u.verbose("Discovered skill %s",s.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const s of e)this.mcpToolHandlers.delete(s)};addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(i=>i.name.toLowerCase())),o=[...(this.config.responseHeaders[e]??[]).filter(i=>!t.has(i.name.toLowerCase())),...s];this.config.responseHeaders[e]=o};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,r=this.getRedirect(e);return t&&r?this.routesBySlug.get(h(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e)||x(e,this.getConfig()))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!S(s.to))return!0;const t=h(s.to);return this.routesBySlug.has(t)};getRoutesByTemplateId=e=>this.newRoutes.filter(s=>s.templateId===e);getAllRoutesForLocale=(e=g)=>{const s=Array.from(this.routesBySlug.values()),t=e.toLowerCase();return s.filter(r=>e===g?!K(r.fsPath):r.slug.startsWith(`/${t}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,s)=>(this.templates.set(e,s),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,s)=>(this.apiRoutesRequestHandlers.set(e,s),e);clearRequestHandlersByPrefix=e=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(e)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(e,s)=>(this.serverPropsGetters.set(e,s),e);registerPagePropsGetter=(e,s)=>{this.pagePropsGetters.set(e,s)};async writeRouteStaticData(e,s){const t=await this.resolveRouteStaticData(e,s,!1);t&&U(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return q(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},o=await e.getStaticData?.(e,r)||{},i=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>i.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const a=this.getGlobalConfig("seo"),n=o?.frontmatter||{};return{...o,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...o.props,dynamicMarkdocComponents:Array.from(i),metadata:{...o?.props?.metadata,...e.metadata},seo:{title:O,...a,...o.props?.seo,siteUrl:a?.siteUrl},compilationErrors:this.compilationErrors},lastModified:t||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,s){if(!e?.length)return;const t=typeof e[0]=="string"?e.join(""):V(e);t&&(s==="head"?this.ssr.headTags.push(t):s==="preBody"?this.ssr.preBodyTags.push(t):this.ssr.postBodyTags.push(t))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,r]of Object.entries(E))switch(r){case"map":{const o=Array.from(this[t].entries());e.push([t,o]);break}case"object":if(t==="config"){e.push([t,await this.getConfigWithEnvPlaceholders()]);break}e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[P]=_.PLAN_GATES,s}static fromJson(e,s){const t=new b(s);for(const[o,i]of Object.entries(E))switch(i){case"map":t[o]=new Map(e[o]);break;case"object":if(o==="config"){t.setGlobalConfig(e[o]);break}t[o]=e[o];break;default:throw new Error("Invalid format")}t.config[m]=X(t.config[m]||{});const r=e[P];return r&&B("PLAN_GATES",r),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],r=s.split(":"),o=r.pop(),{error:i,value:l}=y(e,r);if(i||!L(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[o]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Q.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await w.panicOnBuildContentError(s)}}function X(C){return H(C,e=>A.Ast.fromJSON(JSON.stringify(e)))}export{b as Store,ke as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
@@ -1 +1 @@
1
- import{maskEmail as t}from"./mask-email.js";const o=e=>{const a=/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;return e.replace(a,r=>t(r))};export{o as maskSubject};
1
+ import{maskEmail as c}from"./mask-email.js";const r=/[a-zA-Z0-9._%+-]/,m=/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/,d=e=>{let o="",i=0,a=0;for(;a<e.length;){const n=e.indexOf("@",a);if(n===-1)break;let t=n;for(;t>i&&r.test(e.charAt(t-1));)t--;const s=t<n?m.exec(e.slice(n+1))?.[0]:void 0;if(!s){a=n+1;continue}const l=n+1+s.length;o+=e.slice(i,t)+c(e.slice(t,l)),i=l,a=l}return o+e.slice(i)};export{d as maskSubject};
@@ -1 +1 @@
1
- import{isString as m}from"../../../../../utils/string/is-string.js";const s={email:{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[email_removed]"},phone:{pattern:/(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})(?:\s?(?:ext|x|extension)\.?\s?(\d+))?/g,replacement:"[phone_removed]"},ssn:{pattern:/\b(?!000|666|9\d{2})\d{3}-?(?!00)\d{2}-?(?!0000)\d{4}\b/g,replacement:"[SSN_removed]"},creditCard:{pattern:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,replacement:"[credit_card_removed]"},address:{pattern:/\b\d+\s+[A-Za-z0-9\s,.-]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Lane|Ln|Drive|Dr|Court|Ct|Circle|Cir|Way|Place|Pl|Parkway|Pkwy|Terrace|Ter)\b/gi,replacement:"[address_removed]"},passport:{pattern:/\b[A-Z]{2}[0-9]{7}\b/g,replacement:"[passport_number_removed]"},driversLicense:{pattern:/\b[A-Z]{1,2}[0-9]{6,9}\b/g,replacement:"[driver_license_removed]"},zipCode:{pattern:/(?<!\d-)\b\d{5}(?:-\d{4})?\b(?!-\d)/g,replacement:"[zip_code_removed]"},bankAccount:{pattern:/\b\d{8,17}\b/g,replacement:"[bank_account_removed]"},dateOfBirth:{pattern:/\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12][0-9]|3[01])[-/](?:19|20)\d{2}\b/g,replacement:"[date_removed]"}};function l(n={}){const e={email:{enabled:!0,replacement:"[email_removed]"},phone:{enabled:!0,replacement:"[phone_removed]"},ssn:{enabled:!0,replacement:"[SSN_removed]"},creditCard:{enabled:!0,replacement:"[credit_card_removed]"},address:{enabled:!0,replacement:"[address_removed]"},passport:{enabled:!0,replacement:"[passport_number_removed]"},driversLicense:{enabled:!0,replacement:"[driver_license_removed]"},zipCode:{enabled:!0,replacement:"[zip_code_removed]"},bankAccount:{enabled:!0,replacement:"[bank_account_removed]"},dateOfBirth:{enabled:!0,replacement:"[date_removed]"}};for(const[r,t]of Object.entries(n))e[r]?e[r]={...e[r],...t}:e[r]=t;return e}function b(n,e={}){if(!m(n))return n;const r=l(e);let t=n;for(const[c,a]of Object.entries(r)){if(!a.enabled)continue;const d=s[c],o=d?.pattern||a.pattern,p=a.replacement||d?.replacement||"[PII removed]";o&&(t=t.replace(o,p))}return t}export{b as removePii};
1
+ import{isString as m}from"../../../../../utils/string/is-string.js";const s={email:{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[email_removed]"},phone:{pattern:/(?:\+?1[-.\s]?)?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})(?:\s?(?:ext|x|extension)\.?\s?(\d+))?/g,replacement:"[phone_removed]"},ssn:{pattern:/\b(?!000|666|9\d{2})\d{3}-?(?!00)\d{2}-?(?!0000)\d{4}\b/g,replacement:"[SSN_removed]"},creditCard:{pattern:/\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g,replacement:"[credit_card_removed]"},address:{pattern:/\b\d+\s[A-Za-z0-9\s,.-]+(?:Street|St|Avenue|Ave|Road|Rd|Boulevard|Blvd|Lane|Ln|Drive|Dr|Court|Ct|Circle|Cir|Way|Place|Pl|Parkway|Pkwy|Terrace|Ter)\b/gi,replacement:"[address_removed]"},passport:{pattern:/\b[A-Z]{2}[0-9]{7}\b/g,replacement:"[passport_number_removed]"},driversLicense:{pattern:/\b[A-Z]{1,2}[0-9]{6,9}\b/g,replacement:"[driver_license_removed]"},zipCode:{pattern:/(?<!\d-)\b\d{5}(?:-\d{4})?\b(?!-\d)/g,replacement:"[zip_code_removed]"},bankAccount:{pattern:/\b\d{8,17}\b/g,replacement:"[bank_account_removed]"},dateOfBirth:{pattern:/\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12][0-9]|3[01])[-/](?:19|20)\d{2}\b/g,replacement:"[date_removed]"}};function l(n={}){const e={email:{enabled:!0,replacement:"[email_removed]"},phone:{enabled:!0,replacement:"[phone_removed]"},ssn:{enabled:!0,replacement:"[SSN_removed]"},creditCard:{enabled:!0,replacement:"[credit_card_removed]"},address:{enabled:!0,replacement:"[address_removed]"},passport:{enabled:!0,replacement:"[passport_number_removed]"},driversLicense:{enabled:!0,replacement:"[driver_license_removed]"},zipCode:{enabled:!0,replacement:"[zip_code_removed]"},bankAccount:{enabled:!0,replacement:"[bank_account_removed]"},dateOfBirth:{enabled:!0,replacement:"[date_removed]"}};for(const[r,t]of Object.entries(n))e[r]?e[r]={...e[r],...t}:e[r]=t;return e}function b(n,e={}){if(!m(n))return n;const r=l(e);let t=n;for(const[c,a]of Object.entries(r)){if(!a.enabled)continue;const d=s[c],o=d?.pattern||a.pattern,p=a.replacement||d?.replacement||"[PII removed]";o&&(t=t.replace(o,p))}return t}export{b as removePii};
@@ -0,0 +1,3 @@
1
+ /** Id of the shared data that holds a classic catalog's resolved items; `localeIdSuffix` is empty for the default locale. */
2
+ export declare function getCatalogSharedDataId(catalogId: string, localeIdSuffix?: string): string;
3
+ //# sourceMappingURL=get-catalog-shared-data-id.d.ts.map