@redocly/redoc-reef 0.135.0-next.2 → 0.135.0-next.4

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 (69) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/api-schemas/search-facets.d.ts +41 -0
  3. package/dist/api-schemas/search-facets.js +1 -0
  4. package/dist/api-schemas/search.d.ts +66 -0
  5. package/dist/api-schemas/search.js +1 -0
  6. package/dist/client/app/Feedback/useSubmitFeedback.js +1 -1
  7. package/dist/client/app/UserMenu/useUserMenu.js +1 -1
  8. package/dist/client/app/pages/DevLogin/DevLogin.js +1 -1
  9. package/dist/client/app/pages/Invite/Invite.js +1 -1
  10. package/dist/client/app/search/useAiSearch.js +1 -1
  11. package/dist/client/app/search/useFacets.js +1 -1
  12. package/dist/client/app/search/useSearch.js +1 -1
  13. package/dist/client/app/utils/resolveRouteBySlug.js +1 -1
  14. package/dist/client/browser-entry.js +2 -2
  15. package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
  16. package/dist/client/templates/asyncapi-docs/template.js +1 -1
  17. package/dist/client/templates/openapi-docs/helpers.js +2 -2
  18. package/dist/client/templates/openapi-docs/template.js +1 -1
  19. package/dist/client/types/post-message.d.ts +4 -0
  20. package/dist/constants/api.d.ts +49 -0
  21. package/dist/constants/api.js +1 -0
  22. package/dist/constants/common.d.ts +0 -48
  23. package/dist/constants/common.js +1 -1
  24. package/dist/server/config/env-config.d.ts +0 -2
  25. package/dist/server/config/env-schema.d.ts +0 -5
  26. package/dist/server/config/env-schemas/server-config.d.ts +0 -3
  27. package/dist/server/config/env-schemas/server-config.js +1 -1
  28. package/dist/server/constants/common.d.ts +0 -1
  29. package/dist/server/constants/common.js +1 -1
  30. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +1 -1
  31. package/dist/server/plugins/markdown/attribute-resolvers/index.js +1 -1
  32. package/dist/server/plugins/markdown/attribute-resolvers/resolve-image-gallery.d.ts +4 -0
  33. package/dist/server/plugins/markdown/attribute-resolvers/resolve-image-gallery.js +1 -0
  34. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  35. package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +1 -1
  36. package/dist/server/plugins/search/engines/flexsearch/index.d.ts +3 -3
  37. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  38. package/dist/server/plugins/search/engines/search-engine.d.ts +3 -3
  39. package/dist/server/plugins/search/engines/search-engine.js +1 -1
  40. package/dist/server/plugins/search/engines/typesense/index.d.ts +3 -3
  41. package/dist/server/plugins/search/engines/typesense/index.js +1 -1
  42. package/dist/server/plugins/sitemap/index.js +1 -1
  43. package/dist/server/types/plugins/search.d.ts +2 -2
  44. package/dist/server/types/web-server.d.ts +8 -0
  45. package/dist/server/utils/rbac.js +1 -1
  46. package/dist/server/web-server/auth.js +3 -3
  47. package/dist/server/web-server/dev-server.js +1 -1
  48. package/dist/server/web-server/middleware/jsonValidatorMiddleware.d.ts +336 -0
  49. package/dist/server/web-server/middleware/jsonValidatorMiddleware.js +1 -0
  50. package/dist/server/web-server/routes/auth.d.ts +1 -1
  51. package/dist/server/web-server/routes/auth.js +1 -1
  52. package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
  53. package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
  54. package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
  55. package/dist/server/web-server/routes/catalog/catalog.js +1 -1
  56. package/dist/server/web-server/routes/cors-proxy.js +1 -1
  57. package/dist/server/web-server/routes/index.js +1 -1
  58. package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
  59. package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
  60. package/dist/server/web-server/routes/page-data.js +1 -1
  61. package/dist/server/web-server/routes/search.d.ts +5 -3
  62. package/dist/server/web-server/routes/search.js +1 -1
  63. package/dist/types/api.d.ts +15 -0
  64. package/dist/types/index.d.ts +1 -1
  65. package/dist/utils/auth/build-login-url.js +1 -1
  66. package/dist/utils/auth/is-auth-route-path.js +1 -1
  67. package/package.json +17 -16
  68. package/dist/types/search.d.ts +0 -29
  69. /package/dist/types/{search.js → api.js} +0 -0
@@ -1 +1 @@
1
- import{ServerRoutes as L,USER_THEME_ALIAS as c}from"../../constants/common.js";import{envConfig as _}from"../config/env-config.js";const D="runtime",N="/assets",x="/_spec",U="/_bundle",P="static",l="redocly:::linkOriginal",M="@",a="default",i=new RegExp("((?!@i18n\\/|@l10n\\/)\\/?@.*?(?=\\/))","g"),m="@redocly/theme/plugin.js",H="styles.css",F=["@theme/plugin.js","@theme/plugin.cjs","@theme/plugin.mjs"],u=_.JWT_SECRET_KEY||"test_secret_key",A="@i18n",p="@l10n",G=[c,A,p],Y="https://redocly.com/auth/aud",d="catalog.json",g="scorecard.json",B="page-count.json",h="sitemap.xml",K="llms.txt",R=_.PROJECT_ID,e=_.PROJECT_SLUG,n=_.ORGANIZATION_ID,s=_.ORG_SLUG,E=_.BH_API_URL,t=E&&s&&e?`${E}/orgs/${s}/projects/${e}`:void 0,o=E&&n&&R?`${E}/orgs/${n}/projects/${R}`:void 0,S=E?`${E}/entitlements/.well-known/jwks`:"https://app.cloud.redocly.com/api/entitlements/.well-known/jwks",j=_.ENTITLEMENTS_JWKS_CDN_URL||S,J=t?`${t}/feedback`:"",W=o?`${o}/ai-agentic-conversations`:"",$=o?`${o}/semantic-search`:"",y=t&&`${t}/registry/apis`,f=t&&`${t}/registry/paths`,V="no-store",X=365*24*60*60,k="X-Redocly-Cache-Control",w="no-cache",v="public, s-maxage=86400, max-age=10, must-revalidate",b=_.AUTH_URL,Z="Developer Documentation",T=_.REDOCLY_SSR_RENDER_MODE==="worker"?"worker":"main",q=T==="main"?0:_.REDOCLY_SSR_WORKERS_MIN!=null?Number(_.REDOCLY_SSR_WORKERS_MIN):2,z=T==="main"?1:_.REDOCLY_SSR_WORKERS_MAX!=null?Number(_.REDOCLY_SSR_WORKERS_MAX):5,Q="-----BEGIN CERTIFICATE-----",__="-----END CERTIFICATE-----",E_=_.REDOCLY_TELEMETRY_ENDPOINT||"https://app.cloud.redocly.com/api/telemetry/project",t_=!_.isDevelopMode&&_.REDOCLY_TELEMETRY!=="off"||_.REDOCLY_TELEMETRY==="on",o_="http://localhost:4318/v1/traces",R_=[L.HEALTH],r=_.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",e_=_.REDOCLY_CORS_ORIGINS?_.REDOCLY_CORS_ORIGINS.split(",").map(I=>I.trim()).filter(Boolean).concat(r):[r];export{e_ as ALLOWED_CORS_ORIGINS,Y as ALTERNATIVE_AUD_CLAIM_NAME,W as ASK_AI_API_URL,b as AUTH_URL,Q as BEGIN_CERTIFICATE_DELIMITER,t as BH_API_PROJECTS_URL,o as BH_API_PROJECTS_URL_V2,V as CACHE_CONTROL_NO_STORE_HEADER_VALUE,w as CACHE_CONTROL_PUBLIC_HTML,d as CATALOG_OUTPUT_FILE_NAME,X as DEFAULT_IMMUTABLE_CACHE_MAX_AGE,F as DEFAULT_PROJECT_PLUGIN_PATHS,m as DEFAULT_THEME_PLUGIN_PATH,Z as DEFAULT_TITLE,a as DEFAULT_VERSION_NAME,x as DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER,__ as END_CERTIFICATE_DELIMITER,j as ENTITLEMENTS_JWKS_URL,J as FEEDBACK_API_URL,A as I18N_DIR_NAME,u as JWT_SECRET_KEY,p as L10N_DIR_NAME,l as LINK_ORIGINAL_ATTR_NAME,K as LLMS_TXT_FILE_NAME,n as ORG_ID,s as ORG_SLUG,R_ as OTEL_EXCLUDED_ROUTES,o_ as OTEL_TRACES_DEV_URL,B as PAGE_COUNT_OUTPUT_FILE_NAME,R as PROJECT_ID,e as PROJECT_SLUG,U as PUBLIC_API_DEFINITIONS_FOLDER,N as PUBLIC_ASSETS_FOLDER,P as PUBLIC_STATIC_FOLDER,y as REGISTRY_APIS_API_URL,f as REGISTRY_APIS_PATHS_API_URL,G as RESERVED_DIR_NAMES,D as RUNTIME_RESOURCES_DIR,g as SCORECARD_OUTPUT_FILE_NAME,$ as SEMANTIC_SEARCH_API_URL,r as SERVER_EDITOR_APP_URL,h as SITEMAP_FILE_NAME,T as SSR_RENDER_MODE,z as SSR_WORKERS_MAX,q as SSR_WORKERS_MIN,H as STYLES_FILE,t_ as TELEMETRY_ENABLED,E_ as TELEMETRY_ENDPOINT,i as VERSIONED_FOLDER_REGEXP_MATCH,M as VERSION_SEPARATOR,k as X_REDOCLY_CACHE_CONTROL_HEADER,v as X_REDOCLY_CACHE_CONTROL_PUBLIC_HTML};
1
+ import{ServerRoutes as L}from"../../constants/api.js";import{USER_THEME_ALIAS as c}from"../../constants/common.js";import{envConfig as _}from"../config/env-config.js";const N="runtime",x="/assets",U="/_spec",P="/_bundle",l="static",M="redocly:::linkOriginal",a="@",i="default",m=new RegExp("((?!@i18n\\/|@l10n\\/)\\/?@.*?(?=\\/))","g"),H="@redocly/theme/plugin.js",F="styles.css",G=["@theme/plugin.js","@theme/plugin.cjs","@theme/plugin.mjs"],u=_.JWT_SECRET_KEY||"test_secret_key",A="@i18n",p="@l10n",Y=[c,A,p],d="https://redocly.com/auth/aud",g="catalog.json",B="scorecard.json",h="page-count.json",K="sitemap.xml",J="llms.txt",R=_.PROJECT_ID,e=_.PROJECT_SLUG,n=_.ORGANIZATION_ID,s=_.ORG_SLUG,E=_.BH_API_URL,t=E&&s&&e?`${E}/orgs/${s}/projects/${e}`:void 0,o=E&&n&&R?`${E}/orgs/${n}/projects/${R}`:void 0,S=E?`${E}/entitlements/.well-known/jwks`:"https://app.cloud.redocly.com/api/entitlements/.well-known/jwks",W=_.ENTITLEMENTS_JWKS_CDN_URL||S,$=t?`${t}/feedback`:"",f=o?`${o}/ai-agentic-conversations`:"",j=o?`${o}/semantic-search`:"",V=t&&`${t}/registry/apis`,X=t&&`${t}/registry/paths`,k="no-store",w=365*24*60*60,y="X-Redocly-Cache-Control",v="no-cache",b="public, s-maxage=86400, max-age=10, must-revalidate",Z=_.AUTH_URL,q="Developer Documentation",T=_.REDOCLY_SSR_RENDER_MODE==="worker"?"worker":"main",z=T==="main"?0:_.REDOCLY_SSR_WORKERS_MIN!=null?Number(_.REDOCLY_SSR_WORKERS_MIN):2,Q=T==="main"?1:_.REDOCLY_SSR_WORKERS_MAX!=null?Number(_.REDOCLY_SSR_WORKERS_MAX):5,__="-----BEGIN CERTIFICATE-----",E_="-----END CERTIFICATE-----",t_=!_.isDevelopMode&&_.REDOCLY_TELEMETRY!=="off"||_.REDOCLY_TELEMETRY==="on",o_="http://localhost:4318/v1/traces",R_=[L.HEALTH],r=_.SERVER_EDITOR_APP_URL||"http://127.0.0.1:3000",e_=_.REDOCLY_CORS_ORIGINS?_.REDOCLY_CORS_ORIGINS.split(",").map(I=>I.trim()).filter(Boolean).concat(r):[r];export{e_ as ALLOWED_CORS_ORIGINS,d as ALTERNATIVE_AUD_CLAIM_NAME,f as ASK_AI_API_URL,Z as AUTH_URL,__ as BEGIN_CERTIFICATE_DELIMITER,t as BH_API_PROJECTS_URL,o as BH_API_PROJECTS_URL_V2,k as CACHE_CONTROL_NO_STORE_HEADER_VALUE,v as CACHE_CONTROL_PUBLIC_HTML,g as CATALOG_OUTPUT_FILE_NAME,w as DEFAULT_IMMUTABLE_CACHE_MAX_AGE,G as DEFAULT_PROJECT_PLUGIN_PATHS,H as DEFAULT_THEME_PLUGIN_PATH,q as DEFAULT_TITLE,i as DEFAULT_VERSION_NAME,U as DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER,E_ as END_CERTIFICATE_DELIMITER,W as ENTITLEMENTS_JWKS_URL,$ as FEEDBACK_API_URL,A as I18N_DIR_NAME,u as JWT_SECRET_KEY,p as L10N_DIR_NAME,M as LINK_ORIGINAL_ATTR_NAME,J as LLMS_TXT_FILE_NAME,n as ORG_ID,s as ORG_SLUG,R_ as OTEL_EXCLUDED_ROUTES,o_ as OTEL_TRACES_DEV_URL,h as PAGE_COUNT_OUTPUT_FILE_NAME,R as PROJECT_ID,e as PROJECT_SLUG,P as PUBLIC_API_DEFINITIONS_FOLDER,x as PUBLIC_ASSETS_FOLDER,l as PUBLIC_STATIC_FOLDER,V as REGISTRY_APIS_API_URL,X as REGISTRY_APIS_PATHS_API_URL,Y as RESERVED_DIR_NAMES,N as RUNTIME_RESOURCES_DIR,B as SCORECARD_OUTPUT_FILE_NAME,j as SEMANTIC_SEARCH_API_URL,r as SERVER_EDITOR_APP_URL,K as SITEMAP_FILE_NAME,T as SSR_RENDER_MODE,Q as SSR_WORKERS_MAX,z as SSR_WORKERS_MIN,F as STYLES_FILE,t_ as TELEMETRY_ENABLED,m as VERSIONED_FOLDER_REGEXP_MATCH,a as VERSION_SEPARATOR,y as X_REDOCLY_CACHE_CONTROL_HEADER,b as X_REDOCLY_CACHE_CONTROL_PUBLIC_HTML};
@@ -1,4 +1,4 @@
1
- import t from"react";import c from"styled-components";import{RedoclyGraphQLDocs as h}from"@redocly/graphql-docs";import{buildSchema as l}from"graphql";import{LayoutVariant as f}from"@redocly/theme/components/SidebarActions/SidebarActions";import{useThemeConfig as p}from"@redocly/theme/core/hooks";import{withPathPrefix as g}from"@redocly/theme/core/utils";import{ServerRoutes as E}from"../../../../constants/common.js";import{CLIENT_TELEMETRY_ENABLED as u}from"../../../../client/constants/common.js";import{PACKAGE_NAME as d}from"../../../../config/product-gates.js";import{envConfig as S}from"../../../config/env-config.js";import{usePageSharedData as L}from"../../../../client/providers/page-data/hooks.js";import{useCodeHighlight as R}from"../../../../client/app/hooks/codeHighlight/useCodeHighlight.js";function v({pageProps:o}){const e=L("graphQlSettings"),{settings:r}=o,{graphql:i}=p(),{highlight:n}=R(),m=t.useMemo(()=>({graphql:l(e)}),[e]),s=t.useMemo(()=>{const a={...i,...r};return{layout:o.apiOptions?.layout??f.THREE_PANEL,...a,markdown:{...a.markdown,highlight:n},navigation:{contentPrefix:""}}},[i,r,n,o.apiOptions?.layout]);return t.createElement(C,null,t.createElement(h,{schema:m,settings:s,telemetryConfig:{collectorUrl:new URL(g(E.OTEL_TRACES),location.origin).toString(),disabled:!u,serviceVersion:`${d}@${S.REDOCLY_PORTAL_VERSION}`}}))}const C=c.div`
1
+ import t from"react";import c from"styled-components";import{RedoclyGraphQLDocs as h}from"@redocly/graphql-docs";import{buildSchema as l}from"graphql";import{LayoutVariant as f}from"@redocly/theme/components/SidebarActions/SidebarActions";import{useThemeConfig as p}from"@redocly/theme/core/hooks";import{withPathPrefix as g}from"@redocly/theme/core/utils";import{ServerRoutes as E}from"../../../../constants/api.js";import{CLIENT_TELEMETRY_ENABLED as u}from"../../../../client/constants/common.js";import{PACKAGE_NAME as d}from"../../../../config/product-gates.js";import{envConfig as S}from"../../../config/env-config.js";import{usePageSharedData as L}from"../../../../client/providers/page-data/hooks.js";import{useCodeHighlight as R}from"../../../../client/app/hooks/codeHighlight/useCodeHighlight.js";function v({pageProps:o}){const e=L("graphQlSettings"),{settings:r}=o,{graphql:i}=p(),{highlight:n}=R(),m=t.useMemo(()=>({graphql:l(e)}),[e]),s=t.useMemo(()=>{const a={...i,...r};return{layout:o.apiOptions?.layout??f.THREE_PANEL,...a,markdown:{...a.markdown,highlight:n},navigation:{contentPrefix:""}}},[i,r,n,o.apiOptions?.layout]);return t.createElement(C,null,t.createElement(h,{schema:m,settings:s,telemetryConfig:{collectorUrl:new URL(g(E.OTEL_TRACES),location.origin).toString(),disabled:!u,serviceVersion:`${d}@${S.REDOCLY_PORTAL_VERSION}`}}))}const C=c.div`
2
2
  --navigation-anchor-offset: var(--navbar-height);
