@redocly/redoc 0.130.0-next.9 → 0.130.1

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 (111) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/dist/bin.js +1 -1
  3. package/dist/cli/stats/collectors/openapi.js +1 -1
  4. package/dist/cli/telemetry/index.js +1 -1
  5. package/dist/client/ErrorBoundary.js +1 -1
  6. package/dist/client/app/Sidebar/RequestAccessButton.js +2 -2
  7. package/dist/client/app/Sidebar/Sidebar.js +2 -2
  8. package/dist/client/app/hooks/catalog/useCatalogClassic.js +1 -1
  9. package/dist/client/app/hooks/catalog/useCatalogFilter.js +1 -1
  10. package/dist/client/app/hooks/catalog/useCatalogViewMode.js +1 -1
  11. package/dist/client/app/hooks/catalog/useSearchTracker.js +1 -1
  12. package/dist/client/app/hooks/usePageTimeTracker.js +1 -1
  13. package/dist/client/app/hooks/useRouteChangeTracker.js +1 -1
  14. package/dist/client/app/pages/DevLogin/DevLogin.js +1 -1
  15. package/dist/client/app/search/message-handlers.d.ts +29 -0
  16. package/dist/client/app/search/message-handlers.js +1 -0
  17. package/dist/client/app/search/sse-parser.d.ts +10 -0
  18. package/dist/client/app/search/sse-parser.js +2 -0
  19. package/dist/client/app/search/useAiSearch.d.ts +9 -11
  20. package/dist/client/app/search/useAiSearch.js +1 -1
  21. package/dist/client/app/search/useSearch.js +1 -1
  22. package/dist/client/constants/ai-search.d.ts +30 -0
  23. package/dist/client/constants/ai-search.js +1 -0
  24. package/dist/client/constants/index.d.ts +2 -0
  25. package/dist/client/constants/index.js +1 -0
  26. package/dist/client/types/ai-search.d.ts +73 -0
  27. package/dist/client/types/ai-search.js +0 -0
  28. package/dist/client/types/index.d.ts +1 -0
  29. package/dist/constants/l10n/langs/ar.js +1 -1
  30. package/dist/constants/l10n/langs/de.js +1 -1
  31. package/dist/constants/l10n/langs/en.js +1 -1
  32. package/dist/constants/l10n/langs/es.js +1 -1
  33. package/dist/constants/l10n/langs/fr.js +1 -1
  34. package/dist/constants/l10n/langs/hi.js +1 -1
  35. package/dist/constants/l10n/langs/it.js +1 -1
  36. package/dist/constants/l10n/langs/ja.js +1 -1
  37. package/dist/constants/l10n/langs/ko.js +1 -1
  38. package/dist/constants/l10n/langs/pl.js +1 -1
  39. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  40. package/dist/constants/l10n/langs/pt.js +1 -1
  41. package/dist/constants/l10n/langs/ru.js +1 -1
  42. package/dist/constants/l10n/langs/uk.js +1 -1
  43. package/dist/constants/l10n/langs/zh.js +1 -1
  44. package/dist/server/api-routes/run-api-routes-worker.js +1 -1
  45. package/dist/server/constants/common.js +1 -1
  46. package/dist/server/entitlements/entitlements-provider.js +1 -1
  47. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.d.ts +32 -9
  48. package/dist/server/plugins/catalog-entities/database/catalog-entities-service.js +1 -1
  49. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.d.ts +16 -5
  50. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-bff-repository.js +21 -17
  51. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.d.ts +35 -9
  52. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-read-repository.js +24 -21
  53. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.d.ts +31 -8
  54. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-repository.js +1 -1
  55. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
  56. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.d.ts +7 -1
  57. package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-relations-repository.js +1 -1
  58. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.d.ts +1 -1
  59. package/dist/server/plugins/catalog-entities/database/repositories/remote/catalog-entities-remote-repository.js +1 -1
  60. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-entities-exclusion-filter.d.ts +13 -0
  61. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-entities-exclusion-filter.js +1 -0
  62. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.d.ts +31 -0
  63. package/dist/server/plugins/catalog-entities/database/repositories/utils/build-rbac-filter.js +9 -0
  64. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
  65. package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
  66. package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
  67. package/dist/server/plugins/catalog-entities/get-server-props.js +1 -1
  68. package/dist/server/plugins/catalog-entities/types/openapi.d.ts +11 -0
  69. package/dist/server/plugins/catalog-entities/types/openapi.js +0 -0
  70. package/dist/server/plugins/catalog-entities/types/params.d.ts +6 -0
  71. package/dist/server/plugins/catalog-entities/types/params.js +0 -0
  72. package/dist/server/plugins/catalog-entities/utils/catalog-data-collector.js +1 -1
  73. package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.d.ts +11 -0
  74. package/dist/server/plugins/catalog-entities/utils/get-not-accessible-catalog-resources.js +1 -0
  75. package/dist/server/plugins/config-parser/index.js +1 -1
  76. package/dist/server/plugins/default-theme/index.js +1 -1
  77. package/dist/server/plugins/markdown/markdown-static-data-loader.js +1 -1
  78. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +1 -1
  79. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
  80. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
  81. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
  82. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
  83. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  84. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  85. package/dist/server/plugins/mcp/servers/base-server.js +1 -1
  86. package/dist/server/plugins/openapi-docs/template/helpers.d.ts +1 -1
  87. package/dist/server/plugins/openapi-docs/template/helpers.js +3 -3
  88. package/dist/server/plugins/search/llmstxt/index.js +4 -4
  89. package/dist/server/tools/notifiers/logger.js +1 -1
  90. package/dist/server/tools/notifiers/reporter.js +7 -7
  91. package/dist/server/utils/rbac.d.ts +65 -0
  92. package/dist/server/web-server/auth.js +3 -3
  93. package/dist/server/web-server/middleware/catalogAuthMiddleware.d.ts +4 -6
  94. package/dist/server/web-server/middleware/catalogAuthMiddleware.js +1 -1
  95. package/dist/server/web-server/routes/ask-ai.js +1 -1
  96. package/dist/server/web-server/routes/auth.js +1 -1
  97. package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
  98. package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
  99. package/dist/server/web-server/routes/catalog/catalog.js +1 -1
  100. package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.d.ts +10 -0
  101. package/dist/server/web-server/routes/catalog/helpers/has-access-to-entity.js +1 -0
  102. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  103. package/dist/server/web-server/routes/helpers/get-current-rbac-teams.d.ts +3 -0
  104. package/dist/server/web-server/routes/helpers/get-current-rbac-teams.js +1 -0
  105. package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.d.ts +11 -0
  106. package/dist/server/web-server/routes/helpers/get-rbac-restrictions-data-for-catalog.js +1 -0
  107. package/dist/server/web-server/routes/index.js +1 -1
  108. package/dist/server/web-server/routes/mcp-oauth.js +1 -1
  109. package/dist/server/web-server/routes/page-data.js +1 -1
  110. package/dist/server/web-server/utils.d.ts +2 -2
  111. package/package.json +16 -16
