@redocly/revel 0.128.0-next.7 → 0.128.0-next.8
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.
- package/CHANGELOG.md +14 -0
- package/dist/server/plugins/default-theme/index.js +1 -1
- package/dist/server/plugins/markdown/index.js +1 -1
- package/dist/server/plugins/openapi-docs/format-bundle-error.d.ts +6 -0
- package/dist/server/plugins/openapi-docs/format-bundle-error.js +5 -0
- package/dist/server/plugins/openapi-docs/index.js +1 -1
- package/dist/server/plugins/openapi-docs/load-definition.js +3 -3
- package/dist/server/plugins/pages/index.js +1 -1
- package/dist/server/plugins/scorecard-classic/index.js +1 -1
- package/dist/server/plugins/search/ai-indexer/prepare-ai-search-documents.js +1 -1
- package/dist/server/plugins/search/documents/search-documents.js +1 -1
- package/dist/server/plugins/sitemap/index.js +1 -1
- package/dist/server/store.d.ts +1 -1
- package/dist/server/types/plugins/common.d.ts +1 -0
- package/dist/server/utils/catalog-classic/get-route-slug-to-catalog-slug-map.d.ts +19 -0
- package/dist/server/utils/catalog-classic/get-route-slug-to-catalog-slug-map.js +1 -0
- package/dist/server/utils/catalog-classic/get-route-slug-to-catalog-slug-map.test.d.ts +2 -0
- package/dist/server/utils/catalog-classic/get-route-slug-to-catalog-slug-map.test.js +1 -0
- package/dist/server/web-server/routes/replay-oauth2-redirect.js +78 -33
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @redocly/revel
|
|
2
2
|
|
|
3
|
+
## 0.128.0-next.8
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5cd6434fa4: Pages with the `excludeFromSearch` front matter option are also excluded from the sitemap.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 81dc45dc56: Updated `@redocly/openapi-core` to version `2.12.1`.
|
|
12
|
+
- Updated dependencies [81dc45dc56]
|
|
13
|
+
- @redocly/openapi-docs@3.16.0-next.8
|
|
14
|
+
- @redocly/asyncapi-docs@1.5.0-next.8
|
|
15
|
+
- @redocly/portal-plugin-mock-server@0.13.0-next.8
|
|
16
|
+
|
|
3
17
|
## 0.128.0-next.7
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{DEFAULT_SSO_IDP_TITLE as b,DEV_LOGIN_SLUG as g,INVITE_SLUG as
|
|
1
|
+
import{REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{DEFAULT_SSO_IDP_TITLE as b,DEV_LOGIN_SLUG as g,INVITE_SLUG as T,PUBLIC_RBAC_SCOPE_ITEM as f,UI_ACCESSIBLE_CONFIG_PROPS as D,CONFIG_FILE_NAME as l}from"../../../constants/common.js";import{isDevelopMode as P}from"../../utils/envs/is-develop-mode.js";import{getTemplatePath as s}from"./get-template-path.js";import{resolveLinksFromConfig as n}from"../nav-utils.js";import{resolveLogoConfig as F}from"./resolve-logo.js";import{extractTeamNames as _}from"./extract-team-names.js";import{resolveProductsConfig as E}from"./resolve-products-config.js";import{getExcludedFromLinkCheckerPatterns as y}from"../sidebars/utils.js";import{resolveEntitiesCatalogConfig as O}from"./resolve-catalog-entities.js";import{telemetryTraceStep as A}from"../../../cli/telemetry/helpers/trace-step.js";async function q(i){return{id:"Default Theme",async processContent(e){await A("build.plugin.default_theme",async()=>{const t=v(e),a=Object.keys(e.getConfig()?.ssoDirect||{}).length>0,o=e.createTemplate("invite",s("../../../../dist/client/app/pages/Invite/Invite.js"));if(e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,excludeFromSearch:!0,slug:T,[c]:f,fsPath:T,templateId:o}),i.devLogin&&a){let r={frontmatter:{},seo:{title:"Login page"},authIdps:t.filter(u=>u.title!=b),rbac:{teams:_(e.getConfig().rbac)}};const p=e.createTemplate("dev-login",s("../../../../dist/client/app/pages/DevLogin/DevLogin.js"));e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,excludeFromSearch:!0,slug:g,[c]:f,fsPath:g,templateId:p,getStaticData:async()=>({props:r})})}else if(t.length>1){let r={frontmatter:{},seo:{title:"Login page"},authIdps:t};const p=e.createTemplate("login",s("../../../../dist/client/app/pages/Login/Login.js"));e.addRoute({duplicateInAllLocales:!0,excludeFromSidebar:!0,slug:g,[c]:f,fsPath:g,templateId:p,getStaticData:async()=>({props:r})})}e.createTemplate("404",s("../../../../dist/client/app/pages/404/404.js")),e.createTemplate("403",s("../../../../dist/client/app/pages/403/403.js")),e.createTemplate("403OIDC",s("../../../../dist/client/app/pages/403/403OIDC.js")),P()&&e.createTemplate("compilation-error",s("../../../../dist/client/app/pages/CompilationError/CompilationError.js"))})},async afterRoutesCreated(e,t){const{contentDir:a,outdir:o}=e,r=e.getConfig(),{navbar:p,footer:u,userMenu:m,search:I,breadcrumbs:C,products:S}=r,L=Object.keys(r?.ssoDirect||{}).length>0,d=y(r),h={navFile:l,excludedFromLinkCheckerPatterns:d};e.setGlobalData({...j(r),navbar:await n(p,a,e,t,h),footer:await n(u,a,e,t,h),breadcrumbs:{...C,prefixItems:await n(C?.prefixItems||[],a,e,t,{navFile:l,excludedFromLinkCheckerPatterns:d})},userMenu:{...m,hide:m?.hide??!L,menu:await n(m?.items,a,e,t,{navFile:l,excludedFromLinkCheckerPatterns:d})},logo:await F(r.logo,l,o,t.fs),auth:{idpsInfo:v(e),devLogin:i.devLogin&&L},products:await E(S,e,t),search:{...I,suggestedPages:await n(I?.suggestedPages,a,e,t,{navFile:l,excludedFromLinkCheckerPatterns:d})},entitiesCatalog:await O(r.entitiesCatalog,l,o,t.fs),headScriptTags:void 0,linkTags:void 0,postBodyScriptTags:void 0,preBodyScriptTags:void 0})}}}function v(i){const e=i.getConfig().ssoDirect;return Object.entries(e||{}).map(([a,o])=>({idpId:a,type:o.type,title:o.title}))}function j(i){const e={};for(const t of D)i[t]&&(e[t]=i[t]);return e}export{q as defaultThemePlugin,j as pickUiAccessibleConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import u from"path";import{REDOCLY_TEAMS_RBAC as
|
|
1
|
+
import u from"path";import{REDOCLY_TEAMS_RBAC as F}from"@redocly/config";import{MARKDOC_PARTIALS_DATA_KEY as D}from"../../store.js";import{reporter as R}from"../../tools/notifiers/reporter.js";import{extractMdFirstHeading as b,getAst as A}from"./compiler.js";import{getTemplatePath as w}from"./get-template-path.js";import{prepareMarkdocPartials as C}from"./markdoc/partials.js";import{searchResolver as M}from"./search/search-resolver.js";import{markdownStaticDataLoader as T}from"./markdown-static-data-loader.js";import{makeErrorRoute as E}from"../error-route.js";import{validateRbacConfig as I}from"../validate-rbac-config.js";import{findFrontmatterSlugs as O,getSidebarSharedDataId as _,resolveFrontmatterSlugs as G}from"../utils.js";import{isPartial as L}from"./is-partial.js";import{markdownFrontmatterLoader as j}from"./markdown-frontmatter-loader.js";import{resolveRawPartials as z}from"./markdoc/resolve-raw-partials.js";import{getAiDocumentsStore as B}from"./search/get-ai-search-documents.js";import{registerPageProps as K}from"../register-page-props.js";import{sanitizeMalformedMdContent as N}from"./utils/sanitize-malformed-md-content.js";import{telemetryTraceStep as W}from"../../../cli/telemetry/helpers/trace-step.js";async function nt(h){return{id:"markdoc",requiredEntitlements:["markdown"],loaders:{"markdown-frontmatter":j,"markdown-ast":async(e,r)=>{const i=await r.fs.read(e),n=await r.getConfig(),d=await z(i,e,n?.markdown?.partialsFolders,r),l=N(d);return A(e,l)}},processContent:async(e,r)=>{await W("build.plugin.markdown",async i=>{const{markdown:n}=await r.getConfig();i?.setAttribute("config",JSON.stringify(n||{}));const d=n?.partialsFolders??[],l=e.createTemplate("markdown","@redocly/theme/core/templates/Markdown"),S=e.registerServerPropsGetter("markdown",w("./get-server-props.js"));e.createTemplate("error",w("../../../client/app/Error/ErrorDetails.js"));for(const o of await r.fs.scan(/\.md$/))if(!await r.isPathIgnored(o.relativePath)&&!L(o.relativePath,d))try{await k(o)}catch(a){e.addRoute(E(o.relativePath,a)),i?.error(a),await R.panicOnBuild("Failed to create route for markdown file: %s",a.message)}async function k(o){const{relativePath:a,realRelativePath:P}=o,{data:{frontmatter:t}}=await r.cache.load(a,"markdown-frontmatter"),v=t?.metadata||{},y=await O(a,"markdown-frontmatter",t,r),c=G(y,a);let f=null;t?.sidebar&&(f=await _(t.sidebar,a,r.fs));let g=l;if(t?.template){const p=t.template.startsWith("./")||t.template.startsWith("../");let m=t.template;if(p){const s=u.posix.dirname(P);m=u.resolve(h.contentDir,s,t.template)}g=e.createTemplate(t.template,m)}t?.rbac&&I({content:{[a]:t.rbac}}),await K(o,r.fs,e),(c.length?c.reverse():[void 0]).forEach(p=>{e.addRoute({excludeFromSearch:t?.excludeFromSearch||!1,slug:p,fsPath:a,templateId:g,sharedData:f?[{id:f,key:"sidebar"}]:void 0,redirectFrom:Object.entries(t.redirects||{}).map(([m,{type:s}])=>({type:s||301,from:m})),[F]:t?.rbac,getNavText:async()=>(t?.seo?.title||await b(a,r)||"").toString(),metadata:{type:"markdown",...v},async getStaticData(m,s){return T(o,m,r,t,s)},getSearchDocuments:M(t,a,e.getSearchFacets,e.setSearchFacets),getAiDocumentsStore:B(e.getSearchFacets,t),serverPropsGetterIds:[S]})})}})},afterRoutesCreated:async(e,r)=>{const i=await C(r,e);e.setGlobalConfig({[D]:i})}}}export{nt as markdownPlugin};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type NormalizedProblem } from '@redocly/openapi-core';
|
|
2
|
+
/**
|
|
3
|
+
* Formats a bundle error with file path, line/column, and codeframe for better debugging.
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatBundleError(problem: NormalizedProblem, cwd: string): Promise<string>;
|
|
6
|
+
//# sourceMappingURL=format-bundle-error.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{getLineColLocation as f,isAbsoluteUrl as m}from"@redocly/openapi-core";import g from"node:path";import{gray as s}from"../../tools/notifiers/helpers/colors.js";import{getCodeframe as h}from"../../utils/codeframes/codeframes.js";async function P(o,c){const e=o.location?.[0];if(!e)return`${o.message} at `;if(!e.source){const t=e.pointer??"";return`${o.message} at ${t}`}const n=m(e.source.absoluteRef)?e.source.absoluteRef:g.relative(c,e.source.absoluteRef);try{const t=f(e),i=e.pointer?s(`at ${e.pointer}`):"",l=`${n}:${t.start.line}:${t.start.col}`;let r="";try{const a=e.source?.getLines()??[],u={start:{line:t.start.line,character:t.start.col},end:{line:t.end?.line??t.start.line,character:t.end?.col??Math.max(t.start.col+1,a[t.start.line-1]?.length??t.start.col)},lines:a},{frame:$}=h(u,!0);r=$}catch{r=""}return`${l} ${i}
|
|
2
|
+
${o.message}
|
|
3
|
+
${r?`${r}
|
|
4
|
+
`:""}`}catch{const t=e.pointer?s(`at ${e.pointer}`):"";return`${n} ${t}
|
|
5
|
+
${o.message}`}}export{P as formatBundleError};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Z from"node:path";import{simplifyAstStructure as ee}from"@redocly/openapi-docs";import{REDOCLY_TEAMS_RBAC as _}from"@redocly/config";import{OPENAPI_DOCS_TEMPLATE_ID as G,PUBLIC_RBAC_SCOPE_ITEM as $}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as te,PUBLIC_API_DEFINITIONS_FOLDER as oe}from"../../constants/common.js";import{OPENAPI_CUSTOM_FIELDS_SERVER_PROPS_GETTER_ID as ae,OPENAPI_SHARED_DATA_PREFIX as H}from"../../constants/plugins/openapi-docs.js";import{slash as re}from"../../../utils/path/slash.js";import{isDevelopMode as U}from"../../utils/envs/is-develop-mode.js";import{searchResolver as se}from"./search/search-resolver.js";import{convertOpenAPIDocs2Sidebar as ie,shouldAddRoute as ne}from"./utils.js";import{getTemplatePath as
|
|
1
|
+
import Z from"node:path";import{simplifyAstStructure as ee}from"@redocly/openapi-docs";import{REDOCLY_TEAMS_RBAC as _}from"@redocly/config";import{OPENAPI_DOCS_TEMPLATE_ID as G,PUBLIC_RBAC_SCOPE_ITEM as $}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as te,PUBLIC_API_DEFINITIONS_FOLDER as oe}from"../../constants/common.js";import{OPENAPI_CUSTOM_FIELDS_SERVER_PROPS_GETTER_ID as ae,OPENAPI_SHARED_DATA_PREFIX as H}from"../../constants/plugins/openapi-docs.js";import{slash as re}from"../../../utils/path/slash.js";import{isDevelopMode as U}from"../../utils/envs/is-develop-mode.js";import{searchResolver as se}from"./search/search-resolver.js";import{convertOpenAPIDocs2Sidebar as ie,shouldAddRoute as ne}from"./utils.js";import{getTemplatePath as L}from"./get-template-path.js";import{storeDefinitionBundles as pe}from"./store-definition-bundles.js";import{definitionLoader as ce,definitionsLoader as de}from"./load-definition.js";import{getAiDocumentsStore as le}from"./search/get-ai-search-documents.js";import{fromCurrentDir as ue}from"../../utils/paths.js";import{telemetryTraceStep as me}from"../../../cli/telemetry/helpers/trace-step.js";const M="openapi-spec-download";async function Te(V){let w=[],E={};return{id:"openapi",requiredEntitlements:["openapi"],loaders:{"load-oas-docs":de,"load-oas":ce},processContent:async(e,i)=>{await me("build.plugin.openapi_docs",async d=>{e.createRequestHandler(M,ue(import.meta.url,"./spec-download.api.js")),e.addApiRoute({slug:oe+"/*",requestHandlerId:M,httpMethod:"all",[_]:$,getStaticData:async()=>({props:{}})}),e.addApiRoute({slug:te+"/*",requestHandlerId:M,httpMethod:"all",[_]:$,getStaticData:async()=>({props:{}})});const s=e.createTemplate(G,L("./template/OpenAPIDocs.js")),n=e.registerServerPropsGetter(G,L("./get-server-props.js")),g=e.registerServerPropsGetter(ae,L("./get-server-props-custom-fields.js")),l=await i.getConfig();d?.setAttribute("config",JSON.stringify(l.openapi||{}));const I=l.rules?.["custom-fields-schema"];E={};const u=await e.loadOpenApiDefinitions(i);w=u.map(({markdocChunks:m,relativePath:f,customOutputRelativeFile:r,isVirtual:a,realRelativePath:p})=>({chunks:m,relativePath:f,realRelativePath:p,isVirtual:r!=null||a})),pe(u,e.outdir);const P={};for(const m of u||[]){const{definition:f,config:r,relativePath:a,customOutputRelativeFile:p,contentItems:S,flatItems:D,parser:v,options:k,rawOptions:q,hash:J}=m,x=p||a,o=[],B={},{definition:Q}=v||{},{info:c}=Q||{},O=c?.["x-metadata"],C=!!r.openapi?.excludeFromSearch||!!r.theme?.openapi?.excludeFromSearch||!!l.openapi?.excludeFromSearch||!!l.theme?.openapi?.excludeFromSearch,N={title:c?.title,description:c?.description,summary:c?.summary,...r.metadata,...O},h={untagged:[],tagged:new Map};for(const t of D){const{id:y,href:A,operationDefinition:F}=t;if(F){const{tags:R}=F;if(R)for(const b of R)h.tagged.has(b)||h.tagged.set(b,[]),h.tagged.get(b)?.push(t);else h.untagged.push(t);U()&&(B[`#${F.pointer}`]=t.href)}if(!ne({item:t}))continue;const T=t,Y=T.type==="section"&&!!T.infoDefinition,z=A.split("#")[0]+"/",K=t?.operationDefinition?.[_];o.push({excludeFromSearch:C,slugSuffix:z,fsPath:x,httpVerb:t?.httpVerb||"",path:a,templateId:s,[_]:K||r.rbac,getAiDocumentsStore:le({parser:v,options:k,info:c,tagOperations:h,openapiContentItem:T,metadata:N,relativePath:a,getSearchFacets:e.getSearchFacets,includeInLLMsTxt:Y,excludeFromSearch:C}),getStaticData:async R=>({props:{dynamicMarkdocComponents:["openapi"],baseSlug:R.baseSlug,seo:t["x-metadata"]?.seo||{title:t.name,description:t.description},itemId:y,disableAutoScroll:!0}})})}o[0]={...o[0],metadata:{type:"openapi",...N},hasClientRoutes:!0,getSidebar:(t,y)=>{const A=[];return ie({contentItems:S,sidebarItems:A,routeSlug:t.slug,navItem:y}),A},getNavText:()=>c?.title,getSearchDocuments:se(v,k,D,e.getSearchFacets,e.setSearchFacets,C)},O?.apiId&&(P[O.apiId]={slug:o[0]?.slug||""});const W=o[0];o[0]=o[o.length-1],o[o.length-1]=W;for(const t of o)e.addRoute({...t,serverPropsGetterIds:I?[n,g]:[n]});const X=U()?a:void 0,j=`${H}${a}`;E[j]={fsPath:x,definition:f,options:q,sourcePath:X,routesMapping:B,hash:J};for(const t of o)e.addRoute({...t,sharedData:[{id:j,key:"openAPIDocsStore"}],serverPropsGetterIds:I?[n,g]:[n]})}e.setGlobalData({apiProducts:P})})},afterRoutesCreated:async(e,i)=>{for(const{chunks:d,relativePath:s,isVirtual:n,realRelativePath:g}of w)await i.cache.load(s,{loader:async function(){await i.cache.load(g,"load-oas");for(const{node:I,markdown:u,pointer:P,key:m,relativePath:f}of d){const[r,...a]=P.split("#"),p=a.join("#"),S=re(Z.relative(V.contentDir,r)),{ast:D}=await e.parseMarkdoc({content:u,relativePath:S,isVirtual:n,cacheId:S+(p?"#"+p:"")},i,{sharedDataIds:[`${H}${f}`]});I[`x-parsed-md-${m}`]={result:ee(D)}}},name:"openapi-markdoc-inline-parser"});for(const[d,s]of Object.entries(E))await e.createSharedData(d,{...s,baseSlug:e.getRouteByFsPath(s.fsPath)?.baseSlug},s.hash)}}}export{Te as openAPIDocsPlugin};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
`;const
|
|
3
|
-
`}if(f.length>
|
|
1
|
+
import*as l from"path";import{convertSwagger2OpenAPI as oo}from"@redocly/openapi-docs/lib/utils/convertSwagger2OpenAPI.js";import{Source as no,bundle as ro,createConfig as to,getTotals as io,resolvePlugins as eo}from"@redocly/openapi-core";import{normalizeOptions as ao,OpenAPIParser as so,buildContentItems as co}from"@redocly/openapi-docs";import{combineUrls as E}from"@redocly/theme/core/utils";import{CONFIG_FILE_NAME as A}from"../../../constants/common.js";import{PUBLIC_API_DEFINITIONS_FOLDER as P}from"../../constants/common.js";import{MAX_BUNDLING_ERRORS_TO_PRINT as fo}from"../../constants/plugins/openapi-docs.js";import{unique as lo}from"../../../utils/array/unique.js";import{deepMerge as F}from"../../../utils/object/deep-merge.js";import{pluralize as R}from"../../../utils/string/pluralize.js";import{replaceEnvVariablesDeep as po}from"../../utils/envs/replace-env-variables-deep.js";import{logger as N}from"../../tools/notifiers/logger.js";import{reporter as b}from"../../tools/notifiers/reporter.js";import{injectDecoratorIntoConfig as uo}from"./decorators.js";import{getAllApiConfigsByPath as mo}from"../get-api-config.js";import{normalizeFeedbackOptions as go}from"./utils.js";import{replaceFileExtension as L}from"./store-definition-bundles.js";import{ExternalResolver as wo}from"../../fs/utils/external-ref-resolver.js";import{formatBundleError as ho}from"./format-bundle-error.js";async function Mo(o,u){const{fs:t,cache:O,getConfig:g,isPathIgnored:m}=u;if(l.posix.basename(o)===A)return[];let a;try{a=(await O.load(o,"yaml")).data}catch{return[]}if(!a?.openapi&&!a?.swagger)return N.verbose(`${o} file is not definition. Skipping`),[];const p=await g("."),s=await t.getFileInfo(o),n=await g(l.posix.dirname(o)),M=mo(n?.apis,o,n.configPath),S=[],T=await m(o);for(const c of M){if(!c.output&&T)continue;const U=F({decorators:p.decorators},n,{rbac:void 0},c),{resolvedObj:e}=po(U);if(e.decorators&&typeof e.decorators!="object"){await b.panicOnBuildContentError(`'decorators' must be an object at redocly.yaml, got '${typeof e.decorators}'`);continue}if(e.plugins&&!Array.isArray(e.plugins)){await b.panicOnBuildContentError(`'plugins' must be an array at redocly.yaml, got '${typeof e.plugins}'`);continue}const V=n.configPath?l.posix.dirname(n.configPath):".",r=c.output?l.posix.join(V,c.output):o;if(await m(r))continue;s&&c.output&&!await t.exists(r)&&t.addVirtualFile(r,s);const z=l.resolve(t.cwd,n.realConfigPath||A),v=new wo(t),C=await to(uo(e,r),{configPath:z,externalRefResolver:v});p.plugins&&p.configPath!==n.configPath&&(C.plugins=lo([...C.plugins||[],...await eo(p.plugins,t.cwd)],f=>f.id));const D=l.resolve(t.cwd,o),G=await t.read(o),J={config:C,base:l.dirname(D),doc:{source:new no(D,G),parsed:JSON.parse(JSON.stringify(a))},externalRefResolver:v},{bundle:{parsed:y},problems:B,visitorsData:q}=await ro(J),H=q["markdown/markdown"]?.markdocChunks??[],i=io(B);let _=[i.errors&&`${i.errors} ${R(i.errors,"error","errors")}`,i.warnings&&`${i.warnings} ${R(i.warnings,"warning","warnings")}`,i.ignored&&`${i.ignored} ignored`].filter(Boolean).join(", ");if(i.errors){const f=B.filter(d=>d.severity==="error");let $=`${_} while bundling ${r} definition:
|
|
2
|
+
`;const x=Math.min(f.length,fo);for(let d=0;d<x;d++){const Y=f[d],Z=await ho(Y,t.cwd);$+=`${Z}
|
|
3
|
+
`}if(f.length>x){const d=f.length-x;$+=`... and ${d} more ${R(d,"error","errors")}`}await b.panicOnBuild($)}i.warnings&&N.warn(`${_} while bundling %rp definition`,r);const w=bo(y.swagger!==void 0?await oo(y):y,n.metadata),h=F(p.openapi||{},n.openapi||{},c.openapi||c?.theme?.openapi||{});h.showSchemaCatalogLinks&&(w["x-schema-catalog-link"]=E(P,r));const X=w["x-feedback"]||h.feedback||n.feedback,j={...h,feedback:go(X),hideSidebar:!0,disableRouter:!0,mockServer:e?.mockServer||p?.mockServer,downloadUrls:h.downloadUrls||[{url:E(P,`${L(r,".json")}?download`)},{url:E(P,`${L(r,".yaml")}?download`)}]},I=ao(j);let k;try{k=new so(w,void 0,I)}catch(f){await b.panicOnBuild(f);continue}const{contentItems:K,flatItems:Q}=co(k,I),W={definition:w,config:e,relativePath:r,realRelativePath:s?.realRelativePath||r,customOutputRelativeFile:c.output&&r,markdocChunks:H,contentItems:K,flatItems:Q,options:I,rawOptions:j,parser:k};S.push(W)}return S}async function To(o,u){const{fs:t,cache:O,getConfig:g}=u,m=[];for(const a of await t.scan(/(\.ya?ml|\.json)$/)){if(!await g(l.posix.dirname(a.relativePath)))continue;const s=await O.load(a.relativePath,"load-oas");s.data&&s.data.length&&m.push(...s.data.map(n=>({...n,isVirtual:a.isVirtual||n.isVirtual,hash:s.compoundHash})))}return m}function bo(o,u){return u?{...o,info:{...o.info,"x-metadata":{...o.info["x-metadata"],...u}}}:o}export{Mo as definitionLoader,To as definitionsLoader};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import g from"node:path";import{REDOCLY_TEAMS_RBAC as h}from"@redocly/config";import{slash as S}from"../../../utils/path/slash.js";import{staticDataLoader as w}from"./loaders/static-data-loader.js";import{findFrontmatterSlugs as y,getSidebarSharedDataId as P,resolveFrontmatterSlugs as b}from"../utils.js";import{reactFrontmatterLoader as
|
|
1
|
+
import g from"node:path";import{REDOCLY_TEAMS_RBAC as h}from"@redocly/config";import{slash as S}from"../../../utils/path/slash.js";import{staticDataLoader as w}from"./loaders/static-data-loader.js";import{findFrontmatterSlugs as y,getSidebarSharedDataId as P,resolveFrontmatterSlugs as b}from"../utils.js";import{reactFrontmatterLoader as F}from"./loaders/react-frontmatter-loader.js";import{registerPageProps as v}from"../register-page-props.js";import{telemetryTraceStep as D}from"../../../cli/telemetry/helpers/trace-step.js";import{searchResolver as R}from"./search/search-resolver.js";async function j(){return{loaders:{"react-frontmatter":F},id:"react-pages",requiredEntitlements:["reactPages"],processContent:async(r,a)=>{await D("build.plugin.pages",async()=>{const{fs:o,cache:f}=a;for(const n of await o.scan(/\.page\.tsx?$/)){const{relativePath:e,realRelativePath:l}=n;if(await a.isPathIgnored(e))continue;const p=r.createTemplate(S(e),g.resolve(o.cwd,l));await v(n,o,r);const{data:t}=await f.load(e,"react-frontmatter"),u=await y(e,"react-frontmatter",t,a),s=b(u,e);let i=null;t?.sidebar&&(i=await P(t.sidebar,e,a.fs)),(s.length?s.reverse():[void 0]).forEach(c=>{r.addRoute({excludeFromSearch:t?.excludeFromSearch||!1,slug:c,templateId:p,fsPath:e,sharedData:i?[{id:i,key:"sidebar"}]:void 0,[h]:t?.rbac,getNavText:async()=>t?.seo?.title,getStaticData:async(m,d)=>({props:await w({frontmatter:t,relativePath:e},a,d)}),getSearchDocuments:R(t,e,r.getSearchFacets,r.setSearchFacets)})});for(const[c,{to:m,type:d}]of Object.entries(t?.redirects||{}))r.addRedirect(c,{to:m||s[0],type:d||301})}})}}}export{j as customPagesPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{writeFileSync as E}from"node:fs";import R from"path";import{SCORECARD_OUTPUT_FILE_NAME as L}from"../../constants/common.js";import{mapObject as h}from"../../../utils/object/map-object.js";import{readEnvVariable as P}from"../../utils/envs/read-env-variable.js";import{removeLeadingSlash as
|
|
1
|
+
import{writeFileSync as E}from"node:fs";import R from"path";import{SCORECARD_OUTPUT_FILE_NAME as L}from"../../constants/common.js";import{mapObject as h}from"../../../utils/object/map-object.js";import{readEnvVariable as P}from"../../utils/envs/read-env-variable.js";import{removeLeadingSlash as _}from"../../../utils/url/remove-leading-slash.js";import{combineUrls as y}from"@redocly/theme/core/utils";import{logger as b}from"../../tools/notifiers/logger.js";import{getRouteSlugToCatalogSlugMap as A}from"../../utils/catalog-classic/get-route-slug-to-catalog-slug-map.js";import{ensureDir as j}from"../../utils/index.js";import{getTemplatePath as w}from"./get-template-path.js";import{getAllRuleNames as F}from"./lint.js";import{getScorecardConfig as D}from"./get-scorecard-config.js";import{CUSTOM_FIELDS_SERVER_PROPS_GETTER_ID as N}from"../catalog-classic/index.js";import{getScorecardSlug as U}from"./shared-utils.js";import{scorecardConfigLoader as M}from"./loaders/scorecard-config.js";import{scorecardLoader as k}from"./loaders/scorecard.js";import{computeScorecard as q}from"./compute-scorecard.js";import{telemetryTraceStep as W}from"../../../cli/telemetry/helpers/trace-step.js";const B="scorecardClassic";async function le({id:T,requiredEntitlements:I,loadersPrefix:S=""}){let m=null,C=null,v=!1;return{id:T??"scorecardClassic",requiredEntitlements:I??["scorecard"],loaders:{[`${S}scorecard-config`]:M,[`${S}scorecard`]:k},async processContent(t,l){await W("build.plugin.scorecard_classic",async f=>{const a=t.createTemplate(B,w("./template/index.js")),g=await l.getConfig(),c=D(g);f?.setAttribute("config",JSON.stringify(c||{}));const p=g?.reunite??{},i=g.catalogClassic??{},s=c.levels||[];if(s.length<1)throw Error("Invalid configuration of levels config");m===null&&(m=await q({actions:t,context:l,scorecardConfig:c,reuniteConfig:p}));const{data:{configs:n}}=await l.cache.load("",`${S}scorecard-config`),{perLevel:o,all:d}=F(n);C={levelNames:s.map(r=>r.name),rules:d,rulesPerLevel:o};for(const[r,e]of Object.entries(i)){const u=y(e.slug,"scorecard/");t.addRoute({duplicateInAllLocales:!0,slug:u,fsPath:y(e.slug,"scorecard/"),templateId:a,hasClientRoutes:!0,excludeFromSidebar:!0,serverPropsGetterIds:[N],sharedData:[{id:"scorecard",key:"scorecard"},{key:"catalog",id:"catalog-"+r}],getNavText:()=>Promise.resolve(e.title||"API design scorecard"),getStaticData:async()=>({props:{catalogId:r,catalogConfig:{...e,items:void 0},scorecardConfig:c,scorecardInfo:C}})})}})},afterRoutesCreated:async(t,l)=>{const f=await l.getConfig(),a=f.catalogClassic??{},g=D(f);if(Object.keys(a).length){const i=Object.keys(a).length>1?await A(t,l,a):null,s={};for(const[n,o]of Object.entries(m||{})){const d=t.getRouteByFsPath(n),r=d?.slug;if(r){if(d&&!g.ignoreMetadata){const e=i?i.get(r)??Object.values(a)[0].slug:Object.values(a)[0].slug,u=y(e,"scorecard/");d.metadata={...d.metadata,scorecardStatus:o.status,scorecardLevel:o.scorecardLevel,scorecardLevelIdx:o.scorecardLevelIdx,scorecardLevels:h(o.levels,O=>({uniqueErrors:O.uniqueErrors,uniqueWarnings:O.uniqueWarnings})),scoreCardSlug:u+"apis/"+encodeURIComponent(_(r))}}if(s[r]={...o,levels:h(o.levels,e=>({...e,problems:e.problems.map(u=>({ruleId:u.ruleId,severity:u.severity}))}))},!v){const e=R.resolve(t.outdir,"_scorecard",U(r));E(j(e),JSON.stringify(o))}}}await t.createSharedData("scorecard",s)}const c={};for(const[i,s]of Object.entries(m||{})){const n=t.getRouteByFsPath(i)?.slug;n&&(c[n]=s)}const p=P("REDOCLY_METADATA_OUTPUT_FOLDER");!v&&p&&(b.info("Writing scorecard data..."),E(R.join(p,L),JSON.stringify({scorecardData:c,...C}))),v=!0}}}export{le as scorecardClassicPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import p from"node:path";import{existsSync as b}from"node:fs";import{writeFile as
|
|
1
|
+
import p from"node:path";import{existsSync as b}from"node:fs";import{writeFile as x,access as v,rm as N,constants as X}from"fs/promises";import{REDOCLY_ROUTE_RBAC as S,REDOCLY_TEAMS_RBAC as D}from"@redocly/config";import $ from"picomatch";import{DEFAULT_LOCALE_PLACEHOLDER as _}from"../../../../constants/common.js";import{AI_INDEX_EXPORT_FOLDER as j}from"../../../constants/plugins/search.js";import{LLMS_TXT_FILE_NAME as k}from"../../../constants/common.js";import{isBuildMode as B}from"../../../utils/envs/is-build-mode.js";import{logger as a}from"../../../tools/notifiers/logger.js";import{shaHexShort as G}from"../../../utils/crypto/sha-hex-short.js";import{promiseMapLimit as M}from"../../../utils/async/promise-map-limit.js";import{ensureDir as A}from"../../../utils/fs.js";import{isResourcePubliclyAccessible as H,extractTeamsForSearch as U,getRbacTeamsForSearch as Y}from"../../../utils/rbac.js";import{validateLLMsTxtConfig as J,generateLLMsTxt as K,getLLMsTxtMdSlug as V}from"../llmstxt/index.js";const P=20,R="llms.txt:";async function pt(t,i,{aiSearchEnabled:e,llmstxtEnabled:r}){const s=p.join(t.outdir,k);if(!r){try{await v(s,X.W_OK),await N(s)}catch{}if(!e)return}e&&a.info("Preparing AI search documents..."),r&&a.info(`${R} Generating llms.txt files...`);const L=a.startTiming(),c=a.startTiming(),f=t.getGlobalConfig("seo"),l=f?.llmstxt,T=p.resolve(t.outdir,j),u=t.getConfig(),w=u.rbac??{},C=t.getAllRoutes(),F=u?.l10n?.defaultLocale||u?.i18n?.defaultLocale||_,O=(l?.excludeFiles||[]).map(o=>$(o)),d=[];if(await M(C,P,async o=>{if(o.excludeFromSearch)return;const y=await W(o,t),h=await q(o,y,i,t);if(h){if(r)for(const n of await h.getLLMsTxts()){if(O.some(m=>m(n.fsPath)))continue;const g=p.join(t.outdir,V(n.slug));A(g),await x(g,n.content),n.includeInLLMsTxt&&H(o,u)&&d.push(n)}if(e&&B()){const n=await h.getSearchDocuments();if(!n.length)return;const g=z(o,w),m=o.versions?.find(({active:I})=>I),E=m&&{folder:m.folderId,label:m.label,default:m.default};await Q(n,o.fsPath,g,T,F,E)}}}),e&&a.infoTime(c,"AI search documents prepared"),d.length)try{J(l);const o=await K(d,l,{title:f?.title,description:f?.description},i);A(s),await x(s,o),a.infoTime(L,`${R} files generated`)}catch(o){a.error(`${R} Failed to generate llms.txt file. ${o.message}`)}}async function W(t,i){return t.getStaticData?t.getStaticData(t,{...i,contentDir:i.contentDir,parseMarkdoc:(e,r,s)=>i.parseMarkdoc(e,r,s)}):{}}async function q(t,i,e,r){if(t.getAiDocumentsStore)return t.getAiDocumentsStore(t,{...i,[D]:t[D],[S]:t[S]},e,r)}function z(t,i){const e=U(t?.[D]);return e?.length?e:Y(t,i)}async function Q(t,i,e,r,s,L){await M(t,P,async c=>{const f=`${G(i+c.content)}.json`,l=A(p.join(r,f)),T=c.locale===_?s:c.locale;b(l)||await x(l,JSON.stringify({...c,rbacTeams:e||[],version:L,locale:T}),"utf-8")})}export{pt as prepareAiSearchDocuments};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{REDOCLY_ROUTE_RBAC as D,REDOCLY_TEAMS_RBAC as p}from"@redocly/config";import{existsSync as
|
|
1
|
+
import{REDOCLY_ROUTE_RBAC as D,REDOCLY_TEAMS_RBAC as p}from"@redocly/config";import{existsSync as E}from"fs";import{rm as _}from"node:fs/promises";import{DEFAULT_LOCALE_PLACEHOLDER as w}from"../../../../constants/common.js";import{SEARCH_DATA_EXPORT_FOLDER as T}from"../../../constants/plugins/search.js";import{isBuildMode as h}from"../../../utils/envs/is-build-mode.js";import{logger as c}from"../../../tools/notifiers/logger.js";import{telemetry as b}from"../../../telemetry/index.js";import{extractTeamsForSearch as O,getRbacTeamsForSearch as $}from"../../../utils/index.js";import{getSearchDocumentGroup as M}from"../utils.js";async function G(S,t,f){c.info("Preparing search documents and create indexes..."),h()&&E(`${t.outdir}/${T}`)&&await _(`${t.outdir}/${T}`,{recursive:!0});const F=c.startTiming(),R=t.getConfig().rbac,v=[w,...S.localeFolders.map(s=>s.toLowerCase())];for(const s of v){const i=t.getAllRoutesForLocale(s);for(const r of i){if(r.excludeFromSearch)continue;const d=new Map,{product:n}=r,A=await r.getStaticData?.(r,{...t,contentDir:t.contentDir,parseMarkdoc:(a,e,u)=>t.parseMarkdoc(a,e,u)})||{},m=await r.getSearchDocuments?.(r,{...A,[p]:r[p],[D]:r[D]},t),o=r.versions?.find(a=>a.active),C=$(r,R??{});if(m&&m.length)for(const a in m){let e=m[a];const u=O(e?.[p]),g=u?.length?u:C,L=e.tags||[];e={...e,...o&&{version:o.version,isDefaultVersion:o.default,versionFolderId:o.folderId},...n&&{product:n},rbacTeams:g,tags:[...L,...g,...o?o.default?["v:default"]:[`v:${o.folderId}:${o.version}`]:["v:default"],...n?[`p:${n.name}`]:[]],url:e.url&&(e.path&&e.path.length>1?e.url:e.url.split("#")[0])};const l=M(e.facets);if(l){const x=d.get(l)??[];d.set(l,[...x,e])}}for(const[a,e]of d)await f.addDocuments(e,{locale:s,group:a,outDir:t.outdir})}}if(f.cleanupFacetValues(t),c.infoTime(F,"Search indexes created"),h()){c.info("Writing out search data...");const s=c.startTiming();await f.export(t.outdir);const i=c.infoTime(s,"Search data written");i&&b.sendTimingPerformedMessage(i)}}export{G as prepareSearchDocuments};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SitemapStream as l,streamToPromise as
|
|
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};
|
package/dist/server/store.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ export declare class Store {
|
|
|
89
89
|
frontMatterKeysToResolve?: string[] | undefined;
|
|
90
90
|
partialsFolders?: string[] | undefined;
|
|
91
91
|
lastUpdatedBlock?: {
|
|
92
|
-
format?: "
|
|
92
|
+
format?: "short" | "long" | "timeago" | "iso" | undefined;
|
|
93
93
|
hide?: boolean | undefined;
|
|
94
94
|
locale?: string | undefined;
|
|
95
95
|
} | undefined;
|
|
@@ -80,6 +80,7 @@ type PageRouteDetailsForward<TData extends PageStaticData = PageStaticData, TPro
|
|
|
80
80
|
path?: string;
|
|
81
81
|
params?: string[];
|
|
82
82
|
queries?: Record<string, string>;
|
|
83
|
+
excludeFromSearch?: boolean;
|
|
83
84
|
getStaticData?: GetStaticDataFn<PageRouteDetailsForward<TData, TProps>, TData>;
|
|
84
85
|
metadata?: Record<string, unknown>;
|
|
85
86
|
getNavText?: () => Promise<string> | string;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CatalogConfig } from '@redocly/config';
|
|
2
|
+
import type { AfterRoutesCreatedActions, LifecycleContext } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Builds a mapping from route slugs to their corresponding catalog slugs.
|
|
5
|
+
*
|
|
6
|
+
* Iterates through all provided catalog configs, resolves their navigation items,
|
|
7
|
+
* and collects route slugs from the resolved items to create a map that
|
|
8
|
+
* associates each route slug with its parent catalog slug.
|
|
9
|
+
*
|
|
10
|
+
* @param actions - Actions available after routes have been created, providing
|
|
11
|
+
* access to content directory and route resolution utilities
|
|
12
|
+
* @param context - Lifecycle context containing filesystem, cache, and logger
|
|
13
|
+
* utilities needed for resolving navigation items
|
|
14
|
+
* @param catalogConfigs - Record of catalog configuration objects
|
|
15
|
+
* @returns Promise that resolves to a Map where keys are route slugs and values
|
|
16
|
+
* are the corresponding catalog slugs
|
|
17
|
+
*/
|
|
18
|
+
export declare function getRouteSlugToCatalogSlugMap(actions: AfterRoutesCreatedActions, context: LifecycleContext, catalogConfigs: Record<string, CatalogConfig>): Promise<Map<string, string>>;
|
|
19
|
+
//# sourceMappingURL=get-route-slug-to-catalog-slug-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolveItems as g}from"../../plugins/nav-utils.js";import{collectPropValueDeep as n}from"../../../utils/tree/collect-prop-value-deep.js";async function i(o,r,u){const t=new Map;for(const e of Object.values(u)){const l=await g(e.items,o.contentDir,o,r,{navFile:""});if(l){const s=n(l,"routeSlug");for(const a of s)t.set(a,e.slug)}}return t}export{i as getRouteSlugToCatalogSlugMap};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{describe as d,it as u,expect as t,vi as e,beforeEach as m}from"vitest";import{getRouteSlugToCatalogSlugMap as r}from"./get-route-slug-to-catalog-slug-map.js";import{resolveItems as s}from"../../plugins/nav-utils.js";import{collectPropValueDeep as n}from"../../../utils/tree/collect-prop-value-deep.js";e.mock("~/server/plugins/nav-utils.js"),e.mock("~/shared/utils/tree/collect-prop-value-deep.js"),d("getRouteSlugToCatalogSlugMap",()=>{let g,c;m(()=>{e.clearAllMocks(),g={contentDir:"/content",outdir:"/out",serverOutDir:"/server-out",hasSitemap:!1,createSharedData:e.fn(),addRouteSharedData:e.fn(),getRouteByFsPath:e.fn(),getRouteBySlug:e.fn(),getConfig:e.fn(),getGlobalConfig:e.fn(),getAllRoutes:e.fn(),getAllRoutesForLocale:e.fn(),getAllApiRoutes:e.fn(),setGlobalData:e.fn(),getGlobalData:e.fn(),setGlobalConfig:e.fn(),parseMarkdoc:e.fn(),setSearchFacets:e.fn(),getSearchFacets:e.fn(),setSearchEngine:e.fn(),addRedirect:e.fn(),addBrowserPlugin:e.fn(),addSsrComponents:e.fn(),addApiRoute:e.fn(),loadOpenApiDefinitions:e.fn(),getRouteSharedDataByFsPath:e.fn()},c={fs:{},cache:{},getConfig:e.fn(),isPathIgnored:e.fn(),withPathPrefix:e.fn(),logger:{}}}),u("should return empty map when catalogs object is empty",async()=>{const a=await r(g,c,{});t(a).toBeInstanceOf(Map),t(a.size).toBe(0),t(s).not.toHaveBeenCalled()}),u("should return empty map when catalog has no resolved items",async()=>{const o={catalog1:{slug:"catalog1",items:[]}};e.mocked(s).mockResolvedValue(void 0);const a=await r(g,c,o);t(a).toBeInstanceOf(Map),t(a.size).toBe(0),t(s).toHaveBeenCalledTimes(1),t(n).not.toHaveBeenCalled()}),u("should map route slugs to catalog slug for single catalog with items",async()=>{const o={catalog1:{slug:"catalog1",items:[]}},a=[{routeSlug:"/page1",label:"Page 1"},{routeSlug:"/page2",label:"Page 2"}];e.mocked(s).mockResolvedValue(a),e.mocked(n).mockReturnValue(["/page1","/page2"]);const l=await r(g,c,o);t(l.size).toBe(2),t(l.get("/page1")).toBe("catalog1"),t(l.get("/page2")).toBe("catalog1"),t(s).toHaveBeenCalledWith(o.catalog1.items,g.contentDir,g,c,{navFile:""}),t(n).toHaveBeenCalledWith(a,"routeSlug")}),u("should map route slugs to catalog slug for multiple catalogs",async()=>{const o={catalog1:{slug:"catalog1",items:[]},catalog2:{slug:"catalog2",items:[]}},a=[{routeSlug:"/page1",label:"Page 1"}],l=[{routeSlug:"/page2",label:"Page 2"},{routeSlug:"/page3",label:"Page 3"}];e.mocked(s).mockResolvedValueOnce(a).mockResolvedValueOnce(l),e.mocked(n).mockReturnValueOnce(["/page1"]).mockReturnValueOnce(["/page2","/page3"]);const i=await r(g,c,o);t(i.size).toBe(3),t(i.get("/page1")).toBe("catalog1"),t(i.get("/page2")).toBe("catalog2"),t(i.get("/page3")).toBe("catalog2"),t(s).toHaveBeenCalledTimes(2),t(n).toHaveBeenCalledTimes(2)}),u("should handle catalog with empty resolved items array",async()=>{const o={catalog1:{slug:"catalog1",items:[]}};e.mocked(s).mockResolvedValue([]),e.mocked(n).mockReturnValue([]);const a=await r(g,c,o);t(a.size).toBe(0),t(s).toHaveBeenCalledTimes(1),t(n).toHaveBeenCalledWith([],"routeSlug")}),u("should handle nested items with route slugs",async()=>{const o={catalog1:{slug:"catalog1",items:[]}},a=[{routeSlug:"/parent",label:"Parent",items:[{routeSlug:"/parent/child1",label:"Child 1"},{routeSlug:"/parent/child2",label:"Child 2"}]}];e.mocked(s).mockResolvedValue(a),e.mocked(n).mockReturnValue(["/parent","/parent/child1","/parent/child2"]);const l=await r(g,c,o);t(l.size).toBe(3),t(l.get("/parent")).toBe("catalog1"),t(l.get("/parent/child1")).toBe("catalog1"),t(l.get("/parent/child2")).toBe("catalog1")}),u("should handle items without routeSlug property",async()=>{const o={catalog1:{slug:"catalog1",items:[]}},a=[{label:"Page without route slug"},{routeSlug:"/page-with-slug",label:"Page with slug"}];e.mocked(s).mockResolvedValue(a),e.mocked(n).mockReturnValue(["/page-with-slug"]);const l=await r(g,c,o);t(l.size).toBe(1),t(l.get("/page-with-slug")).toBe("catalog1")}),u("should overwrite route slug mapping when same route slug appears in multiple catalogs",async()=>{const o={catalog1:{slug:"catalog1",items:[]},catalog2:{slug:"catalog2",items:[]}},a=[{routeSlug:"/shared-page",label:"Shared Page"}],l=[{routeSlug:"/shared-page",label:"Shared Page"}];e.mocked(s).mockResolvedValueOnce(a).mockResolvedValueOnce(l),e.mocked(n).mockReturnValueOnce(["/shared-page"]).mockReturnValueOnce(["/shared-page"]);const i=await r(g,c,o);t(i.size).toBe(1),t(i.get("/shared-page")).toBe("catalog2")})});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
async function
|
|
1
|
+
async function r(e){return e.html(`
|
|
2
2
|
<!DOCTYPE html>
|
|
3
3
|
<html lang="en">
|
|
4
4
|
<head>
|
|
@@ -19,67 +19,112 @@ async function t(e){return e.html(`
|
|
|
19
19
|
|
|
20
20
|
<body>
|
|
21
21
|
<script>
|
|
22
|
-
const
|
|
23
|
-
function
|
|
24
|
-
return
|
|
22
|
+
const d = "Something went wrong, please, try again.";
|
|
23
|
+
function h(r) {
|
|
24
|
+
return r && r.replace(/=+$/, "");
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
return !!
|
|
26
|
+
function w(r, e) {
|
|
27
|
+
return !!r && !!e && h(r) === h(e);
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
const m = {
|
|
30
|
+
invalid_request: "The request is missing a required parameter, includes an unsupported parameter value (other than grant type), repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.",
|
|
31
|
+
invalid_client: "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).",
|
|
32
|
+
invalid_grant: "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.",
|
|
33
|
+
unauthorized_client: "The authenticated client is not authorized to use this authorization grant type.",
|
|
34
|
+
unsupported_grant_type: "The authorization grant type is not supported by the authorization server.",
|
|
35
|
+
invalid_scope: "The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner.",
|
|
36
|
+
// Authorization endpoint errors (from RFC 6749 Section 4.1.2.1)
|
|
37
|
+
unsupported_response_type: "The requested response type is not supported by the authorization server.",
|
|
38
|
+
access_denied: "The resource owner or authorization server denied the request.",
|
|
39
|
+
// Token endpoint errors (from RFC 6749 Section 5.2)
|
|
40
|
+
server_error: "The authorization server encountered an unexpected condition.",
|
|
41
|
+
temporarily_unavailable: "The authorization server is currently unable to handle the request due to a temporary overloading or maintenance."
|
|
42
|
+
};
|
|
43
|
+
class i extends Error {
|
|
44
|
+
error;
|
|
45
|
+
error_description;
|
|
46
|
+
constructor({
|
|
47
|
+
message: e,
|
|
48
|
+
error: t,
|
|
49
|
+
error_description: n
|
|
50
|
+
}) {
|
|
51
|
+
const o = n || t && m[t] || t || e || d;
|
|
52
|
+
super(o), this.name = "OAuth2Error", this.error = t, this.error_description = n;
|
|
53
|
+
}
|
|
54
|
+
static fromJsonData(e) {
|
|
55
|
+
return new i({
|
|
56
|
+
error: e.error,
|
|
57
|
+
error_description: e.error_description
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
static fromTextData(e) {
|
|
61
|
+
return new i({
|
|
62
|
+
message: e
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
static fromError(e) {
|
|
66
|
+
return new i({
|
|
67
|
+
error: e.message
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function y(r, e) {
|
|
72
|
+
let t;
|
|
73
|
+
const n = e ? new URL(e) : window.location;
|
|
74
|
+
if (/code|token|error/.test(n.hash) ? t = n.hash.substring(1) : t = n.search.substring(1), !t)
|
|
75
|
+
throw console.error("No query string in OAuth 2 redirect URL"), new i({ message: d });
|
|
76
|
+
const o = new URLSearchParams(t), s = o.get("access_token"), a = o.get("code"), c = o.get("token_type"), l = o.get("expires_in"), p = o.get("state"), u = o.get("error"), g = o.get("error_description");
|
|
77
|
+
if (u)
|
|
78
|
+
throw new i({
|
|
79
|
+
error: u,
|
|
80
|
+
error_description: g ?? void 0
|
|
81
|
+
});
|
|
82
|
+
if (!w(p, r?.state))
|
|
37
83
|
throw new Error("Outdated OAuth2 state");
|
|
38
|
-
if (
|
|
39
|
-
if (!
|
|
84
|
+
if (r?.flow === "implicit") {
|
|
85
|
+
if (!s)
|
|
40
86
|
throw new Error(
|
|
41
87
|
\`Your OAuth2 authentication service provider redirected you without an "access_token".
|
|
42
88
|
Please, try again or make sure your OAuth2 settings are correct.\`
|
|
43
89
|
);
|
|
44
|
-
if (!
|
|
90
|
+
if (!c)
|
|
45
91
|
throw new Error(
|
|
46
92
|
\`Your OAuth2 authentication service provider redirected you without a "token_type".
|
|
47
93
|
Please, try again or make sure your OAuth2 settings are correct.\`
|
|
48
94
|
);
|
|
49
|
-
|
|
50
|
-
access_token:
|
|
51
|
-
token_type:
|
|
52
|
-
expires_in:
|
|
95
|
+
r?.successCallback({
|
|
96
|
+
access_token: s,
|
|
97
|
+
token_type: c,
|
|
98
|
+
expires_in: l,
|
|
53
99
|
auth_code: ""
|
|
54
100
|
});
|
|
55
101
|
}
|
|
56
|
-
if (
|
|
57
|
-
if (!
|
|
102
|
+
if (r?.flow === "authorizationCode") {
|
|
103
|
+
if (!a)
|
|
58
104
|
throw new Error(
|
|
59
105
|
\`Your OAuth2 authentication service provider redirected you without authorization "code".
|
|
60
106
|
Please, try again or make sure your OAuth2 settings are correct.\`
|
|
61
107
|
);
|
|
62
|
-
|
|
63
|
-
auth_code:
|
|
108
|
+
r?.successCallback({
|
|
109
|
+
auth_code: a,
|
|
64
110
|
access_token: "",
|
|
65
111
|
token_type: "bearer"
|
|
66
112
|
});
|
|
67
113
|
}
|
|
68
114
|
}
|
|
69
|
-
function
|
|
70
|
-
|
|
71
|
-
const o = (e = window.opener) == null ? void 0 : e.redirectOAuth2;
|
|
115
|
+
function n() {
|
|
116
|
+
const r = window.opener?.redirectOAuth2;
|
|
72
117
|
try {
|
|
73
|
-
y(
|
|
74
|
-
} catch (
|
|
75
|
-
|
|
118
|
+
y(r);
|
|
119
|
+
} catch (o) {
|
|
120
|
+
r?.errorCallback(o);
|
|
76
121
|
}
|
|
77
122
|
window.close();
|
|
78
123
|
}
|
|
79
|
-
window.onload =
|
|
124
|
+
window.onload = n;
|
|
80
125
|
</script>
|
|
81
126
|
|
|
82
127
|
<noscript> You need to enable JavaScript to run this app. </noscript>
|
|
83
128
|
</body>
|
|
84
129
|
</html>
|
|
85
|
-
`)}export{
|
|
130
|
+
`)}export{r as replayOauth2RedirectCallbackHandler};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/revel",
|
|
3
|
-
"version": "0.128.0-next.
|
|
3
|
+
"version": "0.128.0-next.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"@opentelemetry/sdk-trace-node": "2.0.1",
|
|
32
32
|
"@opentelemetry/sdk-trace-web": "2.0.1",
|
|
33
33
|
"@opentelemetry/semantic-conventions": "1.34.0",
|
|
34
|
-
"@redocly/ajv": "8.
|
|
35
|
-
"@redocly/openapi-core": "2.
|
|
34
|
+
"@redocly/ajv": "8.17.1",
|
|
35
|
+
"@redocly/openapi-core": "2.12.1",
|
|
36
36
|
"@shikijs/transformers": "^1.22.2",
|
|
37
37
|
"@tanstack/react-query": "5.62.3",
|
|
38
38
|
"@tanstack/react-table": "8.21.3",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@redocly/mcp-typescript-sdk": "1.18.1",
|
|
41
41
|
"@wojtekmaj/react-datetimerange-picker": "6.0.0",
|
|
42
42
|
"@xmldom/xmldom": "0.8.10",
|
|
43
|
-
"ajv-formats": "^
|
|
43
|
+
"ajv-formats": "^3.0.1",
|
|
44
44
|
"anser": "^2.3.2",
|
|
45
45
|
"babel-plugin-styled-components": "2.1.4",
|
|
46
46
|
"chokidar": "3.6.0",
|
|
@@ -92,12 +92,12 @@
|
|
|
92
92
|
"xml-crypto": "6.0.1",
|
|
93
93
|
"xpath": "0.0.34",
|
|
94
94
|
"yaml-ast-parser": "0.0.43",
|
|
95
|
-
"@redocly/asyncapi-docs": "1.5.0-next.
|
|
95
|
+
"@redocly/asyncapi-docs": "1.5.0-next.8",
|
|
96
96
|
"@redocly/config": "0.40.0",
|
|
97
97
|
"@redocly/graphql-docs": "1.5.0-next.1",
|
|
98
|
-
"@redocly/openapi-docs": "3.16.0-next.
|
|
98
|
+
"@redocly/openapi-docs": "3.16.0-next.8",
|
|
99
99
|
"@redocly/portal-legacy-ui": "0.11.0-next.0",
|
|
100
|
-
"@redocly/portal-plugin-mock-server": "0.13.0-next.
|
|
100
|
+
"@redocly/portal-plugin-mock-server": "0.13.0-next.8",
|
|
101
101
|
"@redocly/realm-asyncapi-sdk": "0.6.0-next.1",
|
|
102
102
|
"@redocly/theme": "0.60.0-next.5"
|
|
103
103
|
},
|