3
3
  --sidebar-width: 0px;
4
4
  `;export{v as default};
@@ -1 +1 @@
1
- import{resolveOpenApiRef as e}from"./resolve-open-api-ref.js";import{resolveJsonSchemaRef as o}from"./resolve-json-schema-ref.js";import{resolveParsedYaml as r}from"./resolve-parsed-yaml.js";import{resolveRawContent as m}from"./resolve-raw-content.js";import{resolveSvgContent as t}from"./resolve-svg-content.js";import{resolveRelativePath as i}from"./resolve-relative-path.js";import{resolveLink as l}from"./resolve-link.js";import{resolveNativeMdLink as s}from"./resolve-native-md-link.js";import{resolveCodeSnippetFromFile as a}from"./resolve-code-snippet-from-file.js";import{resolveDiagramFromFile as p}from"./resolve-diagram-from-file.js";import{resolveHtmlSourceAttribute as n}from"./resolve-html-source-attribute.js";import{resolveHtmlHref as v}from"./resolve-html-href.js";import{resolveImageSrc as f}from"./resolve-image-src.js";import{resolveImageSrcSet as S}from"./resolve-image-src-set.js";import{resolveNavLinks as c}from"./resolve-nav-links.js";import{resolveRelativeOrCdnIcon as h}from"./resolve-relative-or-cdn-icon.js";import{resolveCodeWalkthroughFilesets as d}from"./code-walkthrough/filesets-resolver.js";import{resolveJsonExampleRef as g}from"./resolve-json-example-ref.js";import{resolveSampleFromJsonSchema as F}from"./resolve-sample-from-json-schema.js";const Y={openapiRef:e,jsonSchemaRef:o,parsedYaml:r,rawContent:m,svgContent:t,relativePath:i,link:l,nativeMdLink:s,codeSnippetFile:a,diagramFile:p,htmlSourceAttribute:n,htmlHref:v,imageSrc:f,imageSrcSet:S,navLinks:c,relativeOrCdnIcon:h,codeWalkthroughFilesets:d,jsonExampleRef:g,sampleFromJsonSchema:F};export{Y as attributeResolvers};
1
+ import{resolveOpenApiRef as e}from"./resolve-open-api-ref.js";import{resolveJsonSchemaRef as r}from"./resolve-json-schema-ref.js";import{resolveParsedYaml as o}from"./resolve-parsed-yaml.js";import{resolveRawContent as m}from"./resolve-raw-content.js";import{resolveSvgContent as t}from"./resolve-svg-content.js";import{resolveRelativePath as i}from"./resolve-relative-path.js";import{resolveLink as l}from"./resolve-link.js";import{resolveNativeMdLink as a}from"./resolve-native-md-link.js";import{resolveCodeSnippetFromFile as s}from"./resolve-code-snippet-from-file.js";import{resolveDiagramFromFile as p}from"./resolve-diagram-from-file.js";import{resolveHtmlSourceAttribute as n}from"./resolve-html-source-attribute.js";import{resolveHtmlHref as v}from"./resolve-html-href.js";import{resolveImageSrc as f}from"./resolve-image-src.js";import{resolveImageSrcSet as S}from"./resolve-image-src-set.js";import{resolveImageGallery as c}from"./resolve-image-gallery.js";import{resolveNavLinks as g}from"./resolve-nav-links.js";import{resolveRelativeOrCdnIcon as h}from"./resolve-relative-or-cdn-icon.js";import{resolveCodeWalkthroughFilesets as d}from"./code-walkthrough/filesets-resolver.js";import{resolveJsonExampleRef as F}from"./resolve-json-example-ref.js";import{resolveSampleFromJsonSchema as R}from"./resolve-sample-from-json-schema.js";const Y={openapiRef:e,jsonSchemaRef:r,parsedYaml:o,rawContent:m,svgContent:t,relativePath:i,link:l,nativeMdLink:a,codeSnippetFile:s,diagramFile:p,htmlSourceAttribute:n,htmlHref:v,imageSrc:f,imageSrcSet:S,imageGallery:c,navLinks:g,relativeOrCdnIcon:h,codeWalkthroughFilesets:d,jsonExampleRef:F,sampleFromJsonSchema:R};export{Y as attributeResolvers};
@@ -0,0 +1,4 @@
1
+ import type { Node } from '@markdoc/markdoc';
2
+ import type { MarkdocResolveContext, WithOriginalAttr } from '../../../types';
3
+ export declare function resolveImageGallery(node: WithOriginalAttr<Node>, attributeName: string, pageRelativePath: string, { actions: { contentDir, outdir }, context }: MarkdocResolveContext): Promise<void>;
4
+ //# sourceMappingURL=resolve-image-gallery.d.ts.map
@@ -0,0 +1 @@
1
+ import{getNodeAttribute as p}from"../../../../markdoc/helpers/get-node-attribute.js";import{setNodeAttributeValue as u}from"../../../../markdoc/helpers/set-node-attribute-value.js";import{FileNotFoundError as y,resolveAssetPath as A}from"../../../utils/index.js";import{MdResolveError as d}from"./md-resolve-error.js";import{getLinkOriginalAttrName as v}from"./utils.js";async function P(e,i,f,{actions:{contentDir:c,outdir:m},context:g}){const l=e,h=p(e,i),a=v(i),s=l[a]??h;if(!Array.isArray(s))return;l[a]=s;const r=[],o=[];for(const t of s){if(typeof t!="string"){r.push(t);continue}try{r.push(await A(t,g.fs,{fromFileRelativePath:f,contentDir:c,outdir:m}))}catch(n){if(n instanceof y)r.push(t),o.push(n.filePath);else throw n}}if(u(e,i,r),o.length>0){const[t]=o;throw new d(o.length===1?`File ${t} does not exist`:`Files do not exist: ${o.join(", ")}`,{rawLink:t,link:t})}}export{P as resolveImageGallery};
@@ -1 +1 @@
1
- import{extractTokenFromAuthHeader as u}from"../../../plugins/mcp/utils/jwt.js";import{getUserParamsFromCookies as d}from"../../../web-server/auth.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as i,RBAC_ALL_OTHER_TEAMS as a,ServerRoutes as l}from"../../../../constants/common.js";import{withPathPrefix as h}from"@redocly/theme/core/utils";function c(e){return!e||typeof e!="object"||Object.keys(e).length===0?!1:!(e[i]&&e[i]!=="none"||e[a]&&e[a]!=="none")}function k(e,t){if(!t||Object.keys(t).length===0)return e;const r=t.content;if(r&&Object.keys(r).length>0&&Object.values(r).some(c))return!0;const o=t.teamFoldersBaseRoles;return c(o)?!0:e}async function R(e,t){const r=e.headers.get("Authorization");if(!r)return{isAuthenticated:!1};const o=u(r),s=t?.config?.ssoDirect||{},n=o?await d(s,{authorization:o}):{};return o&&n&&n.isAuthenticated?{isAuthenticated:!0,isTokenValid:!0,currentUser:{teams:n.teams||[],email:n.email||"",claims:n,isAuthenticated:!0,idpAccessToken:n.idpAccessToken||void 0,idpId:n.idpId||void 0},accessToken:o}:{isAuthenticated:!1,isTokenValid:!1}}function O(e){return e=e.replace(/^http:\/\//,"https://"),new Response(JSON.stringify({error:"unauthorized",message:"Authentication required"}),{status:401,headers:{"Content-Type":"application/json","WWW-Authenticate":`Bearer resource_metadata="${e}${l.MCP_OAUTH_PROTECTED_RESOURCE}${h("/mcp")}"`,"Access-Control-Allow-Origin":"*"}})}function _(){return new Response(JSON.stringify({error:"invalid_token",message:"Invalid or expired token"}),{status:401,headers:{"Content-Type":"application/json","WWW-Authenticate":'Bearer error="invalid_token", error_description="Invalid or expired token"',"Access-Control-Allow-Origin":"*"}})}export{_ as constructInvalidTokenResponse,O as constructUnauthorizedResponse,R as handleMcpAuth,k as shouldHandleMcpAuth};
1
+ import{extractTokenFromAuthHeader as u}from"../../../plugins/mcp/utils/jwt.js";import{getUserParamsFromCookies as d}from"../../../web-server/auth.js";import{ServerRoutes as l}from"../../../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as i,RBAC_ALL_OTHER_TEAMS as a}from"../../../../constants/common.js";import{withPathPrefix as h}from"@redocly/theme/core/utils";function c(e){return!e||typeof e!="object"||Object.keys(e).length===0?!1:!(e[i]&&e[i]!=="none"||e[a]&&e[a]!=="none")}function R(e,t){if(!t||Object.keys(t).length===0)return e;const r=t.content;if(r&&Object.keys(r).length>0&&Object.values(r).some(c))return!0;const o=t.teamFoldersBaseRoles;return c(o)?!0:e}async function O(e,t){const r=e.headers.get("Authorization");if(!r)return{isAuthenticated:!1};const o=u(r),s=t?.config?.ssoDirect||{},n=o?await d(s,{authorization:o}):{};return o&&n&&n.isAuthenticated?{isAuthenticated:!0,isTokenValid:!0,currentUser:{teams:n.teams||[],email:n.email||"",claims:n,isAuthenticated:!0,idpAccessToken:n.idpAccessToken||void 0,idpId:n.idpId||void 0},accessToken:o}:{isAuthenticated:!1,isTokenValid:!1}}function _(e){return e=e.replace(/^http:\/\//,"https://"),new Response(JSON.stringify({error:"unauthorized",message:"Authentication required"}),{status:401,headers:{"Content-Type":"application/json","WWW-Authenticate":`Bearer resource_metadata="${e}${l.MCP_OAUTH_PROTECTED_RESOURCE}${h("/mcp")}"`,"Access-Control-Allow-Origin":"*"}})}function g(){return new Response(JSON.stringify({error:"invalid_token",message:"Invalid or expired token"}),{status:401,headers:{"Content-Type":"application/json","WWW-Authenticate":'Bearer error="invalid_token", error_description="Invalid or expired token"',"Access-Control-Allow-Origin":"*"}})}export{g as constructInvalidTokenResponse,_ as constructUnauthorizedResponse,O as handleMcpAuth,R as shouldHandleMcpAuth};
@@ -1,4 +1,4 @@
1
- import{withPathPrefix as p}from"@redocly/theme/core/utils";import{ServerRoutes as h}from"../../../../../../constants/common.js";const f=async(a,t)=>{const{query:c,product:u}=a,l=JSON.stringify({query:c,product:u});let e=`${t.baseUrl}${p(h.SEMANTIC_SEARCH)}`;e.startsWith("http://")&&(e=e.replace(/^http:\/\//,"https://"));const o=t.accessToken?`authorization=${String(t.accessToken).replace(/^Bearer /,"")}`:"";try{const s=await fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...o?{Cookie:o}:{}},body:l});if(!s.ok)return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0};const r=await s.json();if(!r||r.length===0)return{content:[{type:"text",text:"No results found."}]};const i=r.map(n=>`### [${n.title}](${new URL(n.url,t.baseUrl).toString()})
1
+ import{withPathPrefix as p}from"@redocly/theme/core/utils";import{ServerRoutes as h}from"../../../../../../constants/api.js";const f=async(a,t)=>{const{query:c,product:u}=a,l=JSON.stringify({query:c,product:u});let e=`${t.baseUrl}${p(h.SEMANTIC_SEARCH)}`;e.startsWith("http://")&&(e=e.replace(/^http:\/\//,"https://"));const o=t.accessToken?`authorization=${String(t.accessToken).replace(/^Bearer /,"")}`:"";try{const s=await fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...o?{Cookie:o}:{}},body:l});if(!s.ok)return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0};const r=await s.json();if(!r||r.length===0)return{content:[{type:"text",text:"No results found."}]};const i=r.map(n=>`### [${n.title}](${new URL(n.url,t.baseUrl).toString()})
2
2
 
3
3
  ${n.content}
4
4
  `).join(`
@@ -1,16 +1,16 @@
1
1
  import type { SearchFacet, SearchFacetCount } from '@redocly/theme/core/types';
2
- import type { AfterRoutesCreatedActions, SearchEngine, AddDocumentsParams, SearchDocument } from '../../../../types';
2
+ import type { AfterRoutesCreatedActions, SearchEngine, AddDocumentsParams, SearchDocument, AuthDetails } from '../../../../types';
3
3
  import type { SearchRequestParams, SearchResponse, FacetCountsRequestParams } from '../../../../../types/index.js';
4
4
  export declare class FlexSearch implements SearchEngine {
5
5
  #private;
6
6
  initIndexSchema(_facets: Map<string, SearchFacet>): Promise<void>;
7
7
  addDocuments(documents: SearchDocument[], params: AddDocumentsParams): Promise<void>;
8
8
  getIndexesSize(): number;
9
- search(params: SearchRequestParams, _facets?: Map<string, SearchFacet>): Promise<SearchResponse>;
9
+ search(params: SearchRequestParams, auth: AuthDetails, _facets?: Map<string, SearchFacet>): Promise<SearchResponse>;
10
10
  exportDocuments(outDir: string): Promise<void>;
11
11
  exportIndexes(outDir: string): Promise<void>;
12
12
  import(sourceDir: string): Promise<void>;
13
- countFacets(_params: FacetCountsRequestParams, facets: Map<string, SearchFacet>): Record<string, SearchFacetCount[]>;
13
+ countFacets(_params: FacetCountsRequestParams, _auth: AuthDetails, facets: Map<string, SearchFacet>): Record<string, SearchFacetCount[]>;
14
14
  cleanupFacetValues(_actions: AfterRoutesCreatedActions): void;
15
15
  }
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- import{readFile as w,readdir as y,appendFile as E}from"node:fs/promises";import m from"node:path";import{existsSync as F}from"node:fs";import{SEARCH_GROUP_FACET_FIELD as I,SEARCH_PRODUCT_FIELD as C,SEARCH_VERSION_FIELD as $}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as A,SEARCH_DATA_EXPORT_FOLDER as _,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as O}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as v}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as N}from"../../../../config/env-config.js";import{ensureDir as h}from"../../../../utils/index.js";import{FlexSearchIndex as j}from"./search-index.js";class J{#e=new Map;#s;#t=0;async initIndexSchema(t){this.#s={document:{id:"id",tag:"tags",index:A},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#n(t,n){const e=this.#e.get(t);if(e)return e.find(o=>o.id===n)}#o(t,n){let e=this.#n(t,n);return e||(e=new j(n,this.#s),this.#e.set(t,[...this.#e.get(t)??[],e])),e}async addDocuments(t,n){if(t.length){const{group:e,locale:o,outDir:c}=n,i=this.#o(o,e);for(const a of t)i.add(a),N.isBuildMode&&(this.#t++,this.#t>=O&&await this.exportDocuments(c))}}getIndexesSize(){return this.#e.size}async search(t,n){return await v("search",async e=>{const{query:o,locale:c,filter:i,loadMore:a,auth:f}=t,l=this.#e.get(c)??[];let r=[],d="",x=["v:default"];if(e?.setAttribute("locale",c),i)for(const s of i)s.field===I?r=[...r,...s.values]:s.field===C?d=`p:${s.values[0]}`:s.field===$&&s.values.length&&s.values.length===2&&(x=[...x,`v:${s.values[0]}:${s.values[1]}`]);const g={auth:f,query:o,offset:0,SEARCH_GROUP_FACET_FIELD:I,product:d,versions:x},p=[];let u={facets:{},documents:{}};if(a){const s=this.#n(c,a.groupKey);s&&p.push(s.search({...g,offset:a.offset}))}else for(const s of l)r&&r.length?r.includes(s.id)&&p.push(s.search(g)):p.push(s.search(g));const R=await Promise.all(p);for(const s of R){u.documents={...u.documents,...s.documents};for(const[D,S]of Object.entries(s.facets))u.facets[D]?u.facets[D]=[...u.facets[D],...S]:u.facets[D]=S}return u})}async exportDocuments(t){const n='{"documents":[',e=h(m.join(t,_));for(const[o,c]of this.#e){const i=h(m.join(e,o));for(const a of c){const f=Array.from(a.documents);if(f.length===0)continue;const l=h(m.join(i,`${a.id}.json`)),r=!F(l),d=JSON.stringify(f).substring(1).slice(0,-1),x=r?n+d:","+d;await E(l,x,{encoding:"utf8"}),a.clearDocuments()}}this.#t=0}async exportIndexes(t){const n=h(m.join(t,_));for(const[e,o]of this.#e){const c=h(m.join(n,e));for(const i of o){const a=h(m.join(c,`${i.id}.json`)),f={};await i.export((r,d)=>{f[r]=d});const l=`],"index":${JSON.stringify(f)}}`;await E(a,l,{encoding:"utf8"})}}this.#e.clear()}async import(t){const n=`${t}/${_}`;if(!F(n))return;const e=await y(n);for(const o of e){const c=await y(`${n}/${o}`);for(const i of c){const a=`${n}/${o}/${i}`,f=JSON.parse(await w(a,"utf-8")),l=m.parse(i).name;await this.#o(o,l).import(f)}}}countFacets(t,n){const e={};for(const[o,c]of n)e[o]=c.values.map(i=>({value:i,count:0,isCounterVisible:!1}));return e}cleanupFacetValues(t){}}export{J as FlexSearch};
1
+ import{readFile as w,readdir as y,appendFile as E}from"node:fs/promises";import m from"node:path";import{existsSync as F}from"node:fs";import{SEARCH_GROUP_FACET_FIELD as I,SEARCH_PRODUCT_FIELD as C,SEARCH_VERSION_FIELD as $}from"../../../../../constants/common.js";import{SEARCH_INDEX_FIELDS as A,SEARCH_DATA_EXPORT_FOLDER as _,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as O}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as v}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as N}from"../../../../config/env-config.js";import{ensureDir as h}from"../../../../utils/index.js";import{FlexSearchIndex as j}from"./search-index.js";class J{#e=new Map;#s;#t=0;async initIndexSchema(e){this.#s={document:{id:"id",tag:"tags",index:A},worker:!1,tokenize:"forward",context:{depth:2,resolution:9}}}#n(e,s){const n=this.#e.get(e);if(n)return n.find(o=>o.id===s)}#o(e,s){let n=this.#n(e,s);return n||(n=new j(s,this.#s),this.#e.set(e,[...this.#e.get(e)??[],n])),n}async addDocuments(e,s){if(e.length){const{group:n,locale:o,outDir:a}=s,i=this.#o(o,n);for(const c of e)i.add(c),N.isBuildMode&&(this.#t++,this.#t>=O&&await this.exportDocuments(a))}}getIndexesSize(){return this.#e.size}async search(e,s,n){return await v("search",async o=>{const{query:a,locale:i,filter:c,loadMore:r}=e,l=this.#e.get(i)??[];let f=[],d="",x=["v:default"];if(o?.setAttribute("locale",i),c)for(const t of c)t.field===I?f=[...f,...t.values]:t.field===C?d=`p:${t.values[0]}`:t.field===$&&t.values.length&&t.values.length===2&&(x=[...x,`v:${t.values[0]}:${t.values[1]}`]);const g={auth:s,query:a,offset:0,SEARCH_GROUP_FACET_FIELD:I,product:d,versions:x},p=[];let u={facets:{},documents:{}};if(r){const t=this.#n(i,r.groupKey);t&&p.push(t.search({...g,offset:r.offset}))}else for(const t of l)f&&f.length?f.includes(t.id)&&p.push(t.search(g)):p.push(t.search(g));const R=await Promise.all(p);for(const t of R){u.documents={...u.documents,...t.documents};for(const[D,S]of Object.entries(t.facets))u.facets[D]?u.facets[D]=[...u.facets[D],...S]:u.facets[D]=S}return u})}async exportDocuments(e){const s='{"documents":[',n=h(m.join(e,_));for(const[o,a]of this.#e){const i=h(m.join(n,o));for(const c of a){const r=Array.from(c.documents);if(r.length===0)continue;const l=h(m.join(i,`${c.id}.json`)),f=!F(l),d=JSON.stringify(r).substring(1).slice(0,-1),x=f?s+d:","+d;await E(l,x,{encoding:"utf8"}),c.clearDocuments()}}this.#t=0}async exportIndexes(e){const s=h(m.join(e,_));for(const[n,o]of this.#e){const a=h(m.join(s,n));for(const i of o){const c=h(m.join(a,`${i.id}.json`)),r={};await i.export((f,d)=>{r[f]=d});const l=`],"index":${JSON.stringify(r)}}`;await E(c,l,{encoding:"utf8"})}}this.#e.clear()}async import(e){const s=`${e}/${_}`;if(!F(s))return;const n=await y(s);for(const o of n){const a=await y(`${s}/${o}`);for(const i of a){const c=`${s}/${o}/${i}`,r=JSON.parse(await w(c,"utf-8")),l=m.parse(i).name;await this.#o(o,l).import(r)}}}countFacets(e,s,n){const o={};for(const[a,i]of n)o[a]=i.values.map(c=>({value:c,count:0,isCounterVisible:!1}));return o}cleanupFacetValues(e){}}export{J as FlexSearch};
@@ -1,5 +1,5 @@
1
1
  import type { SearchFacet } from '@redocly/theme/core/types';
2
- import type { SearchEngineType, AfterRoutesCreatedActions, AddDocumentsParams, SearchDocument } from '../../../types';
2
+ import type { SearchEngineType, AfterRoutesCreatedActions, AddDocumentsParams, SearchDocument, AuthDetails } from '../../../types';
3
3
  import type { FacetCountsRequestParams, GlobalData, SearchRequestParams, SearchResponse } from '../../../../types/index.js';
4
4
  export declare class SearchEngine {
5
5
  #private;
@@ -8,8 +8,8 @@ export declare class SearchEngine {
8
8
  constructor(type: SearchEngineType, l10n: GlobalData['l10n']);
9
9
  initIndexSchema(searchFacets: Map<string, SearchFacet>): Promise<void>;
10
10
  addDocuments(documents: SearchDocument[], params: AddDocumentsParams): Promise<void>;
11
- search(params: SearchRequestParams, facets?: Map<string, SearchFacet>): Promise<SearchResponse>;
12
- countFacets(params: FacetCountsRequestParams, facets: Map<string, SearchFacet>): Promise<Record<string, import("@redocly/theme/core/types").SearchFacetCount[]>>;
11
+ search(params: SearchRequestParams, auth: AuthDetails, facets?: Map<string, SearchFacet>): Promise<SearchResponse>;
12
+ countFacets(params: FacetCountsRequestParams, auth: AuthDetails, facets: Map<string, SearchFacet>): Promise<Record<string, import("@redocly/theme/core/types").SearchFacetCount[]>>;
13
13
  export(outDir: string): Promise<void>;
14
14
  import(sourceDir: string): Promise<void>;
15
15
  cleanupFacetValues(actions: AfterRoutesCreatedActions): void;
@@ -1 +1 @@
1
- import{DEFAULT_LOCALE_PLACEHOLDER as s}from"../../../../constants/common.js";import{FlexSearch as n}from"./flexsearch/index.js";import{Typesense as a}from"./typesense/index.js";class l{type;l10n;#s={flexsearch:n,typesense:a};#e;constructor(e,t){this.type=e,this.l10n=t,this.#e=new this.#s[e]}async initIndexSchema(e){await this.#e.initIndexSchema?.(e)}async addDocuments(e,t){return this.#e.addDocuments(e,t)}async search(e,t){return this.#e.search({...e,locale:this.#t(e)},t)}async countFacets(e,t){return this.#e.countFacets({...e,locale:this.#t(e)},t)}async export(e){await this.#e.exportDocuments(e),await this.#e.exportIndexes(e)}async import(e){return this.#e.import(e)}#t(e){const t=e.locale||this.l10n?.defaultLocale||s;return t===this.l10n?.defaultLocale?s:t.toLowerCase()}cleanupFacetValues(e){return this.#e.cleanupFacetValues(e)}}export{l as SearchEngine};
1
+ import{DEFAULT_LOCALE_PLACEHOLDER as n}from"../../../../constants/common.js";import{FlexSearch as a}from"./flexsearch/index.js";import{Typesense as c}from"./typesense/index.js";class h{type;l10n;#s={flexsearch:a,typesense:c};#e;constructor(e,t){this.type=e,this.l10n=t,this.#e=new this.#s[e]}async initIndexSchema(e){await this.#e.initIndexSchema?.(e)}async addDocuments(e,t){return this.#e.addDocuments(e,t)}async search(e,t,s){return this.#e.search({...e,locale:this.#t(e)},t,s)}async countFacets(e,t,s){return this.#e.countFacets({...e,locale:this.#t(e)},t,s)}async export(e){await this.#e.exportDocuments(e),await this.#e.exportIndexes(e)}async import(e){return this.#e.import(e)}#t(e){const t=e.locale||this.l10n?.defaultLocale||n;return t===this.l10n?.defaultLocale?n:t.toLowerCase()}cleanupFacetValues(e){return this.#e.cleanupFacetValues(e)}}export{h as SearchEngine};
@@ -1,16 +1,16 @@
1
1
  import type { SearchFacet, SearchFacetCount } from '@redocly/theme/core/types';
2
2
  import type { SearchRequestParams, SearchResponse as ISearchResponse, FacetCountsRequestParams } from '../../../../../types/index.js';
3
- import type { AfterRoutesCreatedActions, SearchEngine, AddDocumentsParams, SearchDocument } from '../../../../types';
3
+ import type { AfterRoutesCreatedActions, SearchEngine, AuthDetails, AddDocumentsParams, SearchDocument } from '../../../../types';
4
4
  export declare class Typesense implements SearchEngine {
5
5
  #private;
6
6
  constructor();
7
7
  initIndexSchema(searchFacets: Map<string, SearchFacet>): Promise<void>;
8
8
  addDocuments(documents: SearchDocument[], params: AddDocumentsParams): Promise<void>;
9
- search(params: SearchRequestParams): Promise<ISearchResponse>;
9
+ search(params: SearchRequestParams, auth: AuthDetails): Promise<ISearchResponse>;
10
10
  exportDocuments(outDir: string): Promise<void>;
11
11
  exportIndexes(outDir: string): Promise<void>;
12
12
  import(_sourceDir: string): Promise<void>;
13
- countFacets(params: FacetCountsRequestParams, _facets: Map<string, SearchFacet>): Promise<Record<string, SearchFacetCount[]>>;
13
+ countFacets(params: FacetCountsRequestParams, auth: AuthDetails): Promise<Record<string, SearchFacetCount[]>>;
14
14
  cleanupFacetValues(actions: AfterRoutesCreatedActions): void;
15
15
  }
16
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- import{appendFile as E}from"node:fs/promises";import{existsSync as $}from"node:fs";import m from"node:path";import{Client as R}from"typesense";import{SEARCH_GROUP_FACET_FIELD as A,SEARCH_PRODUCT_FIELD as T,SEARCH_RBAC_FIELD as b,SEARCH_VERSION_FIELD as f}from"../../../../../constants/common.js";import{BASE_SEARCH_DOCUMENT as O,DISABLE_DEEP_LINK_IF_FIELDS_EXIST as P,HIGHLIGHTED_TEXT_MAX_LENGTH as F,SEARCH_DATA_EXPORT_FOLDER as S,SEARCH_DOCUMENT_METADATA_KEY as N,SEARCH_GROUP_LIMIT as C,SEARCH_MAX_FACET_VALUES as D,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as v}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as I}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as p}from"../../../../config/env-config.js";import{ensureDir as d}from"../../../../utils/index.js";class Y{#e=null;#o="";#t=[{name:"title",type:"string",facet:!1,optional:!0},{name:"text",type:"string",facet:!1,optional:!0},{name:"path",type:"string[]",facet:!1,optional:!0},{name:"isAdditionalOperation",type:"bool",facet:!1,optional:!0,queryable:!1},{name:"parameters",type:"object[]",facet:!1,optional:!0},{name:T,type:"string",facet:!0,optional:!0},{name:f,type:"object",facet:!0,optional:!0},{name:b,type:"string[]",facet:!0},{name:"metadata_curated",type:"bool",facet:!1,optional:!0,queryable:!1},{name:"metadata_keywords_excludes",type:"string[]",facet:!1,optional:!0,queryable:!1},{name:"metadata_keywords_includes",type:"string[]",facet:!1,optional:!0,queryable:!1}];#s=new Map;#n={ORGANIZATION_ID:p.ORGANIZATION_ID??"",PROJECT_ID:p.PROJECT_ID??"",TYPESENSE_API_URL:p.TYPESENSE_API_URL??"",TYPESENSE_API_KEY:p.TYPESENSE_API_KEY??""};constructor(){if(!p.isBuildMode){for(const[e,t]of Object.entries(this.#n))if(!t)throw new Error(`Cannot initialize search index. ${e} is not set`);this.#o=`${this.#n.ORGANIZATION_ID}_${this.#n.PROJECT_ID}_`,this.#e=new R({nodes:[{url:this.#n.TYPESENSE_API_URL}],apiKey:this.#n.TYPESENSE_API_KEY,connectionTimeoutSeconds:5})}}async initIndexSchema(e){this.#p(e)}async addDocuments(e,t){e.push(O);const{locale:r,outDir:n}=t,s=e.map(a=>{const o={...a},c=a[N];return c&&(c.curated&&(o.metadata_curated=c.curated),c.excludes&&(o.metadata_keywords_excludes=c.excludes),c.includes&&(o.metadata_keywords_includes=c.includes)),o}),i=this.#s.get(r)??[];this.#s.set(r,i.concat(s)),i.length+e.length>=v&&await this.exportDocuments(n)}async search(e){return await I("search",async t=>{const{query:r,locale:n,filter:s,loadMore:i,auth:a}=e,o=this.#c(n),c={collection:o,q:r||"*",query_by:this.#l(),max_facet_values:D};if(t?.setAttribute("collectionName",o),t?.setAttribute("locale",n),this.#e)if(i){const{groupKey:l,offset:u}=i,h={offset:u,filter_by:this.#r(a,s),facet_by:"*"};return t?.setAttribute("isLoadMore",!0),t?.setAttribute("filter",h.filter_by),this.#u(await this.#e.collections(o).documents().search({...c,...h}),l)}else{const l={group_by:this.#m(),group_limit:C,filter_by:this.#r(a,s)};t?.setAttribute("groups",l.group_by),t?.setAttribute("filter",l.filter_by);const u=[l,...this.#y(a,s)];return this.#f(await this.#e?.multiSearch.perform({searches:u},c),s)}else return{facets:{},documents:{}}})}#u(e,t){const r={facets:{},documents:{[t]:[]}};if(e.hits&&e.hits.length)for(const n of e.hits)r.documents[t].push({document:this.#a(n),highlight:this.#i(n)});return r}#f(e,t){const r={facets:{},documents:{}};for(const n of this.#_(t))r.documents[n]=[];if("results"in e)for(const n of e.results){if(n.facet_counts&&n.facet_counts.length)for(const s of n.facet_counts)r.facets[s.field_name]=s.counts.map(i=>({value:i.value,count:i.count}));if(n.grouped_hits&&n.grouped_hits.length)for(const s of n.grouped_hits){const i=s.group_key[0],a=[];for(const o of s.hits)a.push({document:this.#a(o),highlight:this.#i(o)});r.documents[i]=a}}return r}#a(e){return this.#h(e)}#i(e){const t={},r=[];for(const[n,s]of Object.entries(e.highlight??{}))if(Array.isArray(s)){if(n==="path"){const i=s,a=[];for(const o of i)a.push(o.snippet);t.path=a}else if(n==="parameters"){const i=s;for(const a of i){let o=!1;for(const[c,l]of Object.entries(a))if(c!=="deepLink")if(Array.isArray(l))for(const u of l)u.matched_tokens?.length&&(o=!0);else l.matched_tokens?.length&&(o=!0);if(o){const c={name:a.name?.snippet||"",description:a.description?.snippet||"",place:a.place?.snippet||"",path:a.path?.map(l=>l?.snippet)||[]};t.parameters=[c];break}}}}else t[n]=s.snippet,r.push(n);for(const[n,s]of Object.entries(e.document))!r.includes(n)&&typeof s=="string"&&(t[n]=s.length>F?`${s.substring(0,F)}...`:s);return t.parameters||(t.parameters=[]),t}#h(e){let t;const r=Object.keys(e.highlight);for(const s of P)if(r.some(i=>i===s))return e.document;const n=e.highlight.parameters;if(n){for(const s of n)for(const[i,a]of Object.entries(s))if(i!=="deepLink"){if(Array.isArray(a)){for(const o of a)if(o.matched_tokens?.length){t=s.deepLink.snippet;break}}else if(a.matched_tokens?.length){t=s.deepLink.snippet;break}}}if(t){const s=t.split("#")[1];return{...e.document,url:`${e.document.url}#${s}`}}return e.document}async exportDocuments(e){const t='{"documents":[',r=d(m.join(e,S));for(const[n,s]of this.#s){if(s.length===0)continue;const i=d(m.join(r,`${n}.json`)),a=!$(i),o=JSON.stringify(s).substring(1).slice(0,-1),c=a?t+o:","+o;await E(i,c,{encoding:"utf8"}),this.#s.set(n,[])}}async exportIndexes(e){const t=d(m.join(e,S));for(const r of this.#s.keys()){const n=d(m.join(t,`${r}.json`)),s=`],"schemaFields":${JSON.stringify(this.#t)}}`;await E(n,s,{encoding:"utf8"})}}async import(e){}async countFacets(e,t){return await I("search.facets",async r=>{const{locale:n,query:s,facetQuery:i,filter:a,field:o,auth:c}=e,l=this.#c(n),u={q:s||"*",query_by:this.#l(),facet_by:"*",facet_query:this.#d(i,o),filter_by:this.#r(c,a,o),max_facet_values:D};if(r?.setAttribute("collectionName",l),r?.setAttribute("query",u.q),r?.setAttribute("facetQuery",u.facet_query),r?.setAttribute("filter",u.filter_by),this.#e){const h={},_=await this.#e.collections(l).documents().search(u);if(_.facet_counts&&_.facet_counts.length)for(const y of _.facet_counts)h[y.field_name]=y.counts.map(g=>({value:g.value,count:g.count,isCounterVisible:!!s||(a?.length||0)>0}));return h}else return{}})}#c(e){return`${this.#o}${e}`}#p(e){for(const[t,{queryable:r}]of e)this.#t.find(n=>n.name===t)||this.#t.push({queryable:r,name:t,type:"string",facet:!0,optional:!0})}#l(){return this.#t.filter(e=>e.facet?e.queryable:e.queryable!==!1).map(e=>e.name).join(",")}#m(){return this.#t.filter(e=>e.facet&&e.name===A).map(e=>e.name).join(",")}#r(e,t,r){const n=`${b}:[${e.teams.map(i=>`'${i}'`).join(", ")}]`;let s=`${f}.isDefault:true`;if(t&&t.length){const i=t.filter(o=>o.field!==r&&o.field!==f).map(o=>{const c=o.values.map(l=>`'${l}'`);return c.length?`${o.field}:[${c.join(", ")}]`:""}).join(" && "),a=t.find(o=>o.field===f);if(a&&a.values.length&&a.values.length===2){const o=a.values[0],c=a.values[1],l=`(${f}.folderId:! ${o} && ${f}.isDefault:true)`,u=`(${f}.folderId:${o} && ${f}.version:${c})`;s=`(${l} || ${u})`}return i?`${n} && ${i} && ${s}`:`${n} && ${s}`}else return`${n} && ${s}`}#d(e,t){return e&&t?`${t}:${e}`:""}#_(e){const t=[];if(e&&e.length)for(const r of e)r.field===A&&t.push(...r.values);return t}#y(e,t){const r=[],n=this.#t.filter(s=>s.facet);for(const s of n){const i={facet_by:s.name,filter_by:this.#r(e,t,s.name)};r.push(i)}return r}cleanupFacetValues(e){const t=e.getSearchFacets();t.forEach(r=>{r.values=[]}),e.setSearchFacets(t)}}export{Y as Typesense};
1
+ import{appendFile as g}from"node:fs/promises";import{existsSync as I}from"node:fs";import m from"node:path";import{Client as $}from"typesense";import{SEARCH_GROUP_FACET_FIELD as E,SEARCH_PRODUCT_FIELD as R,SEARCH_RBAC_FIELD as A,SEARCH_VERSION_FIELD as f}from"../../../../../constants/common.js";import{BASE_SEARCH_DOCUMENT as T,DISABLE_DEEP_LINK_IF_FIELDS_EXIST as O,HIGHLIGHTED_TEXT_MAX_LENGTH as b,SEARCH_DATA_EXPORT_FOLDER as F,SEARCH_DOCUMENT_METADATA_KEY as P,SEARCH_GROUP_LIMIT as N,SEARCH_MAX_FACET_VALUES as S,SEARCH_MAX_INMEMORY_DOCUMENTS_COUNT as C}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as D}from"../../../../telemetry/helpers/trace-step.js";import{envConfig as p}from"../../../../config/env-config.js";import{ensureDir as d}from"../../../../utils/index.js";class U{#e=null;#o="";#t=[{name:"title",type:"string",facet:!1,optional:!0},{name:"text",type:"string",facet:!1,optional:!0},{name:"path",type:"string[]",facet:!1,optional:!0},{name:"isAdditionalOperation",type:"bool",facet:!1,optional:!0,queryable:!1},{name:"parameters",type:"object[]",facet:!1,optional:!0},{name:R,type:"string",facet:!0,optional:!0},{name:f,type:"object",facet:!0,optional:!0},{name:A,type:"string[]",facet:!0},{name:"metadata_curated",type:"bool",facet:!1,optional:!0,queryable:!1},{name:"metadata_keywords_excludes",type:"string[]",facet:!1,optional:!0,queryable:!1},{name:"metadata_keywords_includes",type:"string[]",facet:!1,optional:!0,queryable:!1}];#s=new Map;#n={ORGANIZATION_ID:p.ORGANIZATION_ID??"",PROJECT_ID:p.PROJECT_ID??"",TYPESENSE_API_URL:p.TYPESENSE_API_URL??"",TYPESENSE_API_KEY:p.TYPESENSE_API_KEY??""};constructor(){if(!p.isBuildMode){for(const[e,t]of Object.entries(this.#n))if(!t)throw new Error(`Cannot initialize search index. ${e} is not set`);this.#o=`${this.#n.ORGANIZATION_ID}_${this.#n.PROJECT_ID}_`,this.#e=new $({nodes:[{url:this.#n.TYPESENSE_API_URL}],apiKey:this.#n.TYPESENSE_API_KEY,connectionTimeoutSeconds:5})}}async initIndexSchema(e){this.#p(e)}async addDocuments(e,t){e.push(T);const{locale:n,outDir:r}=t,s=e.map(a=>{const o={...a},c=a[P];return c&&(c.curated&&(o.metadata_curated=c.curated),c.excludes&&(o.metadata_keywords_excludes=c.excludes),c.includes&&(o.metadata_keywords_includes=c.includes)),o}),i=this.#s.get(n)??[];this.#s.set(n,i.concat(s)),i.length+e.length>=C&&await this.exportDocuments(r)}async search(e,t){return await D("search",async n=>{const{query:r,locale:s,filter:i,loadMore:a}=e,o=this.#c(s),c={collection:o,q:r||"*",query_by:this.#l(),max_facet_values:S};if(n?.setAttribute("collectionName",o),n?.setAttribute("locale",s),this.#e)if(a){const{groupKey:l,offset:u}=a,h={offset:u,filter_by:this.#r(t,i),facet_by:"*"};return n?.setAttribute("isLoadMore",!0),n?.setAttribute("filter",h.filter_by),this.#u(await this.#e.collections(o).documents().search({...c,...h}),l)}else{const l={group_by:this.#m(),group_limit:N,filter_by:this.#r(t,i)};n?.setAttribute("groups",l.group_by),n?.setAttribute("filter",l.filter_by);const u=[l,...this.#y(t,i)];return this.#f(await this.#e?.multiSearch.perform({searches:u},c),i)}else return{facets:{},documents:{}}})}#u(e,t){const n={facets:{},documents:{[t]:[]}};if(e.hits&&e.hits.length)for(const r of e.hits)n.documents[t].push({document:this.#i(r),highlight:this.#a(r)});return n}#f(e,t){const n={facets:{},documents:{}};for(const r of this.#_(t))n.documents[r]=[];if("results"in e)for(const r of e.results){if(r.facet_counts&&r.facet_counts.length)for(const s of r.facet_counts)n.facets[s.field_name]=s.counts.map(i=>({value:i.value,count:i.count}));if(r.grouped_hits&&r.grouped_hits.length)for(const s of r.grouped_hits){const i=s.group_key[0],a=[];for(const o of s.hits)a.push({document:this.#i(o),highlight:this.#a(o)});n.documents[i]=a}}return n}#i(e){return this.#h(e)}#a(e){const t={},n=[];for(const[r,s]of Object.entries(e.highlight??{}))if(Array.isArray(s)){if(r==="path"){const i=s,a=[];for(const o of i)a.push(o.snippet);t.path=a}else if(r==="parameters"){const i=s;for(const a of i){let o=!1;for(const[c,l]of Object.entries(a))if(c!=="deepLink")if(Array.isArray(l))for(const u of l)u.matched_tokens?.length&&(o=!0);else l.matched_tokens?.length&&(o=!0);if(o){const c={name:a.name?.snippet||"",description:a.description?.snippet||"",place:a.place?.snippet||"",path:a.path?.map(l=>l?.snippet)||[]};t.parameters=[c];break}}}}else t[r]=s.snippet,n.push(r);for(const[r,s]of Object.entries(e.document))!n.includes(r)&&typeof s=="string"&&(t[r]=s.length>b?`${s.substring(0,b)}...`:s);return t.parameters||(t.parameters=[]),t}#h(e){let t;const n=Object.keys(e.highlight);for(const s of O)if(n.some(i=>i===s))return e.document;const r=e.highlight.parameters;if(r){for(const s of r)for(const[i,a]of Object.entries(s))if(i!=="deepLink"){if(Array.isArray(a)){for(const o of a)if(o.matched_tokens?.length){t=s.deepLink.snippet;break}}else if(a.matched_tokens?.length){t=s.deepLink.snippet;break}}}if(t){const s=t.split("#")[1];return{...e.document,url:`${e.document.url}#${s}`}}return e.document}async exportDocuments(e){const t='{"documents":[',n=d(m.join(e,F));for(const[r,s]of this.#s){if(s.length===0)continue;const i=d(m.join(n,`${r}.json`)),a=!I(i),o=JSON.stringify(s).substring(1).slice(0,-1),c=a?t+o:","+o;await g(i,c,{encoding:"utf8"}),this.#s.set(r,[])}}async exportIndexes(e){const t=d(m.join(e,F));for(const n of this.#s.keys()){const r=d(m.join(t,`${n}.json`)),s=`],"schemaFields":${JSON.stringify(this.#t)}}`;await g(r,s,{encoding:"utf8"})}}async import(e){}async countFacets(e,t){return await D("search.facets",async n=>{const{locale:r,query:s,facetQuery:i,filter:a,field:o}=e,c=this.#c(r),l={q:s||"*",query_by:this.#l(),facet_by:"*",facet_query:this.#d(i,o),filter_by:this.#r(t,a,o),max_facet_values:S};if(n?.setAttribute("collectionName",c),n?.setAttribute("query",l.q),n?.setAttribute("facetQuery",l.facet_query),n?.setAttribute("filter",l.filter_by),this.#e){const u={},h=await this.#e.collections(c).documents().search(l);if(h.facet_counts&&h.facet_counts.length)for(const _ of h.facet_counts)u[_.field_name]=_.counts.map(y=>({value:y.value,count:y.count,isCounterVisible:!!s||(a?.length||0)>0}));return u}else return{}})}#c(e){return`${this.#o}${e}`}#p(e){for(const[t,{queryable:n}]of e)this.#t.find(r=>r.name===t)||this.#t.push({queryable:n,name:t,type:"string",facet:!0,optional:!0})}#l(){return this.#t.filter(e=>e.facet?e.queryable:e.queryable!==!1).map(e=>e.name).join(",")}#m(){return this.#t.filter(e=>e.facet&&e.name===E).map(e=>e.name).join(",")}#r(e,t,n){const r=`${A}:[${e.teams.map(i=>`'${i}'`).join(", ")}]`;let s=`${f}.isDefault:true`;if(t&&t.length){const i=t.filter(o=>o.field!==n&&o.field!==f).map(o=>{const c=o.values.map(l=>`'${l}'`);return c.length?`${o.field}:[${c.join(", ")}]`:""}).join(" && "),a=t.find(o=>o.field===f);if(a&&a.values.length&&a.values.length===2){const o=a.values[0],c=a.values[1],l=`(${f}.folderId:! ${o} && ${f}.isDefault:true)`,u=`(${f}.folderId:${o} && ${f}.version:${c})`;s=`(${l} || ${u})`}return i?`${r} && ${i} && ${s}`:`${r} && ${s}`}else return`${r} && ${s}`}#d(e,t){return e&&t?`${t}:${e}`:""}#_(e){const t=[];if(e&&e.length)for(const n of e)n.field===E&&t.push(...n.values);return t}#y(e,t){const n=[],r=this.#t.filter(s=>s.facet);for(const s of r){const i={facet_by:s.name,filter_by:this.#r(e,t,s.name)};n.push(i)}return n}cleanupFacetValues(e){const t=e.getSearchFacets();t.forEach(n=>{n.values=[]}),e.setSearchFacets(t)}}export{U as Typesense};
@@ -1 +1 @@
1
- import{SitemapStream as l,streamToPromise as d}from"sitemap";import{Readable as p}from"stream";import{writeFileSync as y}from"fs";import g from"path";import{SITEMAP_FILE_NAME as h}from"../../constants/common.js";import{ServerRoutes as w}from"../../../constants/common.js";import{withPathPrefix as P}from"@redocly/theme/core/utils";import{logger as s}from"../../tools/notifiers/logger.js";import{isResourcePubliclyAccessible as b}from"../../utils/index.js";import{telemetryTraceStep as S}from"../../../cli/telemetry/helpers/trace-step.js";async function R(t,n){if(!t)return;const r=t.endsWith(".tsx"),i=t.endsWith(".md");if(!(!r&&!i))try{const o=r?"react-frontmatter":"markdown-frontmatter",e=await n.load(t,o);return e.data.frontmatter?.seo?.priority??e.data.seo?.priority}catch{return}}async function v(t,n){const r=t.fsPath?await R(t.fsPath,n):void 0;if(typeof r=="number"){if(r>=0&&r<=1)return r;s.warn(`Invalid SEO priority value "${r}" found for route "${t.slug}". Priority must be between 0 and 1. Using default priority instead.`)}const i=t.versions?.find(o=>o.active);return i?.default||!i?.5:.3}async function $(){return{id:"sitemap",async afterRoutesCreated(t,n){await S("build.plugin.sitemap",async r=>{const{seo:i}=t.getConfig();if(r?.setAttribute("config",JSON.stringify(i||{})),!i?.siteUrl)return;const o=t.getAllRoutes().filter(e=>!e.excludeFromSearch&&b(e,t.getConfig())&&!Object.keys(w).includes(e.slug));if(o.length)try{const e=g.join(t.outdir,h),m=new l({hostname:i.siteUrl}),c=await Promise.all(o.map(async a=>{const u=await v(a,n.cache);return{url:P(a.slug),priority:u}})),f=await d(p.from(c).pipe(m)).then(a=>a.toString());y(e,f),t.hasSitemap=!0}catch(e){r?.error(e),s.error(`Error creating sitemap: ${e.message}`)}})}}}export{$ as sitemapPlugin};
1
+ import{SitemapStream as l,streamToPromise as d}from"sitemap";import{Readable as p}from"stream";import{writeFileSync as y}from"fs";import g from"path";import{SITEMAP_FILE_NAME as h}from"../../constants/common.js";import{ServerRoutes as w}from"../../../constants/api.js";import{withPathPrefix as P}from"@redocly/theme/core/utils";import{logger as s}from"../../tools/notifiers/logger.js";import{isResourcePubliclyAccessible as b}from"../../utils/index.js";import{telemetryTraceStep as S}from"../../../cli/telemetry/helpers/trace-step.js";async function R(t,n){if(!t)return;const r=t.endsWith(".tsx"),i=t.endsWith(".md");if(!(!r&&!i))try{const o=r?"react-frontmatter":"markdown-frontmatter",e=await n.load(t,o);return e.data.frontmatter?.seo?.priority??e.data.seo?.priority}catch{return}}async function v(t,n){const r=t.fsPath?await R(t.fsPath,n):void 0;if(typeof r=="number"){if(r>=0&&r<=1)return r;s.warn(`Invalid SEO priority value "${r}" found for route "${t.slug}". Priority must be between 0 and 1. Using default priority instead.`)}const i=t.versions?.find(o=>o.active);return i?.default||!i?.5:.3}async function $(){return{id:"sitemap",async afterRoutesCreated(t,n){await S("build.plugin.sitemap",async r=>{const{seo:i}=t.getConfig();if(r?.setAttribute("config",JSON.stringify(i||{})),!i?.siteUrl)return;const o=t.getAllRoutes().filter(e=>!e.excludeFromSearch&&b(e,t.getConfig())&&!Object.keys(w).includes(e.slug));if(o.length)try{const e=g.join(t.outdir,h),m=new l({hostname:i.siteUrl}),c=await Promise.all(o.map(async a=>{const u=await v(a,n.cache);return{url:P(a.slug),priority:u}})),f=await d(p.from(c).pipe(m)).then(a=>a.toString());y(e,f),t.hasSitemap=!0}catch(e){r?.error(e),s.error(`Error creating sitemap: ${e.message}`)}})}}}export{$ as sitemapPlugin};
@@ -9,11 +9,11 @@ import type { SEARCH_DOCUMENT_METADATA_KEY } from '../../constants/plugins/searc
9
9
  export type SearchEngineType = 'flexsearch' | 'typesense';
10
10
  export type SearchEngine = {
11
11
  addDocuments(documents: SearchDocument[], params: AddDocumentsParams): Promise<void>;
12
- search(params: SearchRequestParams): Record<string, any>;
12
+ search(params: SearchRequestParams, auth: AuthDetails): Promise<SearchResponse>;
13
13
  exportDocuments(outDir: string, facets: Map<string, SearchFacet>): Promise<void>;
14
14
  exportIndexes(outDir: string, facets: Map<string, SearchFacet>): Promise<void>;
15
15
  import(sourceDir: string): Promise<void>;
16
- countFacets(params: FacetCountsRequestParams, facets: Map<string, SearchFacet>): Record<string, SearchFacetCount[]> | object;
16
+ countFacets(params: FacetCountsRequestParams, auth: AuthDetails, facets: Map<string, SearchFacet>): Record<string, SearchFacetCount[]> | object;
17
17
  };
18
18
  export type SearchDocumentMetadata = Partial<{
19
19
  includes: string[];
@@ -36,6 +36,14 @@ export type UserIDToken = {
36
36
  sub: string;
37
37
  [k: string]: unknown;
38
38
  };
39
+ export type ValidatedJsonInput<T> = {
40
+ in: {
41
+ json: T;
42
+ };
43
+ out: {
44
+ json: T;
45
+ };
46
+ };
39
47
  declare global {
40
48
  interface Request {
41
49
  context: RequestContext;
@@ -1 +1 @@
1
- import y from"path";import T from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as L,REDOCLY_ROUTE_RBAC as R}from"@redocly/config";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as x,ServerRoutes as w,PUBLIC_RBAC_SCOPE_ITEM as A,RBAC_ALL_OTHER_TEAMS as u,DEFAULT_RBAC_SCOPE as _}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as N}from"../constants/common.js";import{removeTrailingSlash as k}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as B}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as b}from"../../utils/path/parse-path-versions.js";import{reporter as M}from"../tools/notifiers/reporter.js";import{bold as W}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as U}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as $}from"../../utils/guards/is-truthy.js";import{canExpandConfig as v,expandRbacConfig as Y,getTeamFolderDefaults as z,parseTeamFoldersTemplate as K,parseTeamNameTemplate as H}from"./rbac-expand.js";import{getUserParamsFromCookies as G}from"../web-server/auth.js";import{getDeeperGlobPattern as V}from"./globs.js";import{EntitlementsProvider as J}from"../entitlements/entitlements-provider.js";const C=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],Q=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Tt(t,e){const r=C.indexOf(t.toUpperCase()),n=C.indexOf(e.toUpperCase());return r>n?t:e}const E={};function O(t,e){if(!t?.content)return A;const r=t.content,{slug:n,fsPath:s}=e;if(!n&&!s)return A;const o=f=>{const d=`slug:${f}`,p=E[d]??T(f);E[d]=p;const D=`fsPath:${f}`,S=E[D]??T(B(f));return E[D]=S,!!(n&&p(n))||!!(s&&S(s))};if(et(n||s||"")&&Object.keys(r).filter(p=>o(p)).length===0)return r[_]||A;const a=Object.keys(r).filter(f=>o(f));if(a.length==0)return A;const l=a.map(f=>T.scan(f,{tokens:!0,parts:!0}));let h=l[0];for(let f=1;f<l.length;f++)h=V(h,l[f]);return r[h.input]}function xt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const s=r.features?.[t];return s?e.teams.some(o=>s[o]&&s[o].toLowerCase()!=="none"):!0}function gt(t,e){return P(t,{isAuthenticated:!1,teams:[x]},e.access?.rbac||{},e.access?.requiresLogin||!1)}function P(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(w).some(a=>{const l=a.split(":")[0].replace(/\/$/,"");return t.slug===l||t.slug?.startsWith(a)})||typeof t.slug=="string"&&t.slug?.endsWith("/mcp")&&J.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const s=Y(r,e.teams||[]),o=t[L]||O(s,t[R]||{});if(Object.keys(o||{}).length===0)return!1;if(Object.keys(o).length===1&&o[u]&&o[u].toLowerCase()!=="none")return!0;const c=(e?.email?[...e?.teams||[],e?.email]:e?.teams)||[],i=[];for(const a of c??[])o[a]?i.push(o[a]):o[u]&&a!==e?.email&&i.push(o[u]);return i.length?i.some(a=>a.toLowerCase()!=="none"):!1}function Dt(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(I))return!0;const s=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${I}/`),""),c=s==="."?"":s,i={[R]:{slug:t,fsPath:c},slug:t};return P(i,n,e,r)}function St(t,e,r,n,s){if(!t.startsWith(N))return!0;const o=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!o)return!0;const c=n[o];if(!c)return!0;const{base:i,ext:a}=y.parse(t),l=i.split(".")[0],h=a.split(".").join(""),d=c==="."?"":c,p={[R]:{slug:t,fsPath:y.posix.join(d,`${l}.${h}`)},slug:t};return P(p,s,e,r)}async function Lt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:s,federatedIdToken:o,...c}=await G(t,e),{teams:i=[]}=c;let a;return r?a=i.filter(l=>l!==x):a=[x],{isAuthenticated:r,idpAccessToken:n,teams:a,claims:c}}function F(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const s=[];for(const o of t){const c=F(o,e,r,n);c!==void 0&&s.push(c)}return tt(s)}if(typeof t=="object"){if(!P(t,e,r,n))return;let s=!1;const o={};for(const c in t){if(c===L||c===R)continue;if(Q.has(c)){o[c]=t[c];continue}const i=F(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){s=!0;continue}i!==void 0&&(o[c]=i),c==="paths"&&X(i)&&Z(i)}return s?void 0:o}return t}function _t(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function It(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([o,c])=>o===_?[[o,c]]:[[o,c],...t.localeFolders.map(i=>[o.startsWith("/")?`/${i.toLocaleLowerCase()}${o}`:y.posix.join(t.localizationFolder,i,o),c])]),s=Object.fromEntries(n);return{...e,content:s}}async function jt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:s})=>{const{versionFolderPath:o}=b(s)||{},c=y.dirname(s);return o?[o,c]:c}));for(const s of n)r[U(s)]=s;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function X(t){return m(t)&&Object.keys(t).length>0}function Z(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function q(t){return m(t)&&t.type==="separator"}function tt(t){const e=[];let r;for(const n of t){if(q(n)){r=n;continue}r&&(e.push(r),r=void 0),e.push(n)}return e}function et(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const rt=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ct=async t=>{if(t){if(Object.keys(t).length===0)return{};if(rt(t))return nt(t);await M.panicOnContentError(`You are using an incorrect format of ${W("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},nt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const s=k(n);r[s]=e.content[n]}e.content=r}return e};function Ft(t,e){const r=t.fsPath,n=t.slug,s=[];if(v(e)&&(r||n)){const o=[r,n].filter($),c=K(e,o);if(c){const i=e?.teamNamePatterns?.map(l=>l.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];s.push(...i);const a=O({content:{...z(e),...e.content}},t);s.push(...g(a))}else{const i=O(e,t);s.push(...g(i))}}else{const o=O(e,t);s.push(...g(o))}return st(e,s)}function g(t){if(!t)return[];const e=[],r=u in t?{authenticated:t[u],anonymous:t[u]}:{};for(const[n,s]of Object.entries({...r,...t}))s.toLowerCase()!=="none"&&n!==u&&e.push(n);return e}function st(t,e){return e.map(n=>H(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{C as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,It as applyL10nToRbacConfig,St as canAccessAsset,xt as canAccessFeature,P as canAccessResource,Dt as canDownloadApiDefinition,st as expandTeamsForRead,g as extractTeamsFromScopeItems,F as filterDataByAccessDeep,Lt as getAuthDetailsFromCookies,Tt as getHigherRole,Ft as getRbacTeamsListForResource,O as getScopeItemsForResource,rt as isRbacConfigValid,gt as isResourcePubliclyAccessible,nt as normalizeRbacConfig,Ct as parseRbacConfig,_t as parseTeamClaimToArray,jt as resolveDirectoryHashes};
1
+ import y from"path";import T from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as L,REDOCLY_ROUTE_RBAC as R}from"@redocly/config";import{ServerRoutes as w}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as x,PUBLIC_RBAC_SCOPE_ITEM as A,RBAC_ALL_OTHER_TEAMS as u,DEFAULT_RBAC_SCOPE as _}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as N}from"../constants/common.js";import{removeTrailingSlash as k}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as B}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as b}from"../../utils/path/parse-path-versions.js";import{reporter as M}from"../tools/notifiers/reporter.js";import{bold as W}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as U}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as $}from"../../utils/guards/is-truthy.js";import{canExpandConfig as v,expandRbacConfig as Y,getTeamFolderDefaults as z,parseTeamFoldersTemplate as K,parseTeamNameTemplate as H}from"./rbac-expand.js";import{getUserParamsFromCookies as G}from"../web-server/auth.js";import{getDeeperGlobPattern as V}from"./globs.js";import{EntitlementsProvider as J}from"../entitlements/entitlements-provider.js";const C=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],Q=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function xt(t,e){const r=C.indexOf(t.toUpperCase()),n=C.indexOf(e.toUpperCase());return r>n?t:e}const E={};function O(t,e){if(!t?.content)return A;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return A;const s=f=>{const d=`slug:${f}`,p=E[d]??T(f);E[d]=p;const D=`fsPath:${f}`,S=E[D]??T(B(f));return E[D]=S,!!(n&&p(n))||!!(o&&S(o))};if(et(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[_]||A;const a=Object.keys(r).filter(f=>s(f));if(a.length==0)return A;const l=a.map(f=>T.scan(f,{tokens:!0,parts:!0}));let h=l[0];for(let f=1;f<l.length;f++)h=V(h,l[f]);return r[h.input]}function gt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?e.teams.some(s=>o[s]&&o[s].toLowerCase()!=="none"):!0}function Dt(t,e){return P(t,{isAuthenticated:!1,teams:[x]},e.access?.rbac||{},e.access?.requiresLogin||!1)}function P(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(w).some(a=>{const l=a.split(":")[0].replace(/\/$/,"");return t.slug===l||t.slug?.startsWith(a)})||typeof t.slug=="string"&&t.slug?.endsWith("/mcp")&&J.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=Y(r,e.teams||[]),s=t[L]||O(o,t[R]||{});if(Object.keys(s||{}).length===0)return!1;if(Object.keys(s).length===1&&s[u]&&s[u].toLowerCase()!=="none")return!0;const i=(e?.email?[...e?.teams||[],e?.email]:e?.teams)||[],c=[];for(const a of i??[])s[a]?c.push(s[a]):s[u]&&a!==e?.email&&c.push(s[u]);return c.length?c.some(a=>a.toLowerCase()!=="none"):!1}function St(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(I))return!0;const o=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${I}/`),""),i=o==="."?"":o,c={[R]:{slug:t,fsPath:i},slug:t};return P(c,n,e,r)}function Lt(t,e,r,n,o){if(!t.startsWith(N))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^\.]+$/)?.[1];if(!s)return!0;const i=n[s];if(!i)return!0;const{base:c,ext:a}=y.parse(t),l=c.split(".")[0],h=a.split(".").join(""),d=i==="."?"":i,p={[R]:{slug:t,fsPath:y.posix.join(d,`${l}.${h}`)},slug:t};return P(p,o,e,r)}async function _t(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...i}=await G(t,e),{teams:c=[]}=i;let a;return r?a=c.filter(l=>l!==x):a=[x],{isAuthenticated:r,idpAccessToken:n,teams:a,claims:i}}function F(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const i=F(s,e,r,n);i!==void 0&&o.push(i)}return tt(o)}if(typeof t=="object"){if(!P(t,e,r,n))return;let o=!1;const s={};for(const i in t){if(i===L||i===R)continue;if(Q.has(i)){s[i]=t[i];continue}const c=F(t[i],e,r,n);if(i==="items"&&Array.isArray(c)&&c.length===0&&t[i].length!==0){o=!0;continue}c!==void 0&&(s[i]=c),i==="paths"&&X(c)&&Z(c)}return o?void 0:s}return t}function It(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function jt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,i])=>s===_?[[s,i]]:[[s,i],...t.localeFolders.map(c=>[s.startsWith("/")?`/${c.toLocaleLowerCase()}${s}`:y.posix.join(t.localizationFolder,c,s),i])]),o=Object.fromEntries(n);return{...e,content:o}}async function Ct(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=b(o)||{},i=y.dirname(o);return s?[s,i]:i}));for(const o of n)r[U(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function X(t){return m(t)&&Object.keys(t).length>0}function Z(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function q(t){return m(t)&&t.type==="separator"}function tt(t){const e=[];let r;for(const n of t){if(q(n)){r=n;continue}r&&(e.push(r),r=void 0),e.push(n)}return e}function et(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const rt=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ft=async t=>{if(t){if(Object.keys(t).length===0)return{};if(rt(t))return nt(t);await M.panicOnContentError(`You are using an incorrect format of ${W("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},nt=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=k(n);r[o]=e.content[n]}e.content=r}return e};function wt(t,e){const r=t.fsPath,n=t.slug,o=[];if(v(e)&&(r||n)){const s=[r,n].filter($),i=K(e,s);if(i){const c=e?.teamNamePatterns?.map(l=>l.replace("{teamPathSegment}",i.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...c);const a=O({content:{...z(e),...e.content}},t);o.push(...g(a))}else{const c=O(e,t);o.push(...g(c))}}else{const s=O(e,t);o.push(...g(s))}return ot(e,o)}function g(t){if(!t)return[];const e=[],r=u in t?{authenticated:t[u],anonymous:t[u]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==u&&e.push(n);return e}function ot(t,e){return e.map(n=>H(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{C as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,jt as applyL10nToRbacConfig,Lt as canAccessAsset,gt as canAccessFeature,P as canAccessResource,St as canDownloadApiDefinition,ot as expandTeamsForRead,g as extractTeamsFromScopeItems,F as filterDataByAccessDeep,_t as getAuthDetailsFromCookies,xt as getHigherRole,wt as getRbacTeamsListForResource,O as getScopeItemsForResource,rt as isRbacConfigValid,Dt as isResourcePubliclyAccessible,nt as normalizeRbacConfig,Ft as parseRbacConfig,It as parseTeamClaimToArray,Ct as resolveDirectoryHashes};
@@ -1,12 +1,12 @@
1
- import"../node-crypto-polyfill.js";import{DOMParser as P}from"@xmldom/xmldom";import{SignedXml as J}from"xml-crypto";import q from"xpath";import{deflateSync as K,inflateSync as Y}from"fflate";import{createHash as Q}from"crypto";import{ulid as X}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as Z}from"@redocly/config";import{AUTH_URL as G,JWT_SECRET_KEY as C}from"../constants/common.js";import{envConfig as ee}from"../config/env-config.js";import{getPathPrefix as te,withPathPrefix as ne}from"@redocly/theme/core/utils";import{AuthCookieNames as A,DEFAULT_AUTHENTICATED_TEAM as re,REQUIRED_OIDC_SCOPES as N,ServerRoutes as R}from"../../constants/common.js";import{appendQueryParams as oe}from"../../utils/url/append-query-params.js";import{parseHttpsUrl as b}from"../../utils/url/parse-https-url.js";import{logger as ae}from"../tools/notifiers/logger.js";import{randomString as se}from"../utils/crypto/random-string.js";import{randomUUID as v}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as w,JwtTokenExpired as ie}from"./jwt/types.js";import*as f from"./jwt/jwt.js";import{parseTeamClaimToArray as ce}from"../utils/index.js";import{arrayBufferToBase64 as ue,decodeBase64 as U,encodeBase64URL as le,urlSafeBase64 as j}from"./jwt/encode.js";import{formatSamlCertificate as de}from"./utils/format-saml-certificate.js";function V(e){return e?.type===u.OIDC}function me(e){return e?.type===u.SAML2}async function Xe(e,t){if(V(t))return pe(e,t);if(me(t))return fe(e,t)}async function pe(e,t){const n=await F(e,t),r=new Set((t.scopes||[]).concat(N)),o=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:o,pkce:t.pkce}}function fe(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function Ze(e,t,n,r,o={}){const a=new Set((r.scopes||[]).concat(N));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:r.clientId,scope:Array.from(a).join(" "),code:t,redirect_uri:$(n),grant_type:"authorization_code",...r.clientSecret?{client_secret:r.clientSecret}:{},...o}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function he(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:a,idpId:s,pkce:l},m,g,p){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),h=p?.redirectUriOverride??`${e}${ne(R.OIDC_CALLBACK)}`,_={state:v(),idpId:s,redirectUri:h,redirectTo:m,branch:p?.branchOverride??ye(e),inviteCode:g,source:p?.sourceOverride??"portal",uiLocales:p?.uiLocales},y={};if(l){const d=j(se(50)),x=j(Q("sha256").update(d).digest("base64")),I="S256";i.searchParams.append("code_challenge",x),i.searchParams.append("code_challenge_method",I),y.code_verifier={value:d,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:te()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",$(h)),i.searchParams.append("state",le(JSON.stringify(_))),p?.uiLocales&&i.searchParams.append("ui_locales",p.uiLocales);for(const d in a)a[d]!==void 0&&i.searchParams.append(d,a[d]);return{loginUrl:i.toString(),cookies:y}}function Ge(e,t,n,r){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n),o.toString()}async function et(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return f.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpAccessToken?{idp_access_token:e.idpAccessToken}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},C,w.HS256)}async function tt(e){await f.verify(e,C,w.HS256);const{payload:t}=f.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 nt(e){const t=e||X(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function $(e){const t=b(e);if(!t)return e;const n=we(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,H(e,t);const r=B(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,H(e,t)):e}function ye(e){const t=b(e);if(t)return B(t.hostname)?.previewBranch}function H(e,t){return e.replace(/^https:\/\/[^/?#]+/i,`https://${t.host}`)}function B(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const a=n.slice(0,o),s=n.slice(o+2);return!a||!s||s.includes(".")?null:{projectSlug:a,previewBranch:s,after:r}}function we(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const a=t===-1?"":e.slice(t);return{previewBranch:o,after:a}}function Se(e){return e.type===u.OIDC}function Ae(e){return e.type===u.SAML2}function rt(e,t,n,r,o){return Se(e)?he(t,e,n,r,{uiLocales:o}):Ae(e)?ge(t,e,n,r,o):{}}function ge(e,t,n,r,o){const s=`<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
1
+ import"../node-crypto-polyfill.js";import{DOMParser as P}from"@xmldom/xmldom";import{SignedXml as J}from"xml-crypto";import q from"xpath";import{deflateSync as K,inflateSync as Y}from"fflate";import{createHash as Q}from"crypto";import{ulid as X}from"ulid";import{AuthProviderType as u,DEFAULT_TEAM_CLAIM_NAME as Z}from"@redocly/config";import{AUTH_URL as G,JWT_SECRET_KEY as C}from"../constants/common.js";import{envConfig as ee}from"../config/env-config.js";import{getPathPrefix as te,withPathPrefix as ne}from"@redocly/theme/core/utils";import{ServerRoutes as N}from"../../constants/api.js";import{AuthCookieNames as A,DEFAULT_AUTHENTICATED_TEAM as re,REQUIRED_OIDC_SCOPES as R}from"../../constants/common.js";import{appendQueryParams as oe}from"../../utils/url/append-query-params.js";import{parseHttpsUrl as b}from"../../utils/url/parse-https-url.js";import{logger as ae}from"../tools/notifiers/logger.js";import{randomString as se}from"../utils/crypto/random-string.js";import{randomUUID as v}from"../utils/crypto/random-uuid.js";import{AlgorithmTypes as w,JwtTokenExpired as ie}from"./jwt/types.js";import*as f from"./jwt/jwt.js";import{parseTeamClaimToArray as ce}from"../utils/index.js";import{arrayBufferToBase64 as ue,decodeBase64 as U,encodeBase64URL as le,urlSafeBase64 as j}from"./jwt/encode.js";import{formatSamlCertificate as de}from"./utils/format-saml-certificate.js";function V(e){return e?.type===u.OIDC}function me(e){return e?.type===u.SAML2}async function Ze(e,t){if(V(t))return pe(e,t);if(me(t))return fe(e,t)}async function pe(e,t){const n=await F(e,t),r=new Set((t.scopes||[]).concat(R)),o=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:o,pkce:t.pkce}}function fe(e,t){return{type:u.SAML2,idpId:e,name:"SAML2 provider",ssoUrl:t.ssoUrl,issuerId:t.issuerId,entityId:t.entityId||t.issuerId}}async function Ge(e,t,n,r,o={}){const a=new Set((r.scopes||[]).concat(R));return await fetch(e,{method:"POST",body:new URLSearchParams({client_id:r.clientId,scope:Array.from(a).join(" "),code:t,redirect_uri:$(n),grant_type:"authorization_code",...r.clientSecret?{client_secret:r.clientSecret}:{},...o}).toString(),headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"}}).then(s=>s.json())}function he(e,{authorizationEndpoint:t,clientId:n,responseType:r,scope:o,extraParams:a,idpId:s,pkce:l},m,g,p){if(!t||!n||!r||!o)return{loginUrl:void 0};const i=new URL(t),h=p?.redirectUriOverride??`${e}${ne(N.OIDC_CALLBACK)}`,_={state:v(),idpId:s,redirectUri:h,redirectTo:m,branch:p?.branchOverride??ye(e),inviteCode:g,source:p?.sourceOverride??"portal",uiLocales:p?.uiLocales},y={};if(l){const d=j(se(50)),x=j(Q("sha256").update(d).digest("base64")),I="S256";i.searchParams.append("code_challenge",x),i.searchParams.append("code_challenge_method",I),y.code_verifier={value:d,options:{secure:!0,httpOnly:!0,expires:new Date(Date.now()+1e3*60*10),path:te()||"/"}}}i.searchParams.append("client_id",n),i.searchParams.append("scope",o),i.searchParams.append("response_type",r),i.searchParams.append("redirect_uri",$(h)),i.searchParams.append("state",le(JSON.stringify(_))),p?.uiLocales&&i.searchParams.append("ui_locales",p.uiLocales);for(const d in a)a[d]!==void 0&&i.searchParams.append(d,a[d]);return{loginUrl:i.toString(),cookies:y}}function et(e,t,n,r){const o=new URL(e);return o.searchParams.append("post_logout_redirect_uri",t),r&&o.searchParams.append("state",r),o.searchParams.append("id_token_hint",n),o.toString()}async function tt(e){const t=Math.floor(Date.now()/1e3),n=t+(e.ttlSec??600);return f.sign({type:"mcp_auth_code",client_id:e.clientId,redirect_uri:e.redirectUri,id_token:e.idToken,...e.idpAccessToken?{idp_access_token:e.idpAccessToken}:{},...e.codeChallenge?{code_challenge:e.codeChallenge}:{},...e.codeChallengeMethod?{code_challenge_method:e.codeChallengeMethod}:{},iat:t,exp:n},C,w.HS256)}async function nt(e){await f.verify(e,C,w.HS256);const{payload:t}=f.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 rt(e){const t=e||X(),n=t.startsWith("mcp_")?t:`mcp_${t}`;return{id:n,object:"mcpSession",uri:`urn:redocly:realm:mcp:session:${n}`}}function $(e){const t=b(e);if(!t)return e;const n=we(t.hostname);if(n)return t.hostname=`previewauth--${n.previewBranch}${n.after}`,H(e,t);const r=B(t.hostname);return r?(t.hostname=`${r.projectSlug}.previewauth.${r.after}`,H(e,t)):e}function ye(e){const t=b(e);if(t)return B(t.hostname)?.previewBranch}function H(e,t){return e.replace(/^https:\/\/[^/?#]+/i,`https://${t.host}`)}function B(e){const t=e.split(".preview.",2);if(t.length<2)return null;const[n,r]=t,o=n.indexOf("--");if(o===-1)return null;const a=n.slice(0,o),s=n.slice(o+2);return!a||!s||s.includes(".")?null:{projectSlug:a,previewBranch:s,after:r}}function we(e){const t=e.indexOf("."),n=t===-1?e:e.slice(0,t);if(!n.startsWith("preview-"))return null;const r=n.indexOf("--");if(r===-1)return null;const o=n.slice(r+2);if(!o)return null;const a=t===-1?"":e.slice(t);return{previewBranch:o,after:a}}function Se(e){return e.type===u.OIDC}function Ae(e){return e.type===u.SAML2}function ot(e,t,n,r,o){return Se(e)?he(t,e,n,r,{uiLocales:o}):Ae(e)?ge(t,e,n,r,o):{}}function ge(e,t,n,r,o){const s=`<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
4
  ID="_${v()}"
5
5
  IssueInstant="${new Date().toISOString()}"
6
- AssertionConsumerServiceURL="${e}${R.SAML_CALLBACK}"
6
+ AssertionConsumerServiceURL="${e}${N.SAML_CALLBACK}"
7
7
  AttributeConsumingServiceIndex="0">
8
8
  <saml:Issuer>${t.entityId}</saml:Issuer>
9
9
  <samlp:NameIDPolicy
10
10
  AllowCreate="true"
11
11
  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
12
- </samlp:AuthnRequest>`,l=_e(s);return{loginUrl:oe(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function _e(e){return ue(K(new TextEncoder().encode(e)).buffer)}function ot(e){const t=U(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=Y(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function at(e){try{return JSON.parse(U(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function st(e){const t=new P().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,a=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,m=c(t,"//*[local-name(.)='Audience']/text()")[0],g=m&&m.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",h=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],_=h&&h.nodeValue||"",y=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],d=y&&y.nodeValue||"",x=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],I=xe(x),O={},D=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(D.length)for(const M of D){const k=c(M,"./@Name")[0];if(k.nodeValue){const E=c(M,"./*[local-name(.)='AttributeValue']/text()")[0];E?.nodeValue&&(O[k.nodeValue]=E.nodeValue)}}return{uid:_,success:r,expiresAt:I,issuerId:l,entityId:g,attrs:O,cert:i,nameFormat:d,destination:a}}function xe(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 T={},S={jwks:{}};async function F(e,t){if(!T[e]){const n=t.configurationUrl?await z(t.configurationUrl):t.configuration;T[e]=Ie()?Ce(n):n}return T[e]}function Ie(){const e=ee.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}function Ce(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Le(e){for(const t of Object.keys(e)){const n=e[t];if(!V(n))continue;const r=await F(t,n);if(r.jwks_uri){const o=await z(r.jwks_uri);for(const a of o.keys)S.jwks[a.kid]={...a,idpId:t}}}}async function z(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function it(e){return fetch(`${G}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function ct(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=>Te(t.hostname,r))}function Te(e,t){return e===t||e.endsWith(`.${t}`)}async function ut(e,t){const n=new P().parseFromString(e,"application/xml"),r=c(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 o=de(t),a=new J({publicCert:o});a.loadSignature(r);try{return a.checkSignature(e)}catch{return!1}}function lt(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 o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const a=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=a?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?a:void 0),o=o?.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"]||a,email:o,email_verified:!0,teams:r?ce(n[r]):[]}}function W(e,t={}){return e.map(n=>t[n]||n)}async function dt(e,t){if(!t)return{};const n=t[A.AUTHORIZATION];if(!n)return{};try{const r=f.decode(n);if(r.header.alg===w.RS256){S.jwks[r.header.kid]===void 0&&await Le(e);const m=S.jwks[r.header.kid];if(!m)return S.jwks[r.header.kid]=null,{};await f.verify(n,m,w.RS256)}else await f.verify(n,C,w.HS256);const o=r.payload.idpId||S.jwks[r.header.kid]?.idpId,a=e[o]||{},s=Me(a),l=De(a);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...W(r.payload.teams||[],l),..."defaultTeams"in a&&a.defaultTeams||[],...W("teamsClaimName"in a&&r.payload[s||""]||[],l),re])),name:Oe(r.payload),isAuthenticated:!0,idpAccessToken:r.payload.idp_access_token||t[A.IDP_ACCESS_TOKEN],federatedAccessToken:t[A.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[A.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof ie||ae.error("Malformed JWT token: %s",r.message)}return{}}function Oe(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function De(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Me(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return Z}}function c(e,t){return q.select(t,e)||[]}export{rt as buildLoginUrl,he as buildOidcLoginUrl,Ge as buildOidcLogoutUrl,ge as buildSAML2LoginUrl,et as createMcpAuthorizationCode,nt as createMcpSessionResource,ot as decodeSamlResponse,_e as encodeSAML2,lt as extractUserClaims,Xe as getAuthProviderLoginParams,pe as getOidcLoginParams,F as getOidcMetadata,it as getRedoclyTokenPayload,fe as getSaml2LoginParams,dt as getUserParamsFromCookies,Oe as getUsernameFromPayload,V as isOidcProviderConfig,ct as isRedoclySso,me as isSaml2ProviderConfig,Ze as oidcExchangeCodeForToken,S as oidcJwksCache,T as oidcMetadataCache,at as parseOidcState,ye as parsePreviewBranch,st as parseSamlResponse,$ as rewritePreviewAuthRedirectUri,tt as verifyMcpAuthorizationCode,ut as verifySAMLResponse};
12
+ </samlp:AuthnRequest>`,l=_e(s);return{loginUrl:oe(t.ssoUrl,{SAMLRequest:l,RelayState:JSON.stringify({idpId:t.idpId,redirectTo:n,inviteCode:r,source:"portal",uiLocales:o})})}}function _e(e){return ue(K(new TextEncoder().encode(e)).buffer)}function at(e){const t=U(e);if(t.startsWith("<samlp:Response")||t.indexOf("<saml2p:Response")>-1)return t;const n=Y(new Uint8Array(atob(e).split("").map(r=>r.charCodeAt(0))));return new TextDecoder().decode(n)}function st(e){try{return JSON.parse(U(e||""))}catch{throw new Error("Invalid OAuth2 state")}}function it(e){const t=new P().parseFromString(e,"application/xml"),r=c(t,"//*[local-name(.)='StatusCode']/@Value")[0]?.nodeValue?.endsWith("Success")||!1,a=c(t,"//*[local-name(.)='Response']/@Destination")[0]?.nodeValue||"",s=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='Issuer']/text()")[0],l=s&&s.nodeValue||void 0,m=c(t,"//*[local-name(.)='Audience']/text()")[0],g=m&&m.nodeValue||void 0,i=c(t,"//*[local-name(.)='Assertion']//*[local-name(.)='X509Certificate']/text()")[0]?.nodeValue||"",h=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/text()")[0],_=h&&h.nodeValue||"",y=c(t,"//*[local-name(.)='Subject']//*[local-name(.)='NameID']/@Format")[0],d=y&&y.nodeValue||"",x=c(t,"//*[local-name(.)='Conditions']/@NotOnOrAfter")[0],I=xe(x),O={},D=c(t,"//*[local-name(.)='AttributeStatement']//*[local-name(.)='Attribute']");if(D.length)for(const M of D){const k=c(M,"./@Name")[0];if(k.nodeValue){const E=c(M,"./*[local-name(.)='AttributeValue']/text()")[0];E?.nodeValue&&(O[k.nodeValue]=E.nodeValue)}}return{uid:_,success:r,expiresAt:I,issuerId:l,entityId:g,attrs:O,cert:i,nameFormat:d,destination:a}}function xe(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 T={},S={jwks:{}};async function F(e,t){if(!T[e]){const n=t.configurationUrl?await z(t.configurationUrl):t.configuration;T[e]=Ie()?Ce(n):n}return T[e]}function Ie(){const e=ee.REDOCLY_ENFORCE_RESIDENCY;return!!e&&e.includes("host.docker.internal")}function Ce(e){if(typeof e!="object"||e===null)return e;const t={...e};for(const n of Object.keys(t)){const r=t[n];typeof r=="string"&&r.includes("://localhost")&&(t[n]=r.replace("://localhost","://host.docker.internal"))}return t}async function Le(e){for(const t of Object.keys(e)){const n=e[t];if(!V(n))continue;const r=await F(t,n);if(r.jwks_uri){const o=await z(r.jwks_uri);for(const a of o.keys)S.jwks[a.kid]={...a,idpId:t}}}}async function z(e){return fetch(e,{headers:{Accept:"application/json"}}).then(t=>t.json())}async function ct(e){return fetch(`${G}/oidc/userinfo`,{headers:{Accept:"application/json",Authorization:`Bearer ${e}`}}).then(t=>t.status===200?t.json():void 0).catch(()=>{})}function ut(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=>Te(t.hostname,r))}function Te(e,t){return e===t||e.endsWith(`.${t}`)}async function lt(e,t){const n=new P().parseFromString(e,"application/xml"),r=c(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 o=de(t),a=new J({publicCert:o});a.loadSignature(r);try{return a.checkSignature(e)}catch{return!1}}function dt(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 o;(t==="urn:oasis:names:tc:SAML:2.0:nameid-format:email"||t==="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")&&(o=e),t==="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"&&e?.match(/.+@.+/)&&(o=e);const a=n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],s=a?.match(/.+@.+/);return o=o||n["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]||(s?a:void 0),o=o?.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"]||a,email:o,email_verified:!0,teams:r?ce(n[r]):[]}}function W(e,t={}){return e.map(n=>t[n]||n)}async function mt(e,t){if(!t)return{};const n=t[A.AUTHORIZATION];if(!n)return{};try{const r=f.decode(n);if(r.header.alg===w.RS256){S.jwks[r.header.kid]===void 0&&await Le(e);const m=S.jwks[r.header.kid];if(!m)return S.jwks[r.header.kid]=null,{};await f.verify(n,m,w.RS256)}else await f.verify(n,C,w.HS256);const o=r.payload.idpId||S.jwks[r.header.kid]?.idpId,a=e[o]||{},s=Me(a),l=De(a);return{...r.payload,email:r.payload.email?.toLowerCase(),idpId:o,teams:Array.from(new Set([...W(r.payload.teams||[],l),..."defaultTeams"in a&&a.defaultTeams||[],...W("teamsClaimName"in a&&r.payload[s||""]||[],l),re])),name:Oe(r.payload),isAuthenticated:!0,idpAccessToken:r.payload.idp_access_token||t[A.IDP_ACCESS_TOKEN],federatedAccessToken:t[A.FEDERATED_ACCESS_TOKEN],federatedIdToken:t[A.FEDERATED_ID_TOKEN],authCookie:n}}catch(r){r instanceof ie||ae.error("Malformed JWT token: %s",r.message)}return{}}function Oe(e){return(e.firstName&&e.lastName?`${e.firstName} ${e.lastName}`:e.name||e.given_name||e.firstName||e.lastName)||e.email}function De(e){switch(e.type){case u.SAML2:return e.teamsAttributeMap;case u.OIDC:return e.teamsClaimMap;default:return}}function Me(e){switch(e.type){case u.SAML2:return e.teamsAttributeName;case u.OIDC:return e.teamsClaimName;default:return Z}}function c(e,t){return q.select(t,e)||[]}export{ot as buildLoginUrl,he as buildOidcLoginUrl,et as buildOidcLogoutUrl,ge as buildSAML2LoginUrl,tt as createMcpAuthorizationCode,rt as createMcpSessionResource,at as decodeSamlResponse,_e as encodeSAML2,dt as extractUserClaims,Ze as getAuthProviderLoginParams,pe as getOidcLoginParams,F as getOidcMetadata,ct as getRedoclyTokenPayload,fe as getSaml2LoginParams,mt as getUserParamsFromCookies,Oe as getUsernameFromPayload,V as isOidcProviderConfig,ut as isRedoclySso,me as isSaml2ProviderConfig,Ge as oidcExchangeCodeForToken,S as oidcJwksCache,T as oidcMetadataCache,st as parseOidcState,ye as parsePreviewBranch,it as parseSamlResponse,$ as rewritePreviewAuthRedirectUri,nt as verifyMcpAuthorizationCode,lt as verifySAMLResponse};
@@ -1 +1 @@
1
- import{ServerRoutes as c}from"../../constants/common.js";import{reporter as n}from"../tools/notifiers/reporter.js";import{logger as s}from"../tools/notifiers/logger.js";import{telemetry as p}from"../telemetry/index.js";import{installDevRoutes as f,installProdRoutes as v}from"./routes/index.js";import{createRouter as l}from"./router.js";import{readStaticAsset as u}from"./node-asset-reader.js";import{startHttpServer as d}from"./http.js";import{listenStore as S}from"./store-ws.js";import{ejectComponentDataHandler as D}from"./routes/eject.js";import{attachWsServer as R}from"./ws.js";import{DatabasePreconnectService as w}from"../providers/database/database-preconnect-service.js";import{KvService as g}from"../persistence/kv/services/kv-service.js";import{runScorecardsWorker as O}from"../plugins/scorecards/workers/run-scorecards-worker.js";import{isScorecardsEnabled as E}from"../utils/is-scorecards-enabled.js";import{isRealmOrReef as b}from"../utils/is-realm-or-reef.js";async function J(r,i,a){p.initialize(!0);const{port:m=4e3}=a,t=l();if(t.get(c.EJECT_COMPONENT,D(r)),f(t,r),v(t,r,{readStaticAsset:u,resolveRouteData:e=>r.resolveRouteStaticData(e,i)}),b()){await w.init(r.serverOutDir);const e=await g.getInstance({baseDbDir:r.serverOutDir});setInterval(()=>{e.clearExpired().catch(o=>{s.error("Failed to clear expired KV entries",o)})},300*1e3)}try{await r.userCodeReady;const e=await d(t,m),o=R(e);S(r,o),E(r.config)&&await O(r.serverOutDir,r.config.scorecards)}catch(e){await n.panic(e)}}export{J as startDevServer};
1
+ import{ServerRoutes as c}from"../../constants/api.js";import{reporter as n}from"../tools/notifiers/reporter.js";import{logger as s}from"../tools/notifiers/logger.js";import{telemetry as p}from"../telemetry/index.js";import{installDevRoutes as f,installProdRoutes as v}from"./routes/index.js";import{createRouter as l}from"./router.js";import{readStaticAsset as u}from"./node-asset-reader.js";import{startHttpServer as d}from"./http.js";import{listenStore as S}from"./store-ws.js";import{ejectComponentDataHandler as D}from"./routes/eject.js";import{attachWsServer as R}from"./ws.js";import{DatabasePreconnectService as w}from"../providers/database/database-preconnect-service.js";import{KvService as g}from"../persistence/kv/services/kv-service.js";import{runScorecardsWorker as O}from"../plugins/scorecards/workers/run-scorecards-worker.js";import{isScorecardsEnabled as E}from"../utils/is-scorecards-enabled.js";import{isRealmOrReef as b}from"../utils/is-realm-or-reef.js";async function J(r,i,a){p.initialize(!0);const{port:m=4e3}=a,t=l();if(t.get(c.EJECT_COMPONENT,D(r)),f(t,r),v(t,r,{readStaticAsset:u,resolveRouteData:e=>r.resolveRouteStaticData(e,i)}),b()){await w.init(r.serverOutDir);const e=await g.getInstance({baseDbDir:r.serverOutDir});setInterval(()=>{e.clearExpired().catch(o=>{s.error("Failed to clear expired KV entries",o)})},300*1e3)}try{await r.userCodeReady;const e=await d(t,m),o=R(e);S(r,o),E(r.config)&&await O(r.serverOutDir,r.config.scorecards)}catch(e){await n.panic(e)}}export{J as startDevServer};