@@ -1 +1 @@
1
- import{sha1 as w}from"../../utils/crypto/sha1.js";import{isValidSanitizedString as F}from"../../utils/validate-and-sanitize-string";import{CatalogEntitiesService as v}from"./database/catalog-entities-service.js";import{createPaginationParamsValidator as E}from"../../providers/database/pagination/schemas";import{parseSearch as A}from"../../providers/database/pagination/search";import{OPERATORS as b}from"../../providers/database/pagination/constants.js";import{CacheService as T}from"../../persistence/cache/services/cache-service.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as S,CATALOG_FILTERS_CACHE_TTL_IN_SECONDS as I}from"../../constants/plugins/catalog-entities.js";import{isValidIsoDate as D}from"../../utils/is-valid-iso-date.js";import{expandTeamsForRead as R}from"../../utils";const Q={all:"all",domains:"domain",services:"service",teams:"team",users:"user","api-descriptions":"api-description","data-schemas":"data-schema"},V={team:{field:"type",operator:"equal",value:"user"},"api-description":{field:"type",operator:"equal",value:"api-operation"}},N=async({entitiesTypes:e,serverOutDir:i,catalogConfig:t,queries:s={},rbacTeams:o})=>{const d=await v.getInstance({baseDbDir:i}),c=x.concat("domains","owners"),l=E(c).parse(s),u=t.excludes?.map(p=>p.key)??[],g=e.filter(p=>p!=="all"),n=q(g,u);return l.filter?l.filter={op:b.AND,conditions:[l.filter,n]}:l.filter=n,await d.getEntitiesWithRelations({sort:[{field:"type",order:"ASC"}],limit:10,...l},o)},P=async(e,i,t,s)=>{const o=await v.getInstance({baseDbDir:i});let d=null;const c=t?.revision;c&&D(c)&&(d=c);const l=t?.version;if(!F(l,{pattern:/^[a-zA-Z0-9._-]+$/,maxLength:100,allowEmpty:!0}))return null;const u=await o.getEntityWithRelationsByKey(e,{revision:d,version:l},s);if(!u)return null;const g=u.type==="data-schema"?await o.getRelatedEntities(e,{limit:1,filter:{field:"type",operator:"equal",value:"api-description"}}).then(f=>f.items?.[0]??null):null,n=V[u.type]??void 0,a=K(n,l,d),p=await o.getRelatedEntities(e,{limit:10,sort:[{field:"title",order:"ASC"}],filter:a,search:t?.search?A(t?.search,["key","type","title","summary"]):void 0});return{status:"success",entity:u,relatedEntity:g,relations:p}},_=e=>{const i=JSON.stringify({entitiesTypes:e.entitiesTypes.sort(),filtersConfig:e.filtersConfig});return w(i)},L=async({serverOutDir:e,entitiesTypes:i,filtersConfig:t})=>{if(!t||t.length===0)return{};const s=_({entitiesTypes:i,filtersConfig:t}),o=await T.getInstance({baseDbDir:e}),d=await o.get({key:s,namespace:S});if(d)return d;const c=await v.getInstance({baseDbDir:e}),l=[],u=new Map;for(const a of t)!a.options||a.options.length===0?l.push(a.property):u.set(a.property,a.options);const g=await c.getCatalogFilters({entitiesTypes:i,emptyFilters:l}),n={};for(const a of t){const p=u.get(a.property);if(!p){const r=g[a.property];n[a.property]=r&&r.length>0?r:[];continue}const y=(await c.getCatalogFilters({entitiesTypes:i,emptyFilters:[a.property]}))[a.property];if(!y){n[a.property]=[];continue}const h=new Map;for(const r of y){const m=r.value.toLowerCase().trim();h.set(m,{originalValue:r.value,count:r.count})}n[a.property]=p.map(r=>{const m=r.toLowerCase().trim(),C=h.get(m);return{value:C?.originalValue??r,count:C?.count??0}}).filter(r=>r.count>0).sort((r,m)=>r.value.localeCompare(m.value))}return await o.set({key:s,value:n,namespace:S,ttlInSeconds:I}),n},O=async(e,{props:i},{variables:t},{serverOutDir:s,getRouteSharedDataByFsPath:o,getConfig:d})=>{const c=i?.catalogConfig||{};if(!e.params||!i?.catalogConfig)return{status:"notFound"};const[l,u,g]=e.params;if(!l)return{status:"notFound"};const n=M(c,l),a=n?.includes?.map(m=>m.type)??[];if(!n)return{status:"notFound"};const p=R(d().rbac||{},t?.rbac.teams||[]);if(!g&&u!=="entities"){if(n.hide)return{status:"notFound"};const m=await L({entitiesTypes:a,serverOutDir:s,filtersConfig:n.filters}),C=e.queries?.viewMode??"table";return{status:"success",catalogSwitcherItems:k(c,n),entitiesTypes:a,entities:await N({entitiesTypes:a,serverOutDir:s,catalogConfig:n,queries:e.queries,rbacTeams:p}),catalogConfig:n,filters:m,initialViewMode:C}}const f=await P(g,s,e.queries,p),y=f?.entity.sourceFile,h=f?.entity.type==="api-description",r=y&&h&&o(y)||{};return f?{status:"success",entity:f.entity,relatedEntity:f.relatedEntity,relations:f.relations,entitiesCatalogConfig:c,catalogConfig:n,sharedDataIds:r}:{status:"notFound"}},M=(e,i)=>Object.values(e.catalogs??{}).find(t=>t&&typeof t=="object"&&"slug"in t&&t.slug===i),k=(e,i)=>Object.values(e.catalogs??{}).filter(t=>!t?.hide).map(t=>({labelTranslationKey:t?.catalogSwitcherLabelTranslationKey??t?.slug??"",slug:t?.slug??"",selected:t?.slug===i.slug})).sort((t,s)=>t.slug.localeCompare(s.slug)),q=(e,i)=>({op:"AND",conditions:[...e.length?[{field:"type",operator:"in",value:e}]:[],...i.length?[{field:"key",operator:"in",value:i,modifier:"not"}]:[]]}),K=(e,i,t)=>{let s=e;if(i!==void 0){const o={field:"version",operator:"equal",value:i};s=s?{op:b.AND,conditions:[s,o]}:o}if(t){const o={field:"revision",operator:"equal",value:t};s=s?{op:b.AND,conditions:[s,o]}:o}return s},x=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"];var U=O;export{U as default};
1
+ import{sha1 as A}from"../../utils/crypto/sha1.js";import{isValidSanitizedString as T}from"../../utils/validate-and-sanitize-string";import{CatalogEntitiesService as w}from"./database/catalog-entities-service.js";import{createPaginationParamsValidator as I}from"../../providers/database/pagination/schemas";import{parseSearch as D}from"../../providers/database/pagination/search";import{OPERATORS as E}from"../../providers/database/pagination/constants.js";import{CacheService as R}from"../../persistence/cache/services/cache-service.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as F,CATALOG_FILTERS_CACHE_TTL_IN_SECONDS as P}from"../../constants/plugins/catalog-entities.js";import{isValidIsoDate as N}from"../../utils/is-valid-iso-date.js";import{expandTeamsForRead as V}from"../../utils";import{getNotAccessibleCatalogResources as _}from"./utils/get-not-accessible-catalog-resources.js";const it={all:"all",domains:"domain",services:"service",teams:"team",users:"user","api-descriptions":"api-description","data-schemas":"data-schema"},L={team:{field:"type",operator:"equal",value:"user"},"api-description":{field:"type",operator:"equal",value:"api-operation"}},O=async({entitiesTypes:e,serverOutDir:a,catalogConfig:i,queries:t={},rbacTeams:n,excludedTypes:p,excludedEntities:c})=>{const u=await w.getInstance({baseDbDir:a}),f=B.concat("domains","owners"),l=I(f).parse(t),o=i.excludes?.map(s=>s.key)??[],g=e.filter(s=>s!=="all"),m=W(g,o);return l.filter?l.filter={op:E.AND,conditions:[l.filter,m]}:l.filter=m,await u.getEntitiesWithRelations({paginationParams:{sort:[{field:"type",order:"ASC"}],limit:10,...l},rbacTeams:n,excludedTypes:p,excludedEntities:c})},M=async({entityKey:e,serverOutDir:a,queries:i,rbacTeams:t,excludedTypes:n,excludedEntities:p})=>{const c=await w.getInstance({baseDbDir:a});let u=null;const f=i?.revision;f&&N(f)&&(u=f);const l=i?.version;if(!T(l,{pattern:/^[a-zA-Z0-9._-]+$/,maxLength:100,allowEmpty:!0}))return null;const o=await c.getEntityWithRelationsByKey({entityKey:e,filter:{revision:u,version:l},rbacTeams:t,excludedTypes:n,excludedEntities:p});if(!o)return null;const g=o.type==="data-schema"?await c.getRelatedEntities({entityKey:e,paginationParams:{limit:1,filter:{field:"type",operator:"equal",value:"api-description"}}}).then(h=>h.items?.[0]??null):null,m=L[o.type]??void 0,d=j(m,l,u),s=await c.getRelatedEntities({entityKey:e,paginationParams:{limit:10,sort:[{field:"title",order:"ASC"}],filter:d,search:i?.search?D(i?.search,["key","type","title","summary"]):void 0},rbacTeams:t,excludedTypes:n,excludedEntities:p});return{status:"success",entity:o,relatedEntity:g,relations:s}},k=e=>{const a=JSON.stringify({entitiesTypes:e.entitiesTypes.sort(),filtersConfig:e.filtersConfig,rbacTeams:e.rbacTeams,excludedTypes:e.excludedTypes,excludedEntities:e.excludedEntities});return A(a)},q=async({serverOutDir:e,entitiesTypes:a,filtersConfig:i,rbacTeams:t,excludedTypes:n,excludedEntities:p})=>{if(!i||i.length===0)return{};const c=k({entitiesTypes:a,filtersConfig:i,rbacTeams:t,excludedTypes:n,excludedEntities:p}),u=await R.getInstance({baseDbDir:e}),f=await u.get({key:c,namespace:F});if(f)return f;const l=await w.getInstance({baseDbDir:e}),o=[],g=new Map;for(const s of i)!s.options||s.options.length===0?o.push(s.property):g.set(s.property,s.options);const m=await l.getCatalogFilters({entitiesTypes:a,emptyFilters:o,rbacTeams:t,excludedTypes:n,excludedEntities:p}),d={};for(const s of i){const h=g.get(s.property);if(!h){const r=m[s.property];d[s.property]=r&&r.length>0?r:[];continue}const b=(await l.getCatalogFilters({entitiesTypes:a,emptyFilters:[s.property],rbacTeams:t,excludedTypes:n,excludedEntities:p}))[s.property];if(!b){d[s.property]=[];continue}const v=new Map;for(const r of b){const y=r.value.toLowerCase().trim();v.set(y,{originalValue:r.value,count:r.count})}d[s.property]=h.map(r=>{const y=r.toLowerCase().trim(),S=v.get(y);return{value:S?.originalValue??r,count:S?.count??0}}).filter(r=>r.count>0).sort((r,y)=>r.value.localeCompare(y.value))}return await u.set({key:c,value:d,namespace:F,ttlInSeconds:P}),d},x=async(e,{props:a},{variables:i},{serverOutDir:t,getRouteSharedDataByFsPath:n,getConfig:p})=>{const c=a?.catalogConfig||{};if(!e.params||!a?.catalogConfig)return{status:"notFound"};const[u,f,l]=e.params;if(!u)return{status:"notFound"};const o=K(c,u),g=o?.includes?.map(y=>y.type)??[];if(!o||o.hide)return{status:"notFound"};const m=V(p().rbac||{},i?.rbac.teams||[]),{catalogs:d,types:s,entities:h}=_({rbacConfig:p().rbac||{},currentRbacTeams:i?.rbac.teams||[]});if(d.includes(u))return{status:"notFound"};if(!l&&f!=="entities"){const y=await q({entitiesTypes:g,serverOutDir:t,filtersConfig:o.filters,rbacTeams:m,excludedTypes:s,excludedEntities:h}),S=e.queries?.viewMode??"table";return{status:"success",catalogSwitcherItems:z(c,o,d),entitiesTypes:g,entities:await O({entitiesTypes:g,serverOutDir:t,catalogConfig:o,queries:e.queries,rbacTeams:m,excludedTypes:s,excludedEntities:h}),catalogConfig:o,filters:y,initialViewMode:S}}const C=await M({entityKey:l,serverOutDir:t,queries:e.queries,rbacTeams:m,excludedTypes:s,excludedEntities:h});if(!C)return{status:"notFound"};const b=C?.entity.sourceFile,v=C?.entity.type==="api-description",r=b&&v&&n(b)||{};return{status:"success",entity:C.entity,relatedEntity:C.relatedEntity,relations:C.relations,entitiesCatalogConfig:c,catalogConfig:o,sharedDataIds:r}},K=(e,a)=>Object.values(e.catalogs??{}).find(i=>i&&typeof i=="object"&&"slug"in i&&i.slug===a),z=(e,a,i)=>Object.values(e.catalogs??{}).filter(t=>!t?.hide&&!i.includes(t?.slug??"")).map(t=>({labelTranslationKey:t?.catalogSwitcherLabelTranslationKey??t?.slug??"",slug:t?.slug??"",selected:t?.slug===a.slug})).sort((t,n)=>t.slug.localeCompare(n.slug)),W=(e,a)=>({op:"AND",conditions:[...e.length?[{field:"type",operator:"in",value:e}]:[],...a.length?[{field:"key",operator:"in",value:a,modifier:"not"}]:[]]}),j=(e,a,i)=>{let t=e;if(a!==void 0){const n={field:"version",operator:"equal",value:a};t=t?{op:E.AND,conditions:[t,n]}:n}if(i){const n={field:"revision",operator:"equal",value:i};t=t?{op:E.AND,conditions:[t,n]}:n}return t},B=["type","key","title","summary","tags","metadata","metadata.*","git","contact","links","id","source","sourceFile","createdAt","updatedAt"];var st=x;export{st as default};
@@ -0,0 +1,11 @@
1
+ import type { REDOCLY_TEAMS_RBAC } from '@redocly/config';
2
+ import type { OpenAPIOperation, OpenAPISchema } from '@redocly/openapi-docs';
3
+ export type RedoclyOpenAPISchema = OpenAPISchema & {
4
+ [REDOCLY_TEAMS_RBAC]?: Record<string, string>;
5
+ 'x-rbac'?: Record<string, string>;
6
+ };
7
+ export type RedoclyOpenapiOperation = OpenAPIOperation & {
8
+ [REDOCLY_TEAMS_RBAC]?: Record<string, string>;
9
+ 'x-rbac'?: Record<string, string>;
10
+ };
11
+ //# sourceMappingURL=openapi.d.ts.map
@@ -0,0 +1,6 @@
1
+ export type GetEntityByIdParams = {
2
+ rbacTeams?: string[];
3
+ excludedTypes?: string[];
4
+ excludedEntities?: string[];
5
+ };
6
+ //# sourceMappingURL=params.d.ts.map
@@ -1 +1 @@
1
- const i="error";class n{#t=new Set;#e;#s;#i=0;#o=0;addExtractor(t){this.#t.add(t)}increaseSkippedFilesCount(){this.#i++}increaseProcessedFilesCount(){this.#o++}async getCatalogEntitiesData(t){this.#e=this.#a(t),this.#s=this.#n(t);const[s,e]=await Promise.allSettled([this.#e,this.#s]);return{totalEntitiesCount:s.status==="fulfilled"?s.value:i,countOfEntitiesByType:e.status==="fulfilled"?e.value:i,extractors:Array.from(this.#t),totalFilesSkippedByHash:this.#i,totalProcessedFiles:this.#o}}async#a(t){return(await t.getEntities({limit:1,filter:{field:"is_deleted",operator:"equal",value:!1}})).page.total}async#n(t){return(await t.getEntitiesCountByTypes()).reduce((e,{type:o,count:a})=>(e[o]=a,e),{})}}const r=new n;export{n as CatalogDataCollector,r as catalogDataCollector};
1
+ const i="error";class n{#t=new Set;#e;#s;#i=0;#a=0;addExtractor(t){this.#t.add(t)}increaseSkippedFilesCount(){this.#i++}increaseProcessedFilesCount(){this.#a++}async getCatalogEntitiesData(t){this.#e=this.#o(t),this.#s=this.#n(t);const[s,e]=await Promise.allSettled([this.#e,this.#s]);return{totalEntitiesCount:s.status==="fulfilled"?s.value:i,countOfEntitiesByType:e.status==="fulfilled"?e.value:i,extractors:Array.from(this.#t),totalFilesSkippedByHash:this.#i,totalProcessedFiles:this.#a}}async#o(t){return(await t.getEntities({paginationParams:{limit:1,filter:{field:"is_deleted",operator:"equal",value:!1}}})).page.total}async#n(t){return(await t.getEntitiesCountByTypes()).reduce((e,{type:a,count:o})=>(e[a]=o,e),{})}}const r=new n;export{n as CatalogDataCollector,r as catalogDataCollector};
@@ -0,0 +1,11 @@
1
+ import type { RedoclyConfig } from '@redocly/config';
2
+ export declare function getNotAccessibleCatalogResources({ rbacConfig, currentRbacTeams, accessLevel, }: {
3
+ rbacConfig: RedoclyConfig['rbac'];
4
+ currentRbacTeams: string[];
5
+ accessLevel?: 'READ' | 'WRITE';
6
+ }): {
7
+ catalogs: string[];
8
+ types: string[];
9
+ entities: string[];
10
+ };
11
+ //# sourceMappingURL=get-not-accessible-catalog-resources.d.ts.map
@@ -0,0 +1 @@
1
+ import{RBAC_ALL_OTHER_TEAMS as c}from"../../../../constants/common.js";const g=["read","triage","write","maintain","admin"],r=["write","maintain","admin"];function E({rbacConfig:i,currentRbacTeams:s,accessLevel:n="READ"}){const a=[],f=[],e=[];if(n==="READ")for(const[t,o]of Object.entries(i?.entitiesCatalog?.catalogs??{}))o&&(l(o,s,n)||a.push(t));for(const[t,o]of Object.entries(i?.entitiesCatalog?.entitiesTypes??{}))o&&(l(o,s,n)||f.push(t));i?.entitiesCatalog?.entitiesGroups?.forEach(t=>{l(t.config,s,n)||e.push(...t.entities??[])});for(const[t,o]of Object.entries(i?.entitiesCatalog?.entities??{}))o&&(l(o,s,n)||e.push(t));return{catalogs:[...new Set(a)],types:[...new Set(f)],entities:[...new Set(e)]}}function l(i,s,n){const a=i[c],f=n==="WRITE"?r:g,e=[];for(const t of s)i[t]?e.push(i[t]):a&&e.push(a);return e.length>0&&e.some(t=>f.includes(t.toLowerCase()))}export{E as getNotAccessibleCatalogResources};
@@ -1 +1 @@
1
- import y from"path";import{REDOCLY_ROUTE_RBAC as n,REDOCLY_TEAMS_RBAC as b}from"@redocly/config";import{deepMerge as h}from"../../../utils/object/deep-merge.js";import{buildWildcardRedirectsTree as R}from"../../utils/redirects/build-wildcard-redirects-tree.js";import{formatCustomScripts as m,formatCustomLinks as C}from"./format-custom-tags.js";import{applyL10nToRbacConfig as S,resolveDirectoryHashes as D}from"../../utils/rbac.js";import{copySeoAssets as P}from"./copy-seo-assets.js";import{normalizeRedirectSources as T}from"./normalize-redirect-sources.js";import{applyL10nToRedirects as v}from"./apply-l10n-to-redirects.js";import{DEFAULT_LOADERS as A}from"./loaders/index.js";import{resolveSearchFacets as L}from"./resolve-search-facets.js";import{telemetryTraceStep as w}from"../../../cli/telemetry/helpers/trace-step.js";async function U(){return{id:"Config Parser",loaders:A,async processContent(o,{getConfig:c,fs:i}){await w("build.plugin.config_parser",async t=>{const{contentDir:e,setGlobalConfig:s,setGlobalData:f}=o,r=await c(),a={outdir:o.outdir,contentDir:e},p=await m(r.scripts?.head,a),g=await C(r.links,a),u=await m(r.scripts?.body,a),d=h(r,{headScriptTags:p,linkTags:g,postBodyScriptTags:u});t?.setAttribute("config",JSON.stringify(d));const l=r.redirects?T(r.redirects):{};s({...d,requiresLogin:!!r.requiresLogin,rbac:S(i,r.rbac||{}),directoryPaths:await D(i,r.rbac),seo:r.seo&&await P(r.seo,a.contentDir,a.outdir),redirects:v(l,r.l10n),wildcardRedirectsTree:R(l)}),L(r.search?.filters?.facets||[],o.getSearchFacets,o.setSearchFacets),f({removeAttribution:!!r.removeAttribution})})},async afterRoutesCreated(o){const c=o.getGlobalConfig("rbac"),i=o.getGlobalConfig("directoryPaths");if(!(!c||Object.keys(c).length===0))for(const t of o.getAllRoutes()){if(t.versions&&i)for(const e of t.versions){const s=i[e.folderId],r=s==="."||s==="/"?"":s;e[n]={slug:e.link,fsPath:y.posix.join(r,"@"+e.version,"index.md")}}t[n]||t[b]||(t[n]={slug:t.slug,fsPath:t.fsPath})}}}}export{U as configParserPlugin};
1
+ import R from"path";import{REDOCLY_ROUTE_RBAC as l,REDOCLY_TEAMS_RBAC as m}from"@redocly/config";import{deepMerge as C}from"../../../utils/object/deep-merge.js";import{buildWildcardRedirectsTree as S}from"../../utils/redirects/build-wildcard-redirects-tree.js";import{formatCustomScripts as g,formatCustomLinks as D}from"./format-custom-tags.js";import{applyL10nToRbacConfig as P,resolveDirectoryHashes as T}from"../../utils/rbac.js";import{copySeoAssets as v}from"./copy-seo-assets.js";import{normalizeRedirectSources as A}from"./normalize-redirect-sources.js";import{applyL10nToRedirects as L}from"./apply-l10n-to-redirects.js";import{DEFAULT_LOADERS as w}from"./loaders/index.js";import{resolveSearchFacets as O}from"./resolve-search-facets.js";import{telemetryTraceStep as E}from"../../../cli/telemetry/helpers/trace-step.js";async function H(){return{id:"Config Parser",loaders:w,async processContent(t,{getConfig:n,fs:i}){await E("build.plugin.config_parser",async o=>{const{contentDir:e,setGlobalConfig:a,setGlobalData:d}=t,r=await n(),c={outdir:t.outdir,contentDir:e},u=await g(r.scripts?.head,c),b=await D(r.links,c),y=await g(r.scripts?.body,c),f=C(r,{headScriptTags:u,linkTags:b,postBodyScriptTags:y});o?.setAttribute("config",JSON.stringify(f));const p=r.redirects?A(r.redirects):{},h=f.banner?.map(s=>typeof s=="object"&&s!==null&&s.rbac?{...s,[m]:s.rbac}:s);a({...f,banner:h,requiresLogin:!!r.requiresLogin,rbac:P(i,r.rbac||{}),directoryPaths:await T(i,r.rbac),seo:r.seo&&await v(r.seo,c.contentDir,c.outdir),redirects:L(p,r.l10n),wildcardRedirectsTree:S(p)}),O(r.search?.filters?.facets||[],t.getSearchFacets,t.setSearchFacets),d({removeAttribution:!!r.removeAttribution})})},async afterRoutesCreated(t){const n=t.getGlobalConfig("rbac"),i=t.getGlobalConfig("directoryPaths");if(!(!n||Object.keys(n).length===0))for(const o of t.getAllRoutes()){if(o.versions&&i)for(const e of o.versions){const a=i[e.folderId],r=a==="."||a==="/"?"":a;e[l]={slug:e.link,fsPath:R.posix.join(r,"@"+e.version,"index.md")}}o[l]||o[m]||(o[l]={slug:o.slug,fsPath:o.fsPath})}}}}export{H as configParserPlugin};
@@ -1 +1 @@
1
- import{REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{DEV_LOGIN_SLUG as u,INVITE_SLUG as T,PUBLIC_RBAC_SCOPE_ITEM as m,UI_ACCESSIBLE_CONFIG_PROPS as b,CONFIG_FILE_NAME as n,DEFAULT_SSO_IDP_TITLE as P}from"../../../constants/common.js";import{isDevelopMode as _}from"../../utils/envs/is-develop-mode.js";import{getTemplatePath as s}from"./get-template-path.js";import{resolveLinksFromConfig as p}from"../nav-utils.js";import{resolveLogoConfig as F}from"./resolve-logo.js";import{extractTeamNames as E}from"./extract-team-names.js";import{resolveProductsConfig as O}from"./resolve-products-config.js";import{getExcludedFromLinkCheckerPatterns as y}from"../sidebars/utils.js";import{resolveEntitiesCatalogConfig as A}from"./resolve-catalog-entities.js";import{telemetryTraceStep as j}from"../../../cli/telemetry/helpers/trace-step.js";async function q(r){return{id:"Default Theme",async processContent(e){await j("build.plugin.default_theme",async()=>{const t=v(e),a=Object.keys(e.getConfig()?.ssoDirect||{}).length>0,i=e.createTemplate("invite",s("../../../../dist/client/app/pages/Invite/Invite.js"));if(e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,excludeFromSearch:!0,slug:T,[c]:m,fsPath:T,templateId:i}),r.devLogin&&a){const o={frontmatter:{},seo:{title:"Login page"},authIdps:f(t),rbac:{teams:E(e.getConfig().rbac)}},l=e.createTemplate("dev-login",s("../../../../dist/client/app/pages/DevLogin/DevLogin.js"));e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,excludeFromSearch:!0,slug:u,[c]:m,fsPath:u,templateId:l,getStaticData:async()=>({props:o})})}else if(t.length>1){const o={frontmatter:{},seo:{title:"Login page"},authIdps:f(t)},l=e.createTemplate("login",s("../../../../dist/client/app/pages/Login/Login.js"));e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,slug:u,[c]:m,fsPath:u,templateId:l,getStaticData:async()=>({props:o})})}e.createTemplate("404",s("../../../../dist/client/app/pages/404/404.js")),e.createTemplate("403",s("../../../../dist/client/app/pages/403/403.js")),e.createTemplate("403OIDC",s("../../../../dist/client/app/pages/403/403OIDC.js")),_()&&e.createTemplate("compilation-error",s("../../../../dist/client/app/pages/CompilationError/CompilationError.js"))})},async afterRoutesCreated(e,t){const{contentDir:a,outdir:i}=e,o=e.getConfig(),{navbar:l,footer:S,userMenu:g,search:I,breadcrumbs:L,products:D}=o,C=Object.keys(o?.ssoDirect||{}).length>0,d=y(o),h={navFile:n,excludedFromLinkCheckerPatterns:d};e.setGlobalData({...k(o),navbar:await p(l,a,e,t,h),footer:await p(S,a,e,t,h),breadcrumbs:{...L,prefixItems:await p(L?.prefixItems||[],a,e,t,{navFile:n,excludedFromLinkCheckerPatterns:d})},userMenu:{...g,hide:g?.hide??!C,menu:await p(g?.items,a,e,t,{navFile:n,excludedFromLinkCheckerPatterns:d})},logo:await F(o.logo,n,i,t.fs),auth:{idpsInfo:f(v(e)),devLogin:r.devLogin&&C},products:await O(D,e,t),search:{...I,suggestedPages:await p(I?.suggestedPages,a,e,t,{navFile:n,excludedFromLinkCheckerPatterns:d})},entitiesCatalog:await A(o.entitiesCatalog,n,i,t.fs),headScriptTags:void 0,linkTags:void 0,postBodyScriptTags:void 0,preBodyScriptTags:void 0})}}}function v(r){const e=r.getConfig().ssoDirect;return Object.entries(e||{}).map(([a,i])=>({idpId:a,type:i.type,title:i.title}))}function f(r){return process.env.LOCALHOST_LOGIN==="true"?r:r.filter(t=>t.title!==P)}function k(r){const e={};for(const t of b)r[t]&&(e[t]=r[t]);return e}export{q as defaultThemePlugin,k as pickUiAccessibleConfig};
1
+ import{REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{DEV_LOGIN_SLUG as u,INVITE_SLUG as h,PUBLIC_RBAC_SCOPE_ITEM as m,UI_ACCESSIBLE_CONFIG_PROPS as b,CONFIG_FILE_NAME as n,DEFAULT_SSO_IDP_TITLE as P}from"../../../constants/common.js";import{isDevelopMode as _}from"../../utils/envs/is-develop-mode.js";import{getTemplatePath as s}from"./get-template-path.js";import{resolveLinksFromConfig as p}from"../nav-utils.js";import{resolveLogoConfig as F}from"./resolve-logo.js";import{extractTeamNames as E}from"./extract-team-names.js";import{resolveProductsConfig as O}from"./resolve-products-config.js";import{getExcludedFromLinkCheckerPatterns as y}from"../sidebars/utils.js";import{resolveEntitiesCatalogConfig as A}from"./resolve-catalog-entities.js";import{telemetryTraceStep as j}from"../../../cli/telemetry/helpers/trace-step.js";async function q(r){return{id:"Default Theme",async processContent(e){await j("build.plugin.default_theme",async()=>{const t=T(e),a=Object.keys(e.getConfig()?.ssoDirect||{}).length>0,i=e.createTemplate("invite",s("../../../../dist/client/app/pages/Invite/Invite.js"));if(e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,excludeFromSearch:!0,slug:h,[c]:m,fsPath:h,templateId:i}),r.devLogin&&a){const o={frontmatter:{},seo:{title:"Login page"},authIdps:v(t),rbac:{teams:E(e.getConfig().rbac)}},l=e.createTemplate("dev-login",s("../../../../dist/client/app/pages/DevLogin/DevLogin.js"));e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,excludeFromSearch:!0,slug:u,[c]:m,fsPath:u,templateId:l,getStaticData:async()=>({props:o})})}else if(t.length>1){const o={frontmatter:{},seo:{title:"Login page"},authIdps:v(t)},l=e.createTemplate("login",s("../../../../dist/client/app/pages/Login/Login.js"));e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,slug:u,[c]:m,fsPath:u,templateId:l,getStaticData:async()=>({props:o})})}e.createTemplate("404",s("../../../../dist/client/app/pages/404/404.js")),e.createTemplate("403",s("../../../../dist/client/app/pages/403/403.js")),e.createTemplate("403OIDC",s("../../../../dist/client/app/pages/403/403OIDC.js")),_()&&e.createTemplate("compilation-error",s("../../../../dist/client/app/pages/CompilationError/CompilationError.js"))})},async afterRoutesCreated(e,t){const{contentDir:a,outdir:i}=e,o=e.getConfig(),{navbar:l,footer:S,userMenu:g,search:f,breadcrumbs:I,products:D}=o,L=Object.keys(o?.ssoDirect||{}).length>0,d=y(o),C={navFile:n,excludedFromLinkCheckerPatterns:d};e.setGlobalData({...k(o),navbar:await p(l,a,e,t,C),footer:await p(S,a,e,t,C),breadcrumbs:{...I,prefixItems:await p(I?.prefixItems||[],a,e,t,{navFile:n,excludedFromLinkCheckerPatterns:d})},userMenu:{...g,hide:g?.hide??!L,menu:await p(g?.items,a,e,t,{navFile:n,excludedFromLinkCheckerPatterns:d})},logo:await F(o.logo,n,i,t.fs),auth:{idpsInfo:T(e),devLogin:r.devLogin&&L},products:await O(D,e,t),search:{...f,suggestedPages:await p(f?.suggestedPages,a,e,t,{navFile:n,excludedFromLinkCheckerPatterns:d})},entitiesCatalog:await A(o.entitiesCatalog,n,i,t.fs),headScriptTags:void 0,linkTags:void 0,postBodyScriptTags:void 0,preBodyScriptTags:void 0})}}}function T(r){const e=r.getConfig().ssoDirect;return Object.entries(e||{}).map(([a,i])=>({idpId:a,type:i.type,title:i.title}))}function v(r){return process.env.LOCALHOST_LOGIN==="true"?r:r.filter(t=>t.title!==P)}function k(r){const e={};for(const t of b)r[t]&&(e[t]=r[t]);return e}export{q as defaultThemePlugin,k as pickUiAccessibleConfig};
@@ -1 +1 @@
1
- import A from"path";import{REDOCLY_TEAMS_RBAC as m,REDOCLY_ROUTE_RBAC as y}from"@redocly/config";import{removeTrailingSlash as R}from"../../../utils/url/remove-trailing-slash.js";import{addLeadingSlash as S}from"../../../utils/url/add-leading-slash.js";import{resolveFrontmatterKeys as P}from"../resolve-frontmatter-keys.js";import{resolveItem as T}from"../nav-utils.js";const C=new WeakMap;async function _(l,i,s,e,a){const o=await s.getConfig(),{ast:d,compoundHash:n,info:c}=await a.parseMarkdoc(l,s),g={...o.markdown?.editPage,...e.markdown?.editPage},t=i.fsPath!=null?s.fs.getFileInfo(i.fsPath):null,f=!g?.hide&&g?.baseUrl?{to:R(g.baseUrl)+S(t?.realRelativePath||i.fsPath||"")}:void 0,k={...o.feedback,...e.feedback},u=e.feedback?{type:k.type||"sentiment",settings:k.settings||{},hide:e.feedback?.hide}:void 0;let w=C.get(d),r=w?.ast;(!r||w?.compoundHash!==n)&&(r=JSON.stringify(d),C.set(d,{ast:r,compoundHash:n}));let h;e.navigation&&(h={...e.navigation,nextButton:await L(e.navigation.nextButton,i,a,s),previousButton:await L(e.navigation.previousButton,i,a,s)});const p=e?.seo?await P(e.seo,["image"],i.fsPath||"",a,s):void 0,v=c.tagList;Array.isArray(v)&&v.includes("code-walkthrough")&&(e.markdown=e.markdown||{},e.markdown.toc={hide:!0},e.footer=e.footer||{},e.footer={hide:!0});const b=e?.seo?.title||await i.getNavText?.();return{ast:r,frontmatter:await P({...e,...u!==void 0?{feedback:u}:{},...p!==void 0?{seo:p}:{},...h!==void 0?{navigation:h}:{}},o.markdown?.frontMatterKeysToResolve||["image","links"],i.fsPath||"",a,s),editPage:f,props:{metadata:{markdoc:{tagList:c.tagList}},seo:{...p,...b?{title:b}:{}}},[m]:i[m],[y]:i[y]}}async function L(l,i,s,e){if(!l||typeof l!="object")return;let a=l,o,d;if("page"in a&&typeof a.page=="string"){const{page:t,...f}=a;a=f,o=t}if("label"in a&&typeof a.label=="string"){const{label:t,...f}=a;a=f,d=t}let n;if(o){const t=await T({page:o},i.fsPath?A.dirname(i.fsPath):".",s,e,{navFile:i.fsPath||""});n=Array.isArray(t)?t[0]:t,n=n?.type!=="error"?n:void 0}const c=n?.routeSlug,g=d??n?.label;return{...a,label:g,link:c}}export{_ as markdownStaticDataLoader};
1
+ import R from"path";import{REDOCLY_TEAMS_RBAC as b,REDOCLY_ROUTE_RBAC as C}from"@redocly/config";import{removeTrailingSlash as S}from"../../../utils/url/remove-trailing-slash.js";import{addLeadingSlash as T}from"../../../utils/url/add-leading-slash.js";import{resolveFrontmatterKeys as m}from"../resolve-frontmatter-keys.js";import{resolveItem as B}from"../nav-utils.js";const A=new WeakMap;async function F(l,i,s,e,a){const d=await s.getConfig(),{ast:t,compoundHash:n,info:c}=await a.parseMarkdoc(l,s),g={...d.markdown?.editPage,...e.markdown?.editPage},o=i.fsPath!=null?s.fs.getFileInfo(i.fsPath):null,f=!g?.hide&&g?.baseUrl?{to:S(g.baseUrl)+T(o?.realRelativePath||i.fsPath||"")}:void 0,u={...d.feedback,...e.feedback},w=e.feedback?{type:u.type||"sentiment",settings:u.settings||{},hide:e.feedback?.hide}:void 0;Array.isArray(e.banner)&&(e.banner=e.banner.map(r=>r&&r.rbac?{...r,[b]:r.rbac}:r));let v=A.get(t),h=v?.ast;(!h||v?.compoundHash!==n)&&(h=JSON.stringify(t),A.set(t,{ast:h,compoundHash:n}));let p;e.navigation&&(p={...e.navigation,nextButton:await L(e.navigation.nextButton,i,a,s),previousButton:await L(e.navigation.previousButton,i,a,s)});const k=e?.seo?await m(e.seo,["image"],i.fsPath||"",a,s):void 0,y=c.tagList;Array.isArray(y)&&y.includes("code-walkthrough")&&(e.markdown=e.markdown||{},e.markdown.toc={hide:!0},e.footer=e.footer||{},e.footer={hide:!0});const P=e?.seo?.title||await i.getNavText?.();return{ast:h,frontmatter:await m({...e,...w!==void 0?{feedback:w}:{},...k!==void 0?{seo:k}:{},...p!==void 0?{navigation:p}:{}},d.markdown?.frontMatterKeysToResolve||["image","links"],i.fsPath||"",a,s),editPage:f,props:{metadata:{markdoc:{tagList:c.tagList}},seo:{...k,...P?{title:P}:{}}},[b]:i[b],[C]:i[C]}}async function L(l,i,s,e){if(!l||typeof l!="object")return;let a=l,d,t;if("page"in a&&typeof a.page=="string"){const{page:o,...f}=a;a=f,d=o}if("label"in a&&typeof a.label=="string"){const{label:o,...f}=a;a=f,t=o}let n;if(d){const o=await B({page:d},i.fsPath?R.dirname(i.fsPath):".",s,e,{navFile:i.fsPath||""});n=Array.isArray(o)?o[0]:o,n=n?.type!=="error"?n:void 0}const c=n?.routeSlug,g=t??n?.label;return{...a,label:g,link:c}}export{F as markdownStaticDataLoader};
@@ -1 +1 @@
1
- import{telemetry as i}from"../../../../telemetry/index.js";import{mcpToolWorkers as n,MCP_TOOL_WORKER_KEY as a}from"../../../../workers/mcp-tool-worker-pool.js";import{findApiDescriptionByName as p}from"../utils.js";import{getApiDescriptionFromFs as u}from"./utils.js";function f(o,t,s){return{toolName:o,args:t,context:s}}class g{schema;constructor(t){this.schema=t}getContext(t){const s={};for(const e of this.requiredContext)s[e]=t[e];return{...s,apiDescriptionsMap:t.apiDescriptionsMap}}register(t){const s=async(e,r)=>{const c=f(this.name,e,this.getContext(t));return await n.exec(a,[c],{timeout:6e4})};t.server.tool(this.name,this.description,this.schema,s)}async execute(t,s){try{const e=await this.executeAction(t,s);return i.sendMcpToolCalledMessage({server_type:"docs",tool:this.name}),e}catch(e){throw i.sendMcpErrorMessage({server_type:"docs",tool:this.name,message:e instanceof Error?e.message:String(e),stack:e instanceof Error&&e.stack||""}),e}}async getApiDefinition(t,s){if(!s.outdir||!s.accessInfo)throw new Error("Missing required context: outdir and accessInfo");const e=p(s.apiDescriptionsMap,t);if(!e)return{success:!1,response:{content:[{type:"text",text:`No API found matching "${t}".`}]}};const r=await u({relativePath:e.relativePath||"",outdir:s.outdir,accessInfo:s.accessInfo});return r?{success:!0,definition:r}:{success:!1,response:{content:[{type:"text",text:`Spec not found from the file system with "${t}".`}]}}}}export{g as DocsMcpTool};
1
+ import{telemetry as i}from"../../../../telemetry/index.js";import{mcpToolWorkers as n,MCP_TOOL_WORKER_KEY as a}from"../../../../workers/mcp-tool-worker-pool.js";import{findApiDescriptionByName as p}from"../utils.js";import{getApiDescriptionFromFs as u}from"./utils.js";function f(o,t,s){return{toolName:o,args:t,context:s}}class g{schema;constructor(t){this.schema=t}getContext(t){const s={};for(const e of this.requiredContext)s[e]=t[e];return{...s,apiDescriptionsMap:t.apiDescriptionsMap}}register(t){const s=async(e,r)=>{const c=f(this.name,e,this.getContext(t));return await n.exec(a,[c],{timeout:6e4})};t.server.tool(this.name,this.description,this.schema,s)}async execute(t,s){try{const e=await this.executeAction(t,s);return i.sendMcpToolCalledMessage([{object:"mcp_server",server_type:"docs",tool:this.name}]),e}catch(e){throw i.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:this.name,message:e instanceof Error?e.message:String(e),stack:e instanceof Error&&e.stack||""}]),e}}async getApiDefinition(t,s){if(!s.outdir||!s.accessInfo)throw new Error("Missing required context: outdir and accessInfo");const e=p(s.apiDescriptionsMap,t);if(!e)return{success:!1,response:{content:[{type:"text",text:`No API found matching "${t}".`}]}};const r=await u({relativePath:e.relativePath||"",outdir:s.outdir,accessInfo:s.accessInfo});return r?{success:!0,definition:r}:{success:!1,response:{content:[{type:"text",text:`Spec not found from the file system with "${t}".`}]}}}}export{g as DocsMcpTool};
@@ -1 +1 @@
1
- import{resolveParameters as T,resolveRequestBody as y,resolveResponses as P}from"../utils.js";import{isMcpEndpoint as g}from"./utils.js";import{DocsMcpTool as x}from"./docs-mcp-tool.js";import{checkEndpointAndDeleteXMcp as v}from"../../utils/xmcp-utils.js";const p=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","TRACE"],S={type:"object",required:["name","path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...p,...p.map(r=>r.toLowerCase())],minLength:1}}};class D extends x{name="get-endpoint-info";description="Get comprehensive information about specific endpoint including parameters, security, and examples";requiredContext=["outdir","accessInfo"];constructor(){super(S)}async executeAction(a,c){const{name:d,path:o,method:i}=a,n=await this.getApiDefinition(d,c);if(!n.success)return n.response;const{definition:e}=n,m=o.startsWith("/")?o:`/${o}`,{title:u=""}=e.info||{},s=e.paths?.[m],h=i.toLowerCase();if(!s)return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const t=s[h];if(!g(t)||!v(t,"docs"))return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const f=s?.parameters||[],l=t.parameters||[],E={...t,parameters:T({pathParams:f,opParams:l,definition:e}),requestBody:y(t.requestBody,e),responses:P(t.responses,e)};return{content:[{type:"text",text:JSON.stringify({api:u,version:e.info?.version||"",servers:e.servers||[],endpoint:{path:o,method:i.toUpperCase(),...E},globalSecurity:e.security||[],securitySchemes:e.components?.securitySchemes||[]},null,2)}]}}}export{D as GetEndpointInfoTool};
1
+ import{resolveParameters as T,resolveRequestBody as y,resolveResponses as P}from"../utils.js";import{isMcpEndpoint as g}from"./utils.js";import{DocsMcpTool as x}from"./docs-mcp-tool.js";import{checkEndpointAndDeleteXMcp as v}from"../../utils/xmcp-utils.js";const p=["GET","POST","PUT","DELETE","PATCH","OPTIONS","HEAD","TRACE"],S={type:"object",required:["name","path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...p,...p.map(r=>r.toLowerCase())],minLength:1}}};class D extends x{name="get-endpoint-info";description="Get comprehensive information about specific endpoint including parameters, security, and examples";requiredContext=["outdir","accessInfo"];constructor(){super(S)}async executeAction(c,a){const{name:d,path:o,method:i}=c,n=await this.getApiDefinition(d,a);if(!n.success)return n.response;const{definition:e}=n,m=o.startsWith("/")?o:`/${o}`,{title:u=""}=e.info||{},s=e.paths?.[m],h=i.toLowerCase();if(!s)return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const t=s[h];if(!g(t)||!v(t,"docs"))return{content:[{type:"text",text:"Endpoint not found"}],isError:!0};const l=s?.parameters||[],E=t.parameters||[],f={...t,parameters:T({pathParams:l,opParams:E,definition:e}),requestBody:y(t.requestBody,e),responses:P(t.responses,e)};return{content:[{type:"text",text:JSON.stringify({api:u,version:e.info?.version||"",servers:e.servers||[],endpoint:{path:o,method:i.toUpperCase(),...f},globalSecurity:e.security||[],securitySchemes:e.components?.securitySchemes||[]},null,2)}]}}}export{D as GetEndpointInfoTool};
@@ -1 +1 @@
1
- import{DocsMcpTool as r}from"./docs-mcp-tool.js";import{getEndpointsFromPaths as p}from"./utils.js";const c={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1}}};class u extends r{name="get-endpoints";description="Get all endpoints for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(c)}async executeAction(o,i){const{name:s}=o,e=await this.getApiDefinition(s,i);if(!e.success)return e.response;const{definition:t}=e,n=p(t);return n.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",servers:t.servers||[],endpoints:n},null,2)}]}}}export{u as GetEndpointsTool};
1
+ import{DocsMcpTool as r}from"./docs-mcp-tool.js";import{getEndpointsFromPaths as c}from"./utils.js";const p={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1}}};class u extends r{name="get-endpoints";description="Get all endpoints for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(p)}async executeAction(o,i){const{name:s}=o,t=await this.getApiDefinition(s,i);if(!t.success)return t.response;const{definition:e}=t,n=c(e);return n.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:e.info?.title||"",version:e.info?.version||"",servers:e.servers||[],endpoints:n},null,2)}]}}}export{u as GetEndpointsTool};
@@ -1 +1 @@
1
- import{DocsMcpTool as r}from"./docs-mcp-tool.js";const s={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1}}};class a extends r{name="get-full-api-description";description="Get the complete OpenAPI description";requiredContext=["outdir","accessInfo"];constructor(){super(s)}async executeAction(i,n){const{name:o}=i,e=await this.getApiDefinition(o,n);if(!e.success)return e.response;const{definition:t}=e;return{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",definition:t},null,2)}]}}}export{a as GetFullApiDescriptionTool};
1
+ import{DocsMcpTool as s}from"./docs-mcp-tool.js";const r={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1}}};class a extends s{name="get-full-api-description";description="Get the complete OpenAPI description";requiredContext=["outdir","accessInfo"];constructor(){super(r)}async executeAction(i,n){const{name:o}=i,e=await this.getApiDefinition(o,n);if(!e.success)return e.response;const{definition:t}=e;return{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",definition:t},null,2)}]}}}export{a as GetFullApiDescriptionTool};
@@ -1 +1 @@
1
- import{DocsMcpTool as o}from"./docs-mcp-tool.js";const r={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name (or part of it)",minLength:1}}};class p extends o{name="get-security-schemes";description="Get the security schemes for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(r)}async executeAction(s,i){const{name:n}=s,t=await this.getApiDefinition(n,i);if(!t.success)return t.response;const{definition:e}=t;return{content:[{type:"text",text:JSON.stringify({name:e.info?.title,version:e.info?.version,securitySchemes:e.components?.securitySchemes||[],security:e.security||[]},null,2)}]}}}export{p as GetSecuritySchemesTool};
1
+ import{DocsMcpTool as c}from"./docs-mcp-tool.js";const o={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1}}};class p extends c{name="get-security-schemes";description="Get the security schemes for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(o)}async executeAction(s,i){const{name:n}=s,t=await this.getApiDefinition(n,i);if(!t.success)return t.response;const{definition:e}=t;return{content:[{type:"text",text:JSON.stringify({name:e.info?.title,version:e.info?.version,securitySchemes:e.components?.securitySchemes||[],security:e.security||[]},null,2)}]}}}export{p as GetSecuritySchemesTool};
@@ -1 +1 @@
1
- import{createMcpRequestHandler as D}from"./mcp-request-handler.js";import{createDocsMcpServer as v}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as h}from"../utils.js";import{createInternalServerError as y}from"./errors.js";import{McpServerType as m}from"../constants.js";import{telemetry as f}from"../../../telemetry/index.js";import{constructInvalidTokenResponse as A,constructUnauthorizedResponse as L,handleMcpAuth as S,shouldHandleMcpAuth as b}from"../auth/auth-handlers.js";async function I(r,s,i,n){try{f.initialize();const e=s,t=e?.props?.config?.apiDescriptionsMap||{},a=e?.props?.outdir||"",o=e?.props?.config?.mcpDocsServerName||"Docs MCP server",u=new URL(n.url).origin,{user:c,config:{rbac:p={},mcp:l={}}}=r,d=h(t,c,p,r.config.requiresLogin||!1),g=l.docs?.name||o,M={rbac:p,email:c?.email,teams:c?.teams,isAuthenticated:!!c?.isAuthenticated,requiresLogin:r.config.requiresLogin||!1};return await v({name:g,baseUrl:u,headers:i,apiDescriptionsMap:d,outdir:a,accessInfo:M})}catch(e){throw f.sendMcpErrorMessage({server_type:m.Docs,message:e?.message||"",stack:e?.stack||""}),y(e?.message||"Internal server error mcp docs")}}const R=D({createServerInstance:I,serverType:m.Docs}),w=async(r,s,i)=>{const n=!!s?.config?.requiresLogin,e=s?.config?.rbac;if(b(n,e)){const{isAuthenticated:t,isTokenValid:a,currentUser:o}=await S(r,s);if(!t)return L(new URL(r.url).origin);if(!a)return A();o&&(s.user=o)}return R(r,s,i)};var E=w;export{E as default};
1
+ import{createMcpRequestHandler as v}from"./mcp-request-handler.js";import{createDocsMcpServer as D}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as h}from"../utils.js";import{createInternalServerError as y}from"./errors.js";import{McpServerType as m}from"../constants.js";import{telemetry as f}from"../../../telemetry/index.js";import{constructInvalidTokenResponse as b,constructUnauthorizedResponse as A,handleMcpAuth as L,shouldHandleMcpAuth as S}from"../auth/auth-handlers.js";async function I(r,s,i,n){try{f.initialize();const e=s,t=e?.props?.config?.apiDescriptionsMap||{},a=e?.props?.outdir||"",o=e?.props?.config?.mcpDocsServerName||"Docs MCP server",u=new URL(n.url).origin,{user:c,config:{rbac:p={},mcp:l={}}}=r,d=h(t,c,p,r.config.requiresLogin||!1),g=l.docs?.name||o,M={rbac:p,email:c?.email,teams:c?.teams,isAuthenticated:!!c?.isAuthenticated,requiresLogin:r.config.requiresLogin||!1};return await D({name:g,baseUrl:u,headers:i,apiDescriptionsMap:d,outdir:a,accessInfo:M})}catch(e){throw f.sendMcpErrorMessage([{object:"mcp_server",server_type:m.Docs,message:e?.message||"",stack:e?.stack||""}]),y(e?.message||"Internal server error mcp docs")}}const R=v({createServerInstance:I,serverType:m.Docs}),w=async(r,s,i)=>{const n=!!s?.config?.requiresLogin,e=s?.config?.rbac;if(S(n,e)){const{isAuthenticated:t,isTokenValid:a,currentUser:o}=await L(r,s);if(!t)return A(new URL(r.url).origin);if(!a)return b();o&&(s.user=o)}return R(r,s,i)};var E=w;export{E as default};
@@ -1 +1 @@
1
- import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as s,McpServerType as d}from"../constants.js";class n extends Error{code;data;requestId;constructor(e,t,o,a){super(t),this.name="McpError",this.code=e,this.data=o,this.requestId=a}createErrorResponse(){const e={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},t=i(this.code);return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}}function i(r){switch(r){case s.InvalidRequest:case s.InvalidParams:return 400;case s.MethodNotFound:return 404;case s.ServerError:return 405;case s.InternalError:default:return 500}}function m(r){return new n(s.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function u(r,e=d.Docs,t){const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;return c.sendMcpErrorMessage({server_type:e,message:o,stack:a||""}),new n(s.InternalError,"Internal server error mcp",o,t).createErrorResponse()}function f(r="Invalid request",e){return new n(s.InvalidRequest,r,void 0,e).createErrorResponse()}function h(r="Invalid parameters",e){return new n(s.InvalidParams,r,void 0,e).createErrorResponse()}async function v(r,e,t){try{return await r()}catch(o){return c.sendMcpErrorMessage({server_type:e,message:o?.message||"",stack:o?.stack||""}),t&&t(),u(o,e)}}export{n as McpError,u as createInternalServerError,h as createInvalidParamsError,f as createInvalidRequestError,m as createMethodNotAllowedError,v as withErrorHandling};
1
+ import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as s,McpServerType as d}from"../constants.js";class n extends Error{code;data;requestId;constructor(e,t,o,a){super(t),this.name="McpError",this.code=e,this.data=o,this.requestId=a}createErrorResponse(){const e={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},t=i(this.code);return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}}function i(r){switch(r){case s.InvalidRequest:case s.InvalidParams:return 400;case s.MethodNotFound:return 404;case s.ServerError:return 405;case s.InternalError:default:return 500}}function m(r){return new n(s.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function p(r,e=d.Docs,t){const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;return c.sendMcpErrorMessage([{object:"mcp_server",server_type:e,message:o,stack:a||""}]),new n(s.InternalError,"Internal server error mcp",o,t).createErrorResponse()}function f(r="Invalid request",e){return new n(s.InvalidRequest,r,void 0,e).createErrorResponse()}function h(r="Invalid parameters",e){return new n(s.InvalidParams,r,void 0,e).createErrorResponse()}async function v(r,e,t){try{return await r()}catch(o){return c.sendMcpErrorMessage([{object:"mcp_server",server_type:e,message:o?.message||"",stack:o?.stack||""}]),t&&t(),p(o,e)}}export{n as McpError,p as createInternalServerError,h as createInvalidParamsError,f as createInvalidRequestError,m as createMethodNotAllowedError,v as withErrorHandling};
@@ -1 +1 @@
1
- import{McpServer as t}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as s}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{telemetry as i}from"../../../telemetry/index.js";class p{server;transport;#r;#t=!1;constructor(e){this.server=new t(e,{capabilities:{logging:{}}}),this.transport=new s({sessionIdGenerator:void 0})}async initialize(){return this.registerTools(),await this.server.connect(this.transport),{server:this.server,transport:this.transport,cleanup:this.cleanup.bind(this)}}clearCleanupTimeout(){this.#r&&(clearTimeout(this.#r),this.#r=void 0)}#e;async cleanup(){return this.#e?this.#e:(this.#e=this.#s(),this.#e)}async#s(){if(!this.#t){this.#t=!0,this.clearCleanupTimeout();try{this.transport.close()}catch(e){throw i.sendMcpErrorMessage({server_type:this.getServerType(),message:e?.message||"Unknown cleanup error",stack:e?.stack||""}),e}}}}async function h(r,...e){return await new r(...e).initialize()}export{p as BaseMcpServer,h as createMcpServerInstance};
1
+ import{McpServer as t}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as s}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{telemetry as i}from"../../../telemetry/index.js";class p{server;transport;#r;#t=!1;constructor(e){this.server=new t(e,{capabilities:{logging:{}}}),this.transport=new s({sessionIdGenerator:void 0})}async initialize(){return this.registerTools(),await this.server.connect(this.transport),{server:this.server,transport:this.transport,cleanup:this.cleanup.bind(this)}}clearCleanupTimeout(){this.#r&&(clearTimeout(this.#r),this.#r=void 0)}#e;async cleanup(){return this.#e?this.#e:(this.#e=this.#s(),this.#e)}async#s(){if(!this.#t){this.#t=!0,this.clearCleanupTimeout();try{this.transport.close()}catch(e){throw i.sendMcpErrorMessage([{object:"mcp_server",server_type:this.getServerType(),message:e?.message||"Unknown cleanup error",stack:e?.stack||""}]),e}}}}async function h(r,...e){return await new r(...e).initialize()}export{p as BaseMcpServer,h as createMcpServerInstance};
@@ -13,6 +13,6 @@ export declare function joinWithSeparator(base?: string, path?: string, sep?: st
13
13
  export declare function parsePartials(partials?: Record<string, any>): Record<string, Node | Node[]> | undefined;
14
14
  export declare function usePatchedStore(storeJs: OpenAPIDocsStore, { markdown, baseSlug }: PageProps): OpenAPIDocsStore;
15
15
  export declare function safeParseFunction(fnInput: EventFunctionInput): ((event: EventType) => void) | null;
16
- export declare function mergeEvents(userFunction: ((event: EventType) => void) | null, telemetryEvent?: AsyncApiRealmUI.GetEventData<'openapi_docs'>['eventType']): (event: EventType) => void;
16
+ export declare function mergeEvents(userFunction: ((event: EventType) => void) | null, telemetryEvent?: AsyncApiRealmUI.GetEventData<'openapi_docs'>[number]['eventType']): (event: EventType) => void;
17
17
  export {};
18
18
  //# sourceMappingURL=helpers.d.ts.map
@@ -1,5 +1,5 @@
1
- import{useMemo as u}from"react";import{components as l}from"@redocly-markdoc/components";import{Ast as f}from"@markdoc/markdoc";import{PageNavigation as g}from"@redocly/theme/components/PageNavigation/PageNavigation";import{tags as d,components as h}from"@redocly/theme/markdoc/default";import{Breadcrumbs as _}from"@redocly/theme/components/Breadcrumbs/Breadcrumbs";import{withPathPrefix as m}from"@redocly/theme/core/utils";import{OPENAPI_DOCS_TEMPLATE_ID as y,ServerRoutes as w}from"../../../../constants/common.js";import{isBrowser as P}from"../../../../utils/env/is-browser.js";import*as S from"../../markdown/markdoc/custom-components/index.js";import*as v from"../../markdown/markdoc/nodes/index.js";import O from"../../markdown/markdoc/tags/index.js";import{usePageData as C,useSidebarSiblingsData as A}from"../../../../client/providers/page-data/hooks";import{telemetry as E}from"../../../../client/app/telemetry/index.js";import{getMockServerDocsConfig as T}from"./mock-server-config";function V(t="",r="",o="/"){return t.endsWith(o)&&(t=t.slice(0,-o.length)),r.startsWith(o)&&(r=r.slice(o.length)),!t||!r?t+r:t+o+r}function b(t){if(t)return Object.entries(t).reduce((r,[o,e])=>(r[o]=f.fromJSON(JSON.stringify(e)),r),{})}function Y(t,{markdown:r,baseSlug:o}){return u(()=>{const n=P();t.options.oAuth2RedirectURI=n?`${window.location.origin}${m(w.REPLAY_OAUTH2_CALLBACK)}`:null,t.options.routingBasePath=m(o),t.options.mockServer=T(t.options.mockServer,o),t.options.scrollYOffset=n?parseInt(getComputedStyle(document.documentElement).getPropertyValue("--navbar-height"),10):0,t.options.markdocOptions={tags:{...O,...d},nodes:{...v},components:{...S,...h,...l,...globalThis.__LOADER.markdocComponents},...r,partials:b(r?.partials)},t.options.unstable_hooks={...t.options.unstable_hooks,MiddlePanelFooter:()=>{const{templateId:i}=C()||{},{nextPage:s,prevPage:a}=A()||{};return i===y?null:g({nextPage:s,prevPage:a})},MiddlePanelHeader:()=>_({})};const p={codeSamplesLanguageSwitch:"samples_language_switch",codeSamplesCopy:"code_samples_copy",panelToggle:"panel_toggle",targetServerSwitch:"target_server_switch",tryItOpen:"try_it_toggle",tryItSent:"try_it_sent"},c={};for(const[i,s]of Object.entries(p)){const a=F(t.options.events?.[i]);c[i]=I(a,s)}return t.options.events=c,t},[t,r,o])}function F(t){if(typeof window>"u")return null;if(typeof t=="function")return t;if(typeof t!="string")return null;try{const r=t.trim();if(!r.match(/^(\([^)]*\)\s*=>\s*.+|[a-zA-Z_$][\w$]*\s*=>\s*.+)$/))throw new Error("Invalid function format. Only arrow functions allowed.");if(["eval","Function","constructor","prototype","__proto__","import","require","process","global","window","document"].some(n=>r.includes(n)))throw new Error("Function contains prohibited keywords");return new Function("event",`
1
+ import{useMemo as u}from"react";import{components as l}from"@redocly-markdoc/components";import{Ast as f}from"@markdoc/markdoc";import{PageNavigation as d}from"@redocly/theme/components/PageNavigation/PageNavigation";import{tags as g,components as _}from"@redocly/theme/markdoc/default";import{Breadcrumbs as h}from"@redocly/theme/components/Breadcrumbs/Breadcrumbs";import{withPathPrefix as m}from"@redocly/theme/core/utils";import{OPENAPI_DOCS_TEMPLATE_ID as y,ServerRoutes as w}from"../../../../constants/common.js";import{isBrowser as P}from"../../../../utils/env/is-browser.js";import*as S from"../../markdown/markdoc/custom-components/index.js";import*as v from"../../markdown/markdoc/nodes/index.js";import O from"../../markdown/markdoc/tags/index.js";import{usePageData as C,useSidebarSiblingsData as A}from"../../../../client/providers/page-data/hooks";import{telemetry as E}from"../../../../client/app/telemetry/index.js";import{getMockServerDocsConfig as T}from"./mock-server-config";function V(t="",e="",o="/"){return t.endsWith(o)&&(t=t.slice(0,-o.length)),e.startsWith(o)&&(e=e.slice(o.length)),!t||!e?t+e:t+o+e}function b(t){if(t)return Object.entries(t).reduce((e,[o,r])=>(e[o]=f.fromJSON(JSON.stringify(r)),e),{})}function Y(t,{markdown:e,baseSlug:o}){return u(()=>{const n=P();t.options.oAuth2RedirectURI=n?`${window.location.origin}${m(w.REPLAY_OAUTH2_CALLBACK)}`:null,t.options.routingBasePath=m(o),t.options.mockServer=T(t.options.mockServer,o),t.options.scrollYOffset=n?parseInt(getComputedStyle(document.documentElement).getPropertyValue("--navbar-height"),10):0,t.options.markdocOptions={tags:{...O,...g},nodes:{...v},components:{...S,..._,...l,...globalThis.__LOADER.markdocComponents},...e,partials:b(e?.partials)},t.options.unstable_hooks={...t.options.unstable_hooks,MiddlePanelFooter:()=>{const{templateId:i}=C()||{},{nextPage:s,prevPage:a}=A()||{};return i===y?null:d({nextPage:s,prevPage:a})},MiddlePanelHeader:()=>h({})};const p={codeSamplesLanguageSwitch:"samples_language_switch",codeSamplesCopy:"code_samples_copy",panelToggle:"panel_toggle",targetServerSwitch:"target_server_switch",tryItOpen:"try_it_toggle",tryItSent:"try_it_sent"},c={};for(const[i,s]of Object.entries(p)){const a=F(t.options.events?.[i]);c[i]=I(a,s)}return t.options.events=c,t},[t,e,o])}function F(t){if(typeof window>"u")return null;if(typeof t=="function")return t;if(typeof t!="string")return null;try{const e=t.trim();if(!e.match(/^(\([^)]*\)\s*=>\s*.+|[a-zA-Z_$][\w$]*\s*=>\s*.+)$/))throw new Error("Invalid function format. Only arrow functions allowed.");if(["eval","Function","constructor","prototype","__proto__","import","require","process","global","window","document"].some(n=>e.includes(n)))throw new Error("Function contains prohibited keywords");return new Function("event",`
2
2
  'use strict';
3
- const userFn = ${r};
3
+ const userFn = ${e};
4
4
  return userFn(event);
5
- `)}catch(r){return console.error("Function parsing error:",r),null}}function I(t,r){return o=>{if(t)try{t(o)}catch(e){console.error("User event handler error:",e)}if(r)try{E.sendOpenapiDocsMessage({eventType:r,operationHttpVerb:o.operationHttpVerb,operationPath:o.operationPath,lang:"lang"in o?o.lang:void 0,action:o.action,state:"state"in o?o.state:void 0,serverUrl:"serverUrl"in o?o.serverUrl:void 0})}catch{}}}export{V as joinWithSeparator,I as mergeEvents,b as parsePartials,F as safeParseFunction,Y as usePatchedStore};
5
+ `)}catch(e){return console.error("Function parsing error:",e),null}}function I(t,e){return o=>{if(t)try{t(o)}catch(r){console.error("User event handler error:",r)}if(e)try{E.sendOpenapiDocsMessage([{object:"openapi_docs",eventType:e,operationHttpVerb:o.operationHttpVerb,operationPath:o.operationPath,lang:"lang"in o?o.lang:void 0,action:o.action,state:"state"in o?o.state:void 0,serverUrl:"serverUrl"in o?o.serverUrl:void 0}])}catch{}}}export{V as joinWithSeparator,I as mergeEvents,b as parsePartials,F as safeParseFunction,Y as usePatchedStore};
@@ -1,4 +1,4 @@
1
- import a from"picomatch";import{dirname as $,resolve as x}from"node:path";import{access as E,readFile as F,constants as P}from"fs/promises";import{removeTrailingSlash as w}from"../../../../utils/url/remove-trailing-slash.js";import{logger as I}from"../../../tools/notifiers/logger.js";const l="llms.txt",u="Table of contents";async function g(e,t,n={title:l,description:void 0},o){if(!t)return{title:n.title||l,description:n.description,details:void 0,sections:[{title:u,description:void 0,llmstxts:e}]};const s=t.title||n.title||l,r=t.description||n.description,i=await y(t,o),c=t.sections?.map(d=>{const{title:f,description:h,excludeFiles:L,includeFiles:m}=d,T=p(e,{excludeFiles:L,includeFiles:m});return{title:f,description:h,llmstxts:T}});return{title:s,description:r,details:i,sections:c||[{title:u,description:void 0,llmstxts:p(e,{includeFiles:["**/*"],excludeFiles:[]})}]}}async function y(e,t){const n=await t.getConfig();if(e?.details?.path&&n.configPath)try{const o=t.fs.getFileInfo(n.configPath);if(!o)throw new Error(`Config file ${n.configPath} not found`);const s=x(t.fs.cwd,$(o.relativePath),e.details.path);return await E(s,P.R_OK),F(s,"utf-8")}catch{throw new Error(`${e.details.path} is not accessible`)}if(e?.details?.content)return e.details.content}function p(e,t){const{excludeFiles:n,includeFiles:o}=t,s=n?.map(i=>a(i)),r=o?.map(i=>a(i));return e.filter(i=>s?.some(d=>d(i.fsPath))?!1:r?.some(d=>d(i.fsPath)))}async function S(e,t,n={title:l,description:void 0},o){const s=await g(e,t,n,o),r=[`# ${s.title}
1
+ import a from"picomatch";import{dirname as $,resolve as x}from"node:path";import{access as P,readFile as E,constants as F}from"fs/promises";import{removeTrailingSlash as w}from"../../../../utils/url/remove-trailing-slash.js";import{logger as I}from"../../../tools/notifiers/logger.js";import{withPathPrefix as g}from"@redocly/theme/core/utils";const l="llms.txt",u="Table of contents";async function y(t,e,n={title:l,description:void 0},o){if(!e)return{title:n.title||l,description:n.description,details:void 0,sections:[{title:u,description:void 0,llmstxts:t}]};const s=e.title||n.title||l,r=e.description||n.description,i=await M(e,o),c=e.sections?.map(d=>{const{title:f,description:h,excludeFiles:L,includeFiles:m}=d,T=p(t,{excludeFiles:L,includeFiles:m});return{title:f,description:h,llmstxts:T}});return{title:s,description:r,details:i,sections:c||[{title:u,description:void 0,llmstxts:p(t,{includeFiles:["**/*"],excludeFiles:[]})}]}}async function M(t,e){const n=await e.getConfig();if(t?.details?.path&&n.configPath)try{const o=e.fs.getFileInfo(n.configPath);if(!o)throw new Error(`Config file ${n.configPath} not found`);const s=x(e.fs.cwd,$(o.relativePath),t.details.path);return await P(s,F.R_OK),E(s,"utf-8")}catch{throw new Error(`${t.details.path} is not accessible`)}if(t?.details?.content)return t.details.content}function p(t,e){const{excludeFiles:n,includeFiles:o}=e,s=n?.map(i=>a(i)),r=o?.map(i=>a(i));return t.filter(i=>s?.some(d=>d(i.fsPath))?!1:r?.some(d=>d(i.fsPath)))}async function N(t,e,n={title:l,description:void 0},o){const s=await y(t,e,n,o),r=[`# ${s.title}
2
2
 
3
3
  `];return s.description&&r.push(`> ${s.description}
4
4
 
@@ -8,6 +8,6 @@ import a from"picomatch";import{dirname as $,resolve as x}from"node:path";import
8
8
  `),i.description?r.push(`${i.description.replace(/\n+$/,"")}
9
9
 
10
10
  `):r.push(`
11
- `),i.llmstxts.forEach(c=>{r.push(` - ${M({title:c.title,description:c.description,slug:v(c.slug)})}`)}),r.push(`
12
- `)}),r.join("")}function M({title:e,description:t,slug:n}){return`[${e}](${w(process.env.REDOCLY_PUBLIC_URL||"")}${encodeURI(n)})${t?`: ${t}`:""}
13
- `}function A(e){if(e?.details?.path&&e?.details?.content)throw new Error('"details.path" and "details.content" are mutually exclusive. Please use only one of them.')}function v(e){return`${e}${e==="/"?"index.html.md":".md"}`}export{S as generateLLMsTxt,v as getLLMsTxtMdSlug,M as llmsTxtLink,A as validateLLMsTxtConfig};
11
+ `),i.llmstxts.forEach(c=>{r.push(` - ${v({title:c.title,description:c.description,slug:_(c.slug)})}`)}),r.push(`
12
+ `)}),r.join("")}function v({title:t,description:e,slug:n}){return`[${t}](${w(process.env.REDOCLY_PUBLIC_URL||"")}${encodeURI(g(n))})${e?`: ${e}`:""}
13
+ `}function H(t){if(t?.details?.path&&t?.details?.content)throw new Error('"details.path" and "details.content" are mutually exclusive. Please use only one of them.')}function _(t){return`${t}${t==="/"?"index.html.md":".md"}`}export{N as generateLLMsTxt,_ as getLLMsTxtMdSlug,v as llmsTxtLink,H as validateLLMsTxtConfig};
@@ -1,2 +1,2 @@
1
1
  import{telemetry as a}from"../../telemetry/index.js";import{isProductionMode as c}from"../../utils/envs/is-production-mode.js";import l,{LogLevel as r,shouldLog as h,parseLogLevel as u}from"./formatter.js";import{isVirtualFile as f}from"../../fs/utils/isVirtualFile.js";import{TerminalManager as p}from"./terminal-manager.js";import{isDevelopMode as g}from"../../utils/envs/is-develop-mode.js";class d{#e;#l;#i;#n;#r=new Map;#o=new Map;constructor({context:t,forceNonInteractive:e,minLogLevel:i}={}){this.#e=t,this.#l=c(),this.#i=new p(e),this.#n=i??u(process.env.REDOCLY_LOG_LEVEL)??(g()?r.INFO:r.HTTP)}shouldLog(t){return h(t,this.#n)}info(t,...e){this.#t({level:r.INFO,message:t,args:e})}infoTime(t,e,...i){return this.#s(r.INFO,e,t,...i)}success(t,...e){this.#t({level:r.SUCCESS,message:t,args:e})}logInFooter(t,e,...i){const o=l.interpolate(e,...i)+`
2
- `;this.isInteractive()||this.#i.isFooterChanged(t,o)&&this.#t({level:r.INFO,message:e,args:i}),this.#i.updateFooter(t,o)}successTime(t,e,...i){return this.#s(r.SUCCESS,e,t,...i)}warn(t,...e){this.#t({level:r.WARN,message:t,args:e})}warnProd(t,...e){this.#l?this.warn(t,...e):this.verbose(t,...e)}error(t,...e){this.#t({level:r.ERROR,message:t,args:e})}contentError(t,...e){this.#t({level:r.ERROR,message:t,scope:"content",args:e})}verbose(t,...e){this.#t({level:r.VERBOSE,message:t,args:e})}verboseTime(t,e,...i){return this.#s(r.VERBOSE,e,t,...i)}httpTime(t){return this.#s(r.HTTP,"",t)}startTiming(t){const e=t||Symbol();this.#r.set(e,performance.now());const i=setTimeout(()=>{this.#r.delete(e),this.#o.delete(e)},500*1e3);return this.#o.set(e,i),e}updateContext(t){this.#e={...this.#e,...t}}clearAllTimeouts(){for(const t of this.#o.values())clearTimeout(t);this.#o.clear()}isInteractive(){return this.#i.isInteractive()}warnForRealFile(t,e,i,...o){f(e,i)||this.warn(t,e,...o)}#s(t,e,i,...o){const n=this.#r.get(i);if(!n)return;const s=Math.round(performance.now()-n);return this.#r.delete(i),this.#t({level:t,message:e,duration:s,args:o}),{message:e,timeMs:s}}#t({level:t,message:e,duration:i,scope:o,args:n}){if(!h(t,this.#n))return;let s=e&&l.interpolate(e,...n);s&&i!=null&&t!==r.VERBOSE&&a.sendTimingPerformedMessage({timeMs:i,message:s});const m={level:t,message:s,duration:i,scope:o,context:this.#e};process.stderr.write(l.format(m))}}const O=new d;export{d as Logger,O as logger};
2
+ `;this.isInteractive()||this.#i.isFooterChanged(t,o)&&this.#t({level:r.INFO,message:e,args:i}),this.#i.updateFooter(t,o)}successTime(t,e,...i){return this.#s(r.SUCCESS,e,t,...i)}warn(t,...e){this.#t({level:r.WARN,message:t,args:e})}warnProd(t,...e){this.#l?this.warn(t,...e):this.verbose(t,...e)}error(t,...e){this.#t({level:r.ERROR,message:t,args:e})}contentError(t,...e){this.#t({level:r.ERROR,message:t,scope:"content",args:e})}verbose(t,...e){this.#t({level:r.VERBOSE,message:t,args:e})}verboseTime(t,e,...i){return this.#s(r.VERBOSE,e,t,...i)}httpTime(t){return this.#s(r.HTTP,"",t)}startTiming(t){const e=t||Symbol();this.#r.set(e,performance.now());const i=setTimeout(()=>{this.#r.delete(e),this.#o.delete(e)},500*1e3);return this.#o.set(e,i),e}updateContext(t){this.#e={...this.#e,...t}}clearAllTimeouts(){for(const t of this.#o.values())clearTimeout(t);this.#o.clear()}isInteractive(){return this.#i.isInteractive()}warnForRealFile(t,e,i,...o){f(e,i)||this.warn(t,e,...o)}#s(t,e,i,...o){const n=this.#r.get(i);if(!n)return;const s=Math.round(performance.now()-n);return this.#r.delete(i),this.#t({level:t,message:e,duration:s,args:o}),{message:e,timeMs:s}}#t({level:t,message:e,duration:i,scope:o,args:n}){if(!h(t,this.#n))return;let s=e&&l.interpolate(e,...n);s&&i!=null&&t!==r.VERBOSE&&a.sendTimingPerformedMessage([{object:"timing",timeMs:i,message:s}]);const m={level:t,message:s,duration:i,scope:o,context:this.#e};process.stderr.write(l.format(m))}}const O=new d;export{d as Logger,O as logger};
@@ -1,12 +1,12 @@
1
- import{isBuildMode as h}from"../../utils/envs/is-build-mode.js";import{logger as e}from"../../tools/notifiers/logger.js";import P from"./formatter.js";import{blue as g,gray as p,red as a}from"./helpers/colors.js";import{isVirtualFile as b}from"../../fs/utils/isVirtualFile.js";import{telemetry as u}from"../../telemetry/index.js";import{shutdowner as f}from"../shutdowner.js";const c=30;class C{#r=[];#o=[];#e=new Map;#t=[];pushError(r,t,...o){const n=P.interpolate(r,...o);this.#r.push({severity:t,message:n,type:"ERROR"})}reportBrokenLink(r){this.#r.push(r)}reportCompilationError(r){const t=`${r.message}::${r.sourceFileRelativePath}::${r?.sourceFileLocation?.line}`;this.#e.has(t)||this.#e.set(t,r)}reportPageRenderError(r){this.#t.push(r)}async panicOnBuild(r,...t){r instanceof Error&&(r=r.message+`
2
- `+r.stack),h()?await this.panic(r,...t):this.pushError(r,"PANIC",...t)}async panicOnBuildContentErrorForRealFile(r,t,o,...n){b(t,o)||await this.panicOnBuildContentError(r,...n)}async panicOnBuildContentError(r,...t){r instanceof Error&&(r=r.message+`
1
+ import{isBuildMode as h}from"../../utils/envs/is-build-mode.js";import{logger as e}from"../../tools/notifiers/logger.js";import P from"./formatter.js";import{blue as b,gray as p,red as c}from"./helpers/colors.js";import{isVirtualFile as g}from"../../fs/utils/isVirtualFile.js";import{telemetry as u}from"../../telemetry/index.js";import{shutdowner as f}from"../shutdowner.js";const a=30;class C{#r=[];#o=[];#e=new Map;#t=[];pushError(r,t,...o){const i=P.interpolate(r,...o);this.#r.push({severity:t,message:i,type:"ERROR"})}reportBrokenLink(r){this.#r.push(r)}reportCompilationError(r){const t=`${r.message}::${r.sourceFileRelativePath}::${r?.sourceFileLocation?.line}`;this.#e.has(t)||this.#e.set(t,r)}reportPageRenderError(r){this.#t.push(r)}async panicOnBuild(r,...t){r instanceof Error&&(r=r.message+`
2
+ `+r.stack),h()?await this.panic(r,...t):this.pushError(r,"PANIC",...t)}async panicOnBuildContentErrorForRealFile(r,t,o,...i){g(t,o)||await this.panicOnBuildContentError(r,...i)}async panicOnBuildContentError(r,...t){r instanceof Error&&(r=r.message+`
3
3
  `+r.stack),h()?await this.panicOnContentError(r,...t):this.pushError(r,"PANIC",...t)}async panic(r,...t){let o;r instanceof Error?(o=r,r=r.message+`
4
- `+r.stack):o=new Error(r),e.error(r,...t),u.sendCliErrorCaughtMessage({message:r}),await f.exitWithCode(1,o)}async panicOnContentError(r,...t){let o;r instanceof Error?(o=r,r=r.message+`
5
- `+r.stack):o=new Error(r),e.contentError(r,...t),u.sendCliErrorCaughtMessage({message:r,scope:"content"}),await f.exitWithCode(1,o)}reportMarkdocProblem(r){this.#o.push(r)}clearErrors(){this.#r=[]}clearMarkdocProblems(){this.#o=[]}clearEsbuildProblems(){this.#e.clear()}clearPageRenderProblems(){this.#t=[]}getCompilationProblem(r){return this.#e.get(r)}getCompilationProblems(){return[...this.#e.values()]}getPageRenderProblems(){return this.#t}getPageRenderProblem(r){return this.#t.find(t=>t.sourceFileRelativePath===r)}getProblems(){return[...this.#r,...this.getCompilationProblems(),...this.#o,...this.#t]}summary(r,t=0){const o=this.getProblems(),n=this.#o.filter(l=>l.type==="BROKEN_LINK").length,s=this.#r.filter(l=>l.type==="BROKEN_LINK").length,m=this.#o.length-n,E=this.#r.length-s+this.getCompilationProblems().length+this.#t.length;return e.logInFooter("validate",o.length?a(" \u274C Status: %s markdoc errors, %s broken links, %s other errors"):" \u2705 Status: No errors found",m,n+s,E),t!==0&&e.logInFooter("pages",` \u{1F4C4} Total pages: ${t}`),e.logInFooter("timing",r),e.logInFooter("validate-sep",""),e.isInteractive()&&(o.length?e.logInFooter("actions","Press (e) to print all errors, (q) to quit"):e.logInFooter("actions",p("Press (q) to quit"))),o}printErrors(r=[]){const t=this.#r.length,o=r.length?r:this.getProblems();let n=0;for(const s of o.slice(0,c))n>=t?e.contentError(a(`[${++n}] `)+d(s)):e.error(a(`[${++n}] `)+d(s));o.length>c&&e.error(`... and ${o.length-c} more errors`)}listenStdin(){if(!e.isInteractive())return;process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf8");const r=this.printErrors.bind(this);process.stdin.on("data",function(t){if(t===""&&process.exit(),t==="\x7F"){process.stdout.write("\b \b");return}if(t==="\r"){process.stdout.write(`
6
- `);return}if(t==="e"){r();return}t==="q"&&process.exit(0)})}}const B=new C;function d(i){const r=i.sourceFileLocation,t=r?`:${r.line}:${r.character??1}`:"";return i.message+(i.codeframe?`
4
+ `+r.stack):o=new Error(r),e.error(r,...t),u.sendCliErrorCaughtMessage([{object:"cli",message:r}]),await f.exitWithCode(1,o)}async panicOnContentError(r,...t){let o;r instanceof Error?(o=r,r=r.message+`
5
+ `+r.stack):o=new Error(r),e.contentError(r,...t),u.sendCliErrorCaughtMessage([{object:"cli",message:r,scope:"content"}]),await f.exitWithCode(1,o)}reportMarkdocProblem(r){this.#o.push(r)}clearErrors(){this.#r=[]}clearMarkdocProblems(){this.#o=[]}clearEsbuildProblems(){this.#e.clear()}clearPageRenderProblems(){this.#t=[]}getCompilationProblem(r){return this.#e.get(r)}getCompilationProblems(){return[...this.#e.values()]}getPageRenderProblems(){return this.#t}getPageRenderProblem(r){return this.#t.find(t=>t.sourceFileRelativePath===r)}getProblems(){return[...this.#r,...this.getCompilationProblems(),...this.#o,...this.#t]}summary(r,t=0){const o=this.getProblems(),i=this.#o.filter(l=>l.type==="BROKEN_LINK").length,s=this.#r.filter(l=>l.type==="BROKEN_LINK").length,m=this.#o.length-i,E=this.#r.length-s+this.getCompilationProblems().length+this.#t.length;return e.logInFooter("validate",o.length?c(" \u274C Status: %s markdoc errors, %s broken links, %s other errors"):" \u2705 Status: No errors found",m,i+s,E),t!==0&&e.logInFooter("pages",` \u{1F4C4} Total pages: ${t}`),e.logInFooter("timing",r),e.logInFooter("validate-sep",""),e.isInteractive()&&(o.length?e.logInFooter("actions","Press (e) to print all errors, (q) to quit"):e.logInFooter("actions",p("Press (q) to quit"))),o}printErrors(r=[]){const t=this.#r.length,o=r.length?r:this.getProblems();let i=0;for(const s of o.slice(0,a))i>=t?e.contentError(c(`[${++i}] `)+d(s)):e.error(c(`[${++i}] `)+d(s));o.length>a&&e.error(`... and ${o.length-a} more errors`)}listenStdin(){if(!e.isInteractive())return;process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding("utf8");const r=this.printErrors.bind(this);process.stdin.on("data",function(t){if(t===""&&process.exit(),t==="\x7F"){process.stdout.write("\b \b");return}if(t==="\r"){process.stdout.write(`
6
+ `);return}if(t==="e"){r();return}t==="q"&&process.exit(0)})}}const B=new C;function d(n){const r=n.sourceFileLocation,t=r?`:${r.line}:${r.character??1}`:"";return n.message+(n.codeframe?`
7
7
 
8
- `+i.codeframe+`
8
+ `+n.codeframe+`
9
9
 
10
10
  `:`
11
- `)+(i.sourceFileRelativePath?p(`at ${g("./"+i.sourceFileRelativePath)}${t}`)+`
11
+ `)+(n.sourceFileRelativePath?p(`at ${b("./"+n.sourceFileRelativePath)}${t}`)+`
12
12
  `:"")}export{C as Reporter,B as reporter};
@@ -65,6 +65,71 @@ export declare const normalizeRbacConfig: (rbacConfig: RbacConfig) => {
65
65
  reunite?: {
66
66
  [x: string]: string;
67
67
  } | undefined;
68
+ entitiesCatalog?: {
69
+ catalogs?: {
70
+ [x: string]: unknown;
71
+ all?: {
72
+ [x: string]: string;
73
+ } | undefined;
74
+ services?: {
75
+ [x: string]: string;
76
+ } | undefined;
77
+ domains?: {
78
+ [x: string]: string;
79
+ } | undefined;
80
+ teams?: {
81
+ [x: string]: string;
82
+ } | undefined;
83
+ users?: {
84
+ [x: string]: string;
85
+ } | undefined;
86
+ apiDescriptions?: {
87
+ [x: string]: string;
88
+ } | undefined;
89
+ dataSchemas?: {
90
+ [x: string]: string;
91
+ } | undefined;
92
+ apiOperations?: {
93
+ [x: string]: string;
94
+ } | undefined;
95
+ } | undefined;
96
+ entities?: {
97
+ [x: string]: unknown;
98
+ "**"?: {
99
+ [x: string]: string;
100
+ } | undefined;
101
+ } | undefined;
102
+ entitiesTypes?: {
103
+ [x: string]: unknown;
104
+ user?: {
105
+ [x: string]: string;
106
+ } | undefined;
107
+ service?: {
108
+ [x: string]: string;
109
+ } | undefined;
110
+ domain?: {
111
+ [x: string]: string;
112
+ } | undefined;
113
+ team?: {
114
+ [x: string]: string;
115
+ } | undefined;
116
+ apiDescription?: {
117
+ [x: string]: string;
118
+ } | undefined;
119
+ apiOperation?: {
120
+ [x: string]: string;
121
+ } | undefined;
122
+ dataSchema?: {
123
+ [x: string]: string;
124
+ } | undefined;
125
+ } | undefined;
126
+ entitiesGroups?: {
127
+ entities?: string[] | undefined;
128
+ config?: {
129
+ [x: string]: string;
130
+ } | undefined;
131
+ }[] | undefined;
132
+ } | undefined;
68
133
  content?: {
69
134
  [x: string]: unknown;
70
135
  "**"?: {
@@ -1,7 +1,7 @@
1
- import"../node-crypto-polyfill.js";import{DOMParser as U}from"@xmldom/xmldom";import{SignedXml as B}from"xml-crypto";import F from"xpath";import{deflateSync as J,inflateSync as q}from"fflate";import{createHash as H}from"crypto";import{ulid as W}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as K}from"@redocly/config";import{AUTH_URL as Q,JWT_SECRET_KEY as _}from"../constants/common.js";import{getPathPrefix as X,withPathPrefix as Y}from"@redocly/theme/core/utils";import{DEFAULT_AUTHENTICATED_TEAM as G,REQUIRED_OIDC_SCOPES as D,ServerRoutes as P}from"../../constants/common.js";import{appendQueryParams as Z}from"../../utils/url/append-query-params.js";import{logger as ee}from"../tools/notifiers/logger.js";import{randomString as te}from"../utils/crypto/random-string.js";import{randomUUID as R}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as I,JwtTokenExpired as ne}from"./jwt/types.js";import*as p from"./jwt/jwt.js";import{parseTeamClaimToArray as re}from"../utils/index.js";import{arrayBufferToBase64 as ae,decodeBase64 as v,encodeBase64URL as oe,urlSafeBase64 as j}from"./jwt/encode.js";import{formatSamlCertificate as se}from"./utils/format-saml-certificate.js";function N(e){return e?.type===u.OIDC}function ie(e){return e?.type===u.SAML2}async function ze(e,t){if(N(t))return ce(e,t);if(ie(t))return ue(e,t)}async function ce(e,t){const n=await V(e,t),r=new Set((t.scopes||[]).concat(D)),a=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:n.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(r).join(" "),extraParams:a,pkce:t.pkce}}function ue(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function Be(e,t,n,r,a={}){const o=new Set((r.scopes||[]).concat(D));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:r.clientId,scope:Array.from(o).join(" "),code:t,redirect_uri:E(n),grant_type:"authorization_code",...r.clientSecret?{client_secret:r.clientSecret}:{},...a}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function de(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:a,extraParams:o,idpId:s,pkce:l},m,A,w){if(!t||!n||!r||!a)return{loginUrl:void 0};const c=new URL(t),f=w?.redirectUriOverride??`${e}${Y(P.OIDC_CALLBACK)}`,S={state:R(),idpId:s,redirectUri:f,redirectTo:m,branch:w?.branchOverride??me(e),inviteCode:A,source:w?.sourceOverride??"portal"},h={};if(l){const d=j(te(50)),g=j(H("sha256").update(d).digest("base64")),x="S256";c.searchParams.append("code_challenge",g),c.searchParams.append("code_challenge_method",x),h.code_verifier={value:d,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:X()||"/"}}}c.searchParams.append("client_id",n),c.searchParams.append("scope",a),c.searchParams.append("response_type",r),c.searchParams.append("redirect_uri",E(f)),c.searchParams.append("state",oe(JSON.stringify(S)));for(const d in o)o[d]!==void 0&&c.searchParams.append(d,o[d]);return{loginUrl:c.toString(),cookies:h}}function Fe(e,t,n,r){const a=new URL(e);return a.searchParams.append("post_logout_redirect_uri",t),r&&a.searchParams.append("state",r),a.searchParams.append("id_token_hint",n),a.toString()}async function Je(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return p.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,iat:t,exp:n},_)}async function qe(e){const{header:t,payload:n}=p.decode(e),a=Object.values(I).includes(t.alg)?t.alg:I.HS256;if(await p.verify(e,_,a),n.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!n.client_id||!n.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof n.exp=="number"&&Date.now()>=n.exp*1e3)throw new Error("Authorization code expired");return n}function He(e){const t=e||W(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcp_session",uri:`urn:redocly:realm:mcp:session:${n}`}}function E(e){return e.match(/^https:\/\/preview-[^\.]+--/)?"https://previewauth--"+e.split("--")[1]:e.match(/^(https:\/\/[^\.]+)--[^\.]+\.preview\./)?e.replace(/^(https:\/\/[^\.]+?)--[^\.]+\.preview\./,"$1.previewauth."):e}function me(e){return e.match(/^(https:\/\/[^\.]+)--([^\.]+)\.preview\./)?.[2]||void 0}function le(e){return e.type===u.OIDC}function pe(e){return e.type===u.SAML2}function We(e,t,n,r){return le(e)?de(t,e,n,r):pe(e)?fe(t,e,n,r):{}}function fe(e,t,n,r){const o=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
1
+ import"../node-crypto-polyfill.js";import{DOMParser as D}from"@xmldom/xmldom";import{SignedXml as B}from"xml-crypto";import F from"xpath";import{deflateSync as H,inflateSync as J}from"fflate";import{createHash as q}from"crypto";import{ulid as W}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as K}from"@redocly/config";import{AUTH_URL as Q,JWT_SECRET_KEY as I}from"../constants/common.js";import{getPathPrefix as X,withPathPrefix as Y}from"@redocly/theme/core/utils";import{DEFAULT_AUTHENTICATED_TEAM as G,REQUIRED_OIDC_SCOPES as N,ServerRoutes as P}from"../../constants/common.js";import{appendQueryParams as Z}from"../../utils/url/append-query-params.js";import{logger as ee}from"../tools/notifiers/logger.js";import{randomString as te}from"../utils/crypto/random-string.js";import{randomUUID as k}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as y,JwtTokenExpired as ne}from"./jwt/types.js";import*as p from"./jwt/jwt.js";import{parseTeamClaimToArray as re}from"../utils/index.js";import{arrayBufferToBase64 as ae,decodeBase64 as R,encodeBase64URL as oe,urlSafeBase64 as v}from"./jwt/encode.js";import{formatSamlCertificate as se}from"./utils/format-saml-certificate.js";function j(e){return e?.type===u.OIDC}function ie(e){return e?.type===u.SAML2}async function ze(e,t){if(j(t))return ce(e,t);if(ie(t))return ue(e,t)}async function ce(e,t){const r=await V(e,t),n=new Set((t.scopes||[]).concat(N)),a=t.authorizationRequestCustomParams||{};return{type:u.OIDC,idpId:e,name:"OAuth provider",authorizationEndpoint:r.authorization_endpoint,clientId:t.clientId,responseType:"code",scope:Array.from(n).join(" "),extraParams:a,pkce:t.pkce}}function ue(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function Be(e,t,r,n,a={}){const o=new Set((n.scopes||[]).concat(N));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:n.clientId,scope:Array.from(o).join(" "),code:t,redirect_uri:E(r),grant_type:"authorization_code",...n.clientSecret?{client_secret:n.clientSecret}:{},...a}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function de(e,{authorizationEndpoint:t,clientId:r,responseType:n,scope:a,extraParams:o,idpId:s,pkce:l},m,A,S){if(!t||!r||!n||!a)return{loginUrl:void 0};const c=new URL(t),f=S?.redirectUriOverride??`${e}${Y(P.OIDC_CALLBACK)}`,x={state:k(),idpId:s,redirectUri:f,redirectTo:m,branch:S?.branchOverride??me(e),inviteCode:A,source:S?.sourceOverride??"portal"},h={};if(l){const d=v(te(50)),_=v(q("sha256").update(d).digest("base64")),g="S256";c.searchParams.append("code_challenge",_),c.searchParams.append("code_challenge_method",g),h.code_verifier={value:d,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:X()||"/"}}}c.searchParams.append("client_id",r),c.searchParams.append("scope",a),c.searchParams.append("response_type",n),c.searchParams.append("redirect_uri",E(f)),c.searchParams.append("state",oe(JSON.stringify(x)));for(const d in o)o[d]!==void 0&&c.searchParams.append(d,o[d]);return{loginUrl:c.toString(),cookies:h}}function Fe(e,t,r,n){const a=new URL(e);return a.searchParams.append("post_logout_redirect_uri",t),n&&a.searchParams.append("state",n),a.searchParams.append("id_token_hint",r),a.toString()}async function He(e){const t=Math.floor(Date.now()/1e3),r=t+(e.ttlSec??600);return p.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,iat:t,exp:r},I,y.HS256)}async function Je(e){await p.verify(e,I,y.HS256);const{payload:t}=p.decode(e);if(t.type!=="mcp_auth_code")throw new Error("Invalid authorization code type");if(!t.client_id||!t.redirect_uri)throw new Error("Authorization code missing required claims");if(typeof t.exp=="number"&&Date.now()>=t.exp*1e3)throw new Error("Authorization code expired");return t}function qe(e){const t=e||W(),r=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:r,object:"mcp_session",uri:`urn:redocly:realm:mcp:session:${r}`}}function E(e){return e.match(/^https:\/\/preview-[^\.]+--/)?"https://previewauth--"+e.split("--")[1]:e.match(/^(https:\/\/[^\.]+)--[^\.]+\.preview\./)?e.replace(/^(https:\/\/[^\.]+?)--[^\.]+\.preview\./,"$1.previewauth."):e}function me(e){return e.match(/^(https:\/\/[^\.]+)--([^\.]+)\.preview\./)?.[2]||void 0}function le(e){return e.type===u.OIDC}function pe(e){return e.type===u.SAML2}function We(e,t,r,n){return le(e)?de(t,e,r,n):pe(e)?fe(t,e,r,n):{}}function fe(e,t,r,n){const o=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
2
2
  xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
3
3
  Version="2.0"
4
- ID="_${R()}"
4
+ ID="_${k()}"
5
5
  IssueInstant="${new Date().toISOString()}"
6
6
  AssertionConsumerServiceURL="${e}${P.SAML_CALLBACK}"
7
7
  AttributeConsumingServiceIndex="0">
@@ -9,4 +9,4 @@ import"../node-crypto-polyfill.js";import{DOMParser as U}from"@xmldom/xmldom";im
9
9
  <samlp:NameIDPolicy
10
10
  AllowCreate="true"
11
11
  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
12
- </samlp:AuthnRequest>`,s=he(o);return{loginUrl:Z(t.ssoUrl,{SAMLRequest:s,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal"})})}}function he(e){return ae(J(new TextEncoder().encode(e)).buffer)}function Ke(e){const t=v(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=q(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function Qe(e){try{return JSON.parse(v(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function Xe(e){const t=new U().parseFromString(e,"application/xml"),r=i(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,o=i(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,m=i(t,"//*[local-name(.)='Audience']/text()")[0],A=m&&m.nodeValue||void 0,c=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",f=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],S=f&&f.nodeValue||"",h=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],d=h&&h.nodeValue||"",g=i(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],x=ye(g),k={},T=i(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(T.length)for(const C of T){const O=i(C,"./@Name")[0];if(O.nodeValue){const b=i(C,"./*[local-name(.)='AttributeValue']/text()")[0];b?.nodeValue&&(k[O.nodeValue]=b.nodeValue)}}return{uid:S,success:r,expiresAt:x,issuerId:l,entityId:A,attrs:k,cert:c,nameFormat:d,destination:o}}function ye(e){const t=typeof e?.nodeValue=="string"&&L(Date.parse(e.nodeValue)),n=L(Date.now()),r=L(Date.now()+720*60*1e3);return t?t>n&&t<r?r:t:n}function L(e){return Math.floor(e/1e3)}const M={},y={jwks:{}};async function V(e,t){return M[e]||(M[e]=t.configurationUrl?await $(t.configurationUrl):t.configuration),M[e]}async function we(e){for(const t of Object.keys(e)){const n=e[t];if(!N(n))continue;const r=await V(t,n);if(r.jwks_uri){const a=await $(r.jwks_uri);for(const o of a.keys)y.jwks[o.kid]={...o,idpId:t}}}}async function $(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function Ye(e){return fetch(`${Q}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function Ge(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com","cba.au.redocly.com"].some(r=>Ae(t.hostname,r))}function Ae(e,t){return e===t||e.endsWith(`.${t}`)}async function Ze(e,t){const n=new U().parseFromString(e),r=i(n,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!r)throw new Error("Cannot find Signature in the SAML response");const a=se(t),o=new B({publicCert:a});o.loadSignature(r);try{return o.checkSignature(e)}catch{return!1}}function et(e,t,n,r){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=n["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let a;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(a=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(a=e);const o=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=o?.match(/.+@.+/);return a=a||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?o:void 0),a=a?.toLowerCase(),{sub:e,given_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:n["http://schemas.microsoft.com/identity/claims/displayname"]||o,email:a,email_verified:!0,teams:r?re(n[r]):[]}}function z(e,t={}){return e.map(n=>t[n]||n)}async function tt(e,t){if(!t)return{};const n=t.authorization;if(!n)return{};try{const r=p.decode(n);if(r.header.alg===I.RS256){y.jwks[r.header.kid]===void 0&&await we(e);const m=y.jwks[r.header.kid];if(!m)return y.jwks[r.header.kid]=null,{};await p.verify(n,m,r.header.alg)}else await p.verify(n,_,r.header.alg);const a=r.payload.idpId||y.jwks[r.header.kid]?.idpId,o=e[a]||{},s=xe(o),l=ge(o);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:a,teams:Array.from(new Set([...z(r.payload.teams||[],l),..."defaultTeams"in o&&o.defaultTeams||[],...z("teamsClaimName"in o&&r.payload[s||""]||[],l),G])),name:Se(r.payload),isAuthenticated:!0,idpAccessToken:t.idp_access_token,federatedAccessToken:t.federated_access_token,federatedIdToken:t.federated_id_token,authCookie:n}}catch(r){r instanceof ne||ee.error("Malformed JWT token: %s",r.message)}return{}}function Se(e){return e.name||e.given_name||e.email}function ge(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function xe(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return K}}function i(e,t){return F.select(t,e)||[]}export{We as buildLoginUrl,de as buildOidcLoginUrl,Fe as buildOidcLogoutUrl,fe as buildSAML2LoginUrl,Je as createMcpAuthorizationCode,He as createMcpSessionResource,Ke as decodeSamlResponse,he as encodeSAML2,et as extractUserClaims,ze as getAuthProviderLoginParams,ce as getOidcLoginParams,V as getOidcMetadata,Ye as getRedoclyTokenPayload,ue as getSaml2LoginParams,tt as getUserParamsFromCookies,Se as getUsernameFromPayload,N as isOidcProviderConfig,Ge as isRedoclySso,ie as isSaml2ProviderConfig,Be as oidcExchangeCodeForToken,Qe as parseOidcState,me as parsePreviewBranch,Xe as parseSamlResponse,E as rewritePreviewAuthRedirectUri,qe as verifyMcpAuthorizationCode,Ze as verifySAMLResponse};
12
+ </samlp:AuthnRequest>`,s=he(o);return{loginUrl:Z(t.ssoUrl,{SAMLRequest:s,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:r,inviteCode:n,source:"portal"})})}}function he(e){return ae(H(new TextEncoder().encode(e)).buffer)}function Ke(e){const t=R(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const r=J(new Uint8Array(atob(e).split("").map(n=>n.charCodeAt(0))));return new TextDecoder().decode(r)}function Qe(e){try{return JSON.parse(R(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function Xe(e){const t=new D().parseFromString(e,"application/xml"),n=i(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,o=i(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,m=i(t,"//*[local-name(.)='Audience']/text()")[0],A=m&&m.nodeValue||void 0,c=i(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",f=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],x=f&&f.nodeValue||"",h=i(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],d=h&&h.nodeValue||"",_=i(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],g=ye(_),T={},C=i(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(C.length)for(const O of C){const U=i(O,"./@Name")[0];if(U.nodeValue){const b=i(O,"./*[local-name(.)='AttributeValue']/text()")[0];b?.nodeValue&&(T[U.nodeValue]=b.nodeValue)}}return{uid:x,success:n,expiresAt:g,issuerId:l,entityId:A,attrs:T,cert:c,nameFormat:d,destination:o}}function ye(e){const t=typeof e?.nodeValue=="string"&&L(Date.parse(e.nodeValue)),r=L(Date.now()),n=L(Date.now()+720*60*1e3);return t?t>r&&t<n?n:t:r}function L(e){return Math.floor(e/1e3)}const M={},w={jwks:{}};async function V(e,t){return M[e]||(M[e]=t.configurationUrl?await $(t.configurationUrl):t.configuration),M[e]}async function we(e){for(const t of Object.keys(e)){const r=e[t];if(!j(r))continue;const n=await V(t,r);if(n.jwks_uri){const a=await $(n.jwks_uri);for(const o of a.keys)w.jwks[o.kid]={...o,idpId:t}}}}async function $(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function Ye(e){return fetch(`${Q}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function Ge(e){if(!e.configurationUrl)return!1;const t=new URL(e.configurationUrl);return["localhost","127.0.0.1","blueharvest.cloud","bhstage.cloud","cloud.redocly.com","beta.redocly.com","cloud.eu.redocly.com","beta.eu.redocly.com","cba.au.redocly.com"].some(n=>Se(t.hostname,n))}function Se(e,t){return e===t||e.endsWith(`.${t}`)}async function Ze(e,t){const r=new D().parseFromString(e),n=i(r,"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']")[0];if(!n)throw new Error("Cannot find Signature in the SAML response");const a=se(t),o=new B({publicCert:a});o.loadSignature(n);try{return o.checkSignature(e)}catch{return!1}}function et(e,t,r,n){t==="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&&(e=r["http://schemas.microsoft.com/identity/claims/objectidentifier"]);let a;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(a=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(a=e);const o=r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=o?.match(/.+@.+/);return a=a||r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?o:void 0),a=a?.toLowerCase(),{sub:e,given_name:r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],family_name:r["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"],name:r["http://schemas.microsoft.com/identity/claims/displayname"]||o,email:a,email_verified:!0,teams:n?re(r[n]):[]}}function z(e,t={}){return e.map(r=>t[r]||r)}async function tt(e,t){if(!t)return{};const r=t.authorization;if(!r)return{};try{const n=p.decode(r);if(n.header.alg===y.RS256){w.jwks[n.header.kid]===void 0&&await we(e);const m=w.jwks[n.header.kid];if(!m)return w.jwks[n.header.kid]=null,{};await p.verify(r,m,y.RS256)}else await p.verify(r,I,y.HS256);const a=n.payload.idpId||w.jwks[n.header.kid]?.idpId,o=e[a]||{},s=_e(o),l=xe(o);return{...n.payload,email:n.payload.email?.toLowerCase(),idpId:a,teams:Array.from(new Set([...z(n.payload.teams||[],l),..."defaultTeams"in o&&o.defaultTeams||[],...z("teamsClaimName"in o&&n.payload[s||""]||[],l),G])),name:Ae(n.payload),isAuthenticated:!0,idpAccessToken:t.idp_access_token,federatedAccessToken:t.federated_access_token,federatedIdToken:t.federated_id_token,authCookie:r}}catch(n){n instanceof ne||ee.error("Malformed JWT token: %s",n.message)}return{}}function Ae(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function xe(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function _e(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return K}}function i(e,t){return F.select(t,e)||[]}export{We as buildLoginUrl,de as buildOidcLoginUrl,Fe as buildOidcLogoutUrl,fe as buildSAML2LoginUrl,He as createMcpAuthorizationCode,qe as createMcpSessionResource,Ke as decodeSamlResponse,he as encodeSAML2,et as extractUserClaims,ze as getAuthProviderLoginParams,ce as getOidcLoginParams,V as getOidcMetadata,Ye as getRedoclyTokenPayload,ue as getSaml2LoginParams,tt as getUserParamsFromCookies,Ae as getUsernameFromPayload,j as isOidcProviderConfig,Ge as isRedoclySso,ie as isSaml2ProviderConfig,Be as oidcExchangeCodeForToken,Qe as parseOidcState,me as parsePreviewBranch,Xe as parseSamlResponse,E as rewritePreviewAuthRedirectUri,Je as verifyMcpAuthorizationCode,Ze as verifySAMLResponse};
@@ -1,8 +1,6 @@
1
1
  import type { Context, Next } from 'hono';
2
- import type { HttpMethod } from '../../../types/http.js';
3
- type CatalogAuthMiddlewareOptions = {
4
- secureMethods?: HttpMethod[];
5
- };
6
- export declare function catalogAuthMiddleware(serverOutDir: string, options?: CatalogAuthMiddlewareOptions): (ctx: Context, next: Next) => Promise<Response | void>;
7
- export {};
2
+ export declare function catalogAuthMiddleware({ serverOutDir, protectReadMethods, }: {
3
+ serverOutDir: string;
4
+ protectReadMethods?: boolean;
5
+ }): (ctx: Context, next: Next) => Promise<Response | void>;
8
6
  //# sourceMappingURL=catalogAuthMiddleware.d.ts.map
@@ -1 +1 @@
1
- import{KvService as c}from"../../persistence/kv/services/kv-service.js";import{JWT_SECRET_KEY as d}from"../../constants/common.js";import*as s from"../jwt/jwt.js";const u=1440*60,y=(e,a)=>e.secureMethods?.includes(a)??!1;function w(e,a={}){return async(r,t)=>{const n=r.req.method;return y(a,n)?await l(r,t,e):await t()}}const l=async(e,a,r)=>{const t=e.req.header("apiKey");if(t)return await p(e,a,t,r);const i=e.req.header("authorization")?.replace("Bearer ","");return i?await f(e,a,i):e.json({message:"API key is required"},401)},p=async(e,a,r,t)=>{if(!process.env.BH_API_URL)return e.json({message:"API key validation service not configured"},500);try{const n=await c.getInstance({baseDbDir:t});if(await n.get(["api-keys","reunite",r]))return await a();const o=new URL("/api/api-keys-verify",process.env.BH_API_URL).toString();return(await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:r})})).ok?(await n.set(["api-keys","reunite",r],{valid:!0},{ttlInSeconds:u}),await a()):e.json({message:"Invalid API key"},401)}catch{return e.json({message:"API key validation failed"},400)}},f=async(e,a,r)=>{try{const t=await s.verify(r,d),n=s.decode(r).payload.isInternalConnection;return!t||!n?e.json({message:"API key is required"},401):await a()}catch{return e.json({message:"API key validation failed"},400)}};export{w as catalogAuthMiddleware};
1
+ import{KvService as p}from"../../persistence/kv/services/kv-service.js";import{DEFAULT_AUTHENTICATED_TEAM as A}from"../../../constants/common.js";import{JWT_SECRET_KEY as l}from"../../constants/common.js";import*as d from"../jwt/jwt.js";import{AlgorithmTypes as y}from"../jwt/types.js";const I=60,T=e=>["POST","PUT","DELETE","PATCH"].includes(e),h=e=>["GET"].includes(e);function D({serverOutDir:e,protectReadMethods:t=!0}){return async(r,a)=>await f(r,a,e,t)}const f=async(e,t,r,a=!0)=>{const s=e.req.method,n=T(s)||h(s)&&a,o=e.req.header("apiKey");if(o)return await v(e,t,o,r);const c=e.req.header("authorization")?.replace("Bearer ","");return c?await w(e,t,c):n?e.json({message:"API key is required"},401):await t()},v=async(e,t,r,a)=>{if(!process.env.BH_API_URL||!process.env.ORGANIZATION_ID)return e.json({message:"API key validation service not configured"},500);try{const s=await p.getInstance({baseDbDir:a});let n=await E(s,r);if(n)return e.set("apiKeyTeams",n.teams),await t();const o=new URL(`/api/orgs/${process.env.ORGANIZATION_ID}/session`,process.env.BH_API_URL).toString(),i=await fetch(o,{method:"GET",headers:{Authorization:`Bearer ${r}`}});if(!i.ok)return e.json({message:"Invalid API key"},401);const m=(await i.json())?.user?.teams?.[process.env.ORGANIZATION_ID]??[],u=[A,...m];return e.set("apiKeyTeams",u),await s.set(["api-keys","reunite",r],{valid:!0,teams:u},{ttlInSeconds:I}),await t()}catch{return e.json({message:"API key validation failed"},400)}},w=async(e,t,r)=>{try{const a=await d.verify(r,l,y.HS256),s=d.decode(r).payload.isInternalConnection;return!a||!s?e.json({message:"API key is required"},401):await t()}catch{return e.json({message:"API key validation failed"},400)}},E=async(e,t)=>{try{return await e.get(["api-keys","reunite",t])}catch{return null}};export{D as catalogAuthMiddleware};
@@ -1 +1 @@
1
- import{RbacFeatures as c}from"../../../constants/common.js";import{ASK_AI_API_URL as r}from"../../constants/common.js";import{canAccessFeature as p}from"../../utils/rbac.js";import{handleUnauthorizedApiRequest as u}from"../utils.js";import{isAiSearchEnabled as f}from"../../plugins/search/utils.js";function R(i){return async e=>{if(!r)return e.newResponse(null,404);const o=i.getConfig();if(!f(o))return e.newResponse(null,403,{});const s=e.get("auth");if(!p(c.AI_SEARCH,s,o.rbac,o.requiresLogin))return u(e);const t={"Content-Type":"application/json"};s.idpAccessToken&&(t.Cookie=`accessToken=${s.idpAccessToken}`);const a=await e.req.json(),n=await fetch(r,{method:"POST",body:JSON.stringify(a),headers:t});return n.ok?e.newResponse(n.body,200,{"Content-Type":"text/event-stream"}):e.newResponse(n.body,n.status,{"Content-Type":"application/json"})}}export{R as askAiHandler};
1
+ import{RbacFeatures as p}from"../../../constants/common.js";import{ASK_AI_API_URL as r}from"../../constants/common.js";import{canAccessFeature as u}from"../../utils/rbac.js";import{handleUnauthorizedApiRequest as f}from"../utils.js";import{isAiSearchEnabled as h}from"../../plugins/search/utils.js";function C(a){return async e=>{if(!r)return e.newResponse(null,404);const t=a.getConfig();if(!h(t))return e.newResponse(null,403,{});const o=e.get("auth");if(!u(p.AI_SEARCH,o,t.rbac,t.requiresLogin))return f(e);const i={"Content-Type":"application/json"},n=[];o.claims?.authCookie&&n.push(`authorization=${o.claims.authCookie}`),o.idpAccessToken&&n.push(`accessToken=${o.idpAccessToken}`),n.length>0&&(i.Cookie=n.join("; "));const c=await e.req.json(),s=await fetch(r,{method:"POST",body:JSON.stringify(c),headers:i});return s.ok?e.newResponse(s.body,200,{"Content-Type":"text/event-stream"}):e.newResponse(s.body,s.status,{"Content-Type":"application/json"})}}export{C as askAiHandler};