@redocly/reef 0.133.0 → 0.134.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/dist/client/app/hooks/useBanner.js +1 -1
- package/dist/client/app/hooks/useRouteChangeTracker.js +1 -1
- package/dist/client/app/hooks/utils/match-banner-target.d.ts +7 -1
- package/dist/client/app/hooks/utils/match-banner-target.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/json-schema.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/server/api-routes/execute-api-route.js +1 -1
- package/dist/server/plugins/analytics/ga/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/ga/index.js +1 -1
- package/dist/server/plugins/api-functions/index.js +1 -1
- package/dist/server/plugins/asyncapi-docs/get-server-props.js +1 -1
- package/dist/server/plugins/catalog-entities/database/catalog-entities-publisher.d.ts +2 -2
- package/dist/server/plugins/catalog-entities/database/catalog-entities-publisher.js +6 -6
- package/dist/server/plugins/catalog-entities/database/remote-publish-lock-service.d.ts +22 -0
- package/dist/server/plugins/catalog-entities/database/remote-publish-lock-service.js +1 -0
- package/dist/server/plugins/catalog-entities/database/types.d.ts +1 -0
- package/dist/server/plugins/catalog-entities/plugin.js +1 -1
- package/dist/server/plugins/markdown/index.d.ts +1 -1
- package/dist/server/plugins/markdown/index.js +1 -1
- package/dist/server/plugins/markdown/markdown-frontmatter-loader.js +1 -1
- package/dist/server/plugins/markdown/utils/resolve-markdown-template.d.ts +13 -0
- package/dist/server/plugins/markdown/utils/resolve-markdown-template.js +1 -0
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/types.d.ts +1 -0
- package/dist/server/plugins/openapi-docs/get-server-props.js +1 -1
- package/dist/server/plugins/sidebars/index.js +2 -2
- package/dist/server/store.d.ts +3 -0
- package/dist/server/store.js +1 -1
- package/dist/server/utils/globs.d.ts +2 -1
- package/dist/server/utils/globs.js +1 -1
- package/dist/server/utils/rbac.js +1 -1
- package/package.json +10 -10
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DatabaseConnection } from './types';
|
|
2
|
+
export declare const INTERNAL_CATALOG_PUBLISH_CACHE_NAMESPACE = "catalog-publisher-locks";
|
|
3
|
+
export declare const INTERNAL_CATALOG_PUBLISH_KEY_PREFIX = "catalog-entities::publisher";
|
|
4
|
+
export declare class RemotePublishLockService {
|
|
5
|
+
#private;
|
|
6
|
+
static getInternalCacheValue({ remoteConnection, key, }: {
|
|
7
|
+
remoteConnection: DatabaseConnection;
|
|
8
|
+
key: string;
|
|
9
|
+
}): Promise<string | null>;
|
|
10
|
+
static upsertInternalCacheValue({ remoteConnection, key, value, ttl, }: {
|
|
11
|
+
remoteConnection: DatabaseConnection;
|
|
12
|
+
key: string;
|
|
13
|
+
value: string;
|
|
14
|
+
ttl?: number | null;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
static runUnderRemotePublishLock<T>({ runId, remoteConnection, run, }: {
|
|
17
|
+
runId: string;
|
|
18
|
+
remoteConnection: DatabaseConnection;
|
|
19
|
+
run: () => Promise<T>;
|
|
20
|
+
}): Promise<T>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=remote-publish-lock-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{and as w,eq as i,isNotNull as h,lt as A,sql as E}from"drizzle-orm";import{logger as d}from"../../../tools/notifiers/logger.js";import{cacheTable as a}from"../../../providers/database/databases/sqlite-db/schemas/cache-table.js";const c="catalog-publisher-locks",T="catalog-entities::publisher",f=`${T}::remote-publish-lock`,m=1800*1e3,p=Math.floor(m/1e3),y=60*1e3,I=300*1e3,O=1e3;class n{static async getInternalCacheValue({remoteConnection:t,key:e}){return(await t.client.client.select({value:a.value}).from(a).where(w(i(a.key,e),i(a.namespace,c))).get())?.value??null}static async upsertInternalCacheValue({remoteConnection:t,key:e,value:r,ttl:s=null}){const o=new Date().toISOString();await t.client.client.insert(a).values({key:e,namespace:c,value:r,ttl:s,createdAt:o,updatedAt:o}).onConflictDoUpdate({target:[a.key],set:{namespace:c,value:r,ttl:s,updatedAt:o}}).run()}static async runUnderRemotePublishLock({runId:t,remoteConnection:e,run:r}){const s=JSON.stringify({ownerRunId:t});await n.#a({runId:t,lockValue:s,remoteConnection:e});const o=n.#r({runId:t,lockValue:s,remoteConnection:e}),u=await n.#n(r);clearInterval(o);const l=await n.#s({lockValue:s,remoteConnection:e});if(!u.ok)throw l&&d.warn(`Failed to release remote publish lock after publish error for runId=${t}: ${n.#t(l)}`),n.#e(u.error,`Remote publish failed for runId=${t}: ${n.#t(u.error)}`);if(l)throw n.#e(l,`Failed to release remote publish lock for runId=${t}: ${n.#t(l)}`);return u.result}static async#a({runId:t,lockValue:e,remoteConnection:r}){if(!await n.#i({lockValue:e,remoteConnection:r,timeoutMs:I}))throw new Error(`Timed out waiting for remote publish lock. runId=${t}`)}static#r({runId:t,lockValue:e,remoteConnection:r}){return setInterval(()=>{n.#l({remoteConnection:r,lockValue:e}).catch(s=>{d.warn(`Failed to refresh remote publish lock for runId=${t}: ${n.#t(s)}`)})},y)}static async#n(t){try{return{ok:!0,result:await t()}}catch(e){return{ok:!1,error:e}}}static async#s({lockValue:t,remoteConnection:e}){try{return await n.#c({remoteConnection:e,lockValue:t}),null}catch(r){return r}}static async#i({lockValue:t,remoteConnection:e,timeoutMs:r}){const s=Date.now();for(;Date.now()-s<r;){if(await n.#o({remoteConnection:e,lockValue:t}))return!0;await n.#w(O)}return d.warn("Lock wait timeout. Wait for the other build to finish publishing entities."),!1}static async#o({remoteConnection:t,lockValue:e}){const r=t.client.client,s=new Date().toISOString();await r.delete(a).where(w(i(a.key,f),i(a.namespace,c),h(a.ttl),A(E`datetime(${a.createdAt}, '+' || ${a.ttl} || ' seconds')`,E`datetime('now')`))).run();try{return await r.insert(a).values({key:f,namespace:c,value:e,ttl:p,createdAt:s,updatedAt:s}).run(),!0}catch(o){if(n.#u(o))return!1;throw o}}static async#c({remoteConnection:t,lockValue:e}){await t.client.client.delete(a).where(w(i(a.key,f),i(a.namespace,c),i(a.value,e))).run()}static async#l({remoteConnection:t,lockValue:e}){const r=new Date().toISOString();await t.client.client.update(a).set({ttl:p,createdAt:r,updatedAt:r}).where(w(i(a.key,f),i(a.namespace,c),i(a.value,e))).run()}static#u(t){return t instanceof Error?t.message.toLowerCase().includes("unique constraint failed"):!1}static#w(t){return new Promise(e=>setTimeout(e,t))}static#e(t,e){return t instanceof Error?t:new Error(e)}static#t(t){return t instanceof Error?t.message:typeof t=="string"?t:JSON.stringify(t)}}export{c as INTERNAL_CATALOG_PUBLISH_CACHE_NAMESPACE,T as INTERNAL_CATALOG_PUBLISH_KEY_PREFIX,n as RemotePublishLockService};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FileHashStatus as A,FileType as f}from"../../persistence/file-hashes/types.js";import{envConfig as
|
|
1
|
+
import{FileHashStatus as A,FileType as f}from"../../persistence/file-hashes/types.js";import{envConfig as H}from"../../config/env-config.js";import{CATALOG_BASE_SLUG as C}from"../../../constants/catalog-entities.js";import{telemetryTraceStep as N}from"../../../cli/telemetry/helpers/trace-step.js";import{catalogDataCollector as m}from"./utils/catalog-data-collector.js";import{CATALOG_FILTERS_CACHE_NAMESPACE as L,ENTITIES_MAP_GLOBAL_DATA_KEY as x}from"../../constants/plugins/catalog-entities.js";import{CacheService as G}from"../../persistence/cache/services/cache-service.js";import{getTemplatePath as y}from"./utils/get-template-path.js";import{getCompleteCatalogConfig as D}from"./get-complete-catalog-config.js";import{AsyncApiEntitiesExtractor as B}from"./extensions/extractors/api-description/asyncapi-entities-extractor.js";import{GraphqlEntitiesExtractor as M}from"./extensions/extractors/api-description/graphql-entities-extractor.js";import{FileHashesService as k}from"../../persistence/file-hashes/services/file-hashes-service.js";import{CatalogEntitiesService as z}from"./database/catalog-entities-service.js";import{CatalogEntitiesPublisher as Y}from"./database/catalog-entities-publisher.js";import{ArazzoEntitiesExtractor as j}from"./extensions/extractors/api-description/arazzo-entities-extractor.js";import{FsEntitiesExtractor as q}from"./extensions/extractors/fs-entities-extractor.js";import{HashManager as U}from"./utils/hash-manager.js";import{RbacConfigHashCache as W}from"./utils/rbac-config-hash-cache.js";import{OpenApiEntitiesExtractor as J}from"./extensions/extractors/api-description/openapi-entities-extractor.js";const Z="catalog-entity-template",$="catalog-entity";let S=!0;async function K(){return{id:"CatalogEntities",requiredEntitlements:["catalog"],async processContent(t,e){const i=await e.getConfig(),r=D(i.entitiesCatalog);if(!r.show)return;const{logger:o}=e,a=t.registerServerPropsGetter($,y("../get-server-props.js")),g=t.createTemplate(Z,y("../template/index.js"));t.addRoute({duplicateInAllLocales:!0,slug:C,fsPath:"",templateId:g,excludeFromSidebar:!0,hasClientRoutes:!0,serverPropsGetterIds:[a],getNavText:()=>Promise.resolve("Catalog"),getStaticData:async()=>({props:{catalogConfig:r}})});const[l]=Object.entries(r.catalogs??{}).find(([T,p])=>!p?.hide)||[];l&&t.addRedirect(C,{type:302,to:`${C}/${l}`},{trackOriginalSource:!1}),o.info("Catalog Entities plugin finished")},async afterRoutesCreated(t,e){await N("build.plugin.catalog_entities",async i=>{const r=await e.getConfig(),o=D(r.entitiesCatalog);if(i?.setAttribute("config",JSON.stringify(o)),!o.show)return;const{logger:a}=e;m.resetForRun();const g=S&&H.isDevelopMode,l=await G.getInstance({baseDbDir:t.serverOutDir,databaseType:"local"}),T=new W(l),{rbacConfigChanged:p}=await T.syncAndDetectChange(r.access?.rbac??null),n=g||p,s=await z.getInstance({baseDbDir:t.serverOutDir,removeExisting:g,databaseType:"local",runWithPragmaWalWriteOptimization:!0}),h=await k.getInstance({baseDbDir:t.serverOutDir,databaseType:"local"}),c=new U(h),P=[new q({fileHashManager:c,context:e,catalogEntitiesService:s,catalogConfig:o,shouldCalculateEntities:n}),new J({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:f.OPENAPI_DESCRIPTION,shouldCalculateEntities:n}),new B({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:f.ASYNCAPI_DESCRIPTION,shouldCalculateEntities:n}),new M({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:f.GRAPHQL_DESCRIPTION,shouldCalculateEntities:n}),new j({actions:t,context:e,catalogEntitiesService:s,fileHashManager:c,fileType:f.ARAZZO_DESCRIPTION,shouldCalculateEntities:n})];a.info("Starting entities extractors...");const O=a.startTiming();await s.transaction(async()=>{await Promise.all(P.map(async d=>d.extract()))});const w=s.getEntitySources();t.setGlobalData({[x]:w}),await l.deleteByNamespace(L),a.infoTime(O,"Entities extractors finished");const{changedSourceFiles:_,removedSourceFiles:E}=m.getPublishDelta(),v=a.startTiming(),b=await Y.publishFromLocalToRemote(p?{baseDbDir:t.serverOutDir}:{baseDbDir:t.serverOutDir,changedSourceFiles:_,removedSourceFiles:E});if(b.published&&a.infoTime(v,"Entities published to the database"),b.shouldFinalizeFileHashes){E.length&&await h.deleteFileHashes({op:"AND",conditions:[{field:"status",operator:"equal",value:A.OUTDATED},{field:"file_path",operator:"in",value:E}]});const d=m.getFileHashConfirmations();for(const{fileType:I,filePath:F,hash:R}of d)await h.upsertFileHash({fileType:I,filePath:F,hash:R,status:A.UP_TO_DATE})}else a.warn("Skipped file_hashes finalization because remote catalog publish connection is unavailable; next build will retry.");const u=await m.getCatalogEntitiesData(s);i?.setAttribute("totalEntities",u.totalEntitiesCount),i?.setAttribute("entitiesCountByType",JSON.stringify(u.countOfEntitiesByType)),i?.setAttribute("totalFilesSkippedByHash",u.totalFilesSkippedByHash),i?.setAttribute("totalProcessedFiles",u.totalProcessedFiles),i?.setAttribute("extractors",u.extractors),S=!1})}}}var Et=K;export{K as catalogEntitiesPlugin,Et as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { LifecyclePluginInstance, PluginOptions } from '../../types';
|
|
2
|
-
export declare function markdownPlugin(
|
|
2
|
+
export declare function markdownPlugin(options: PluginOptions): Promise<LifecyclePluginInstance>;
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import{REDOCLY_TEAMS_RBAC as y}from"@redocly/config";import{MARKDOC_PARTIALS_DATA_KEY as D}from"../../store.js";import{reporter as R}from"../../tools/notifiers/reporter.js";import{canAccessFeature as g}from"../../utils/entitlements/can-access-feature.js";import{extractMdFirstHeading as A,getAst as T}from"./compiler.js";import{getTemplatePath as w}from"./get-template-path.js";import{prepareMarkdocPartials as M}from"./markdoc/partials.js";import{searchResolver as C}from"./search/search-resolver.js";import{markdownStaticDataLoader as E}from"./markdown-static-data-loader.js";import{makeErrorRoute as I}from"../error-route.js";import{validateRbacConfig as O}from"../validate-rbac-config.js";import{findFrontmatterSlugs as _,getSidebarSharedDataId as G,resolveFrontmatterSlugs as L}from"../utils.js";import{isPartial as j}from"./is-partial.js";import{markdownFrontmatterLoader as B}from"./markdown-frontmatter-loader.js";import{resolveRawPartials as K}from"./markdoc/resolve-raw-partials.js";import{getAiDocumentsStore as N}from"./search/get-ai-search-documents.js";import{registerPageProps as Y}from"../register-page-props.js";import{resolveMarkdownTemplate as q}from"./utils/resolve-markdown-template.js";import{sanitizeMalformedMdContent as z}from"./utils/sanitize-malformed-md-content.js";import{telemetryTraceStep as H}from"../../../cli/telemetry/helpers/trace-step.js";async function le(h){return{id:"markdoc",requiredEntitlements:["markdown"],loaders:{"markdown-frontmatter":B,"markdown-ast":async(e,t)=>{const i=await t.fs.read(e),m=await t.getConfig(),s=await K(i,e,m?.markdown?.partialsFolders,t),n=z(s);return T(e,n)}},processContent:async(e,t)=>{await H("build.plugin.markdown",async i=>{const{markdown:m}=await t.getConfig();i?.setAttribute("config",JSON.stringify(m||{}));const s=m?.partialsFolders??[],n=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 t.fs.scan(/\.md$/))if(!await t.isPathIgnored(o.relativePath)&&!j(o.relativePath,s))try{await k(o)}catch(a){e.addRoute(I(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:b}=o,{data:{frontmatter:r}}=await t.cache.load(a,"markdown-frontmatter"),P=r?.metadata||{},F=await _(a,"markdown-frontmatter",r,t),p=L(F,a);let d=null;r?.sidebar&&(d=await G(r.sidebar,a,t.fs));let u=n;const f=q({realRelativePath:b,frontmatter:r,markdown:m,contentDir:h.contentDir});f&&(u=e.createTemplate(f.templateRef,f.templatePath)),r?.rbac&&(g("rbac")?O({content:{[a]:r.rbac}}):r.rbac=void 0),g("banner")||(r.banner=void 0),await Y(o,t.fs,e),(p.length?p.reverse():[void 0]).forEach(v=>{e.addRoute({excludeFromSearch:r?.excludeFromSearch||!1,slug:v,fsPath:a,templateId:u,sharedData:d?[{id:d,key:"sidebar"}]:void 0,redirectFrom:Object.entries(r.redirects||{}).map(([l,{type:c}])=>({type:c||301,from:l})),[y]:r?.rbac,getNavText:async()=>(r?.seo?.title||await A(a,t)||"").toString(),metadata:{type:"markdown",...P},async getStaticData(l,c){return E(o,l,t,r,c)},getSearchDocuments:C(r,a,e.getSearchFacets,e.setSearchFacets),getAiDocumentsStore:N(e.getSearchFacets,r),serverPropsGetterIds:[S]})})}})},afterRoutesCreated:async(e,t)=>{const i=await M(t,e);e.setGlobalConfig({[D]:i})}}}export{le as markdownPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"gray-matter";import{ensureFrontmatterThemeCompatibility as m}from"../ensure-frontmatter-theme-compatibility.js";const s=async(t,r)=>{const a=await r.fs.read(t),{data:o}=e.default(a);return{frontmatter:await m(o,t,r.fs)}};export{s as markdownFrontmatterLoader};
|
|
1
|
+
import*as e from"gray-matter";import{ensureFrontmatterThemeCompatibility as m}from"../ensure-frontmatter-theme-compatibility.js";const s=async(t,r)=>{const a=await r.fs.read(t),{data:o}=e.default(a,{});return{frontmatter:await m(o,t,r.fs)}};export{s as markdownFrontmatterLoader};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MarkdownConfig } from '@redocly/config';
|
|
2
|
+
export type ResolvedMarkdownTemplate = {
|
|
3
|
+
templateRef: string;
|
|
4
|
+
templatePath: string;
|
|
5
|
+
};
|
|
6
|
+
export type ResolveMarkdownTemplateParams = {
|
|
7
|
+
realRelativePath: string;
|
|
8
|
+
frontmatter?: Record<string, unknown>;
|
|
9
|
+
markdown?: MarkdownConfig;
|
|
10
|
+
contentDir: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function resolveMarkdownTemplate({ realRelativePath, frontmatter, markdown, contentDir, }: ResolveMarkdownTemplateParams): ResolvedMarkdownTemplate | null;
|
|
13
|
+
//# sourceMappingURL=resolve-markdown-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import i from"path";import{resolveGlobMapValue as p}from"../../../utils/globs.js";function u({realRelativePath:t,frontmatter:e,markdown:r,contentDir:a}){const o=typeof e?.template=="string"?e.template:void 0;if(o)return{templateRef:o,templatePath:l(o,i.posix.dirname(t),a)};const n=p(t,r?.template);return n?{templateRef:n,templatePath:l(n,".",a)}:null}function l(t,e,r){return t.startsWith("./")||t.startsWith("../")?i.resolve(r,e,t):t}export{u as resolveMarkdownTemplate};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{toFetchResponse as
|
|
1
|
+
import{toFetchResponse as D,toReqRes as T}from"fetch-to-node";import{logger as l}from"../../../tools/notifiers/logger.js";import{isObject as C}from"../../../../utils/guards/is-object.js";import{createDocsMcpServer as v}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as S}from"../utils.js";import{createMethodNotAllowedError as b,withErrorHandling as N}from"./errors.js";import{McpServerType as O}from"../constants.js";import{constructInvalidTokenResponse as U,constructUnauthorizedResponse as E,handleMcpAuth as I,shouldHandleMcpAuth as j}from"../auth/auth-handlers.js";const i="X-Redocly-AI-Metadata";function k(r){if(r)try{const e=JSON.parse(r);if(C(e))return e;l.warn(`Ignoring ${i} header: not a JSON object.`)}catch{l.warn(`Ignoring ${i} header: invalid JSON.`)}}const L=async(r,e,f)=>{const c=!!e?.config?.access?.requiresLogin,p=e?.config?.access?.rbac||{};let d;if(j(c,p)){const{isAuthenticated:n,isTokenValid:t,currentUser:s,accessToken:a}=await I(r,e);if(!n)return E(new URL(r.url).origin);if(!t)return U();s&&(e.user=s),d=a}let o;const m=async()=>{o&&(await o.cleanup(),o=void 0)};return await N(async()=>{if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need register it in your MCP Client (VS Code, Cursor, Claude Code, etc.) using that URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return b();const n=f,t=n?.props?.config?.apiDescriptionsMap||{},s=n?.props?.config?.mcpDocsServerName||"Docs MCP server",{config:{mcp:a={}}}=e,g=S(t,e.user,p,c),h=e.config.products?Object.values(e.config.products).map(A=>A?.name):[],M=a.docs?.name||s,R=k(r.headers.get(i));o=await v({name:M,tools:n?.props?.tools||[],context:{...e,accessToken:d,outdir:e.outdir||"",baseUrl:e.baseUrl||new URL(r.url).origin,apiDescriptionsMap:g,products:h,metadata:R}});const w=await r.json(),{req:y,res:u}=T(r);return await o.transport.handleRequest(y,u,w),D(u)},O.Docs,m)};var G=L;export{G as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{McpServer as b}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as g}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{logger as n}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as c,MCP_TOOL_WORKER_KEY as S,MCP_TOOL_IS_AVAILABLE_KEY as _}from"../../../workers/mcp-tool-worker-pool.js";async function w({name:e,tools:l,context:
|
|
1
|
+
import{McpServer as b}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as g}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{logger as n}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as c,MCP_TOOL_WORKER_KEY as S,MCP_TOOL_IS_AVAILABLE_KEY as _}from"../../../workers/mcp-tool-worker-pool.js";async function w({name:e,tools:l,context:m}){const a=new b({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}}}),t=new g({sessionIdGenerator:void 0}),i=M(m);for(const o of l){const u=async(r,d)=>{n.info(`MCP tool called: ${o.name}`);const I={toolName:o.name,args:r,context:i,extra:q(d)};return await c.exec(S,[I],{timeout:6e4})},f=a.tool(o.name,o.description,o.schema,u),p={toolName:o.name,context:i};let s=!1;try{s=await c.exec(_,[p],{timeout:1e4})}catch(r){n.error(`Failed to check MCP tool availability for "${o.name}": ${r instanceof Error?r.message:String(r)}`),s=!1}s||f.disable()}return await a.connect(t),{server:a,transport:t,cleanup:async()=>{t.close()}}}function q(e){return{sessionId:e.sessionId,authInfo:e.authInfo,requestId:e.requestId,requestInfo:e.requestInfo,_meta:e._meta}}function M(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,products:e.products,accessToken:e.accessToken,metadata:e.metadata}}export{w as createDocsMcpServer};
|
|
@@ -78,6 +78,7 @@ export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | k
|
|
|
78
78
|
apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
|
|
79
79
|
products?: string[];
|
|
80
80
|
accessToken?: string;
|
|
81
|
+
metadata?: Record<string, unknown>;
|
|
81
82
|
};
|
|
82
83
|
export type McpToolHandler<TArgs extends Record<string, unknown> = Record<string, unknown>> = (args: TArgs, context: McpToolContext, extra: McpToolExtra) => Promise<McpToolWorkerResponse>;
|
|
83
84
|
export type McpToolIsAvailable = (context: McpToolContext) => boolean | Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getPublicEnvVariables as n}from"../../utils/envs/get-public-env-variables.js";const l=async({fsPath:r,slug:
|
|
1
|
+
import{getPublicEnvVariables as n}from"../../utils/envs/get-public-env-variables.js";const l=async({fsPath:r,slug:e},t,{variables:a,partials:i},o)=>{const s=o.getPartialsForRoute?.(e)||i;return{definitionId:r,...t.props,markdown:{partials:s,variables:{...a,env:n()}}}};var d=l;export{d as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{writeFileSync as tt}from"node:fs";import*as
|
|
1
|
+
import{writeFileSync as tt}from"node:fs";import*as u from"path";import{removeMarkdocTags as et}from"../../../markdoc/helpers/remove-markdoc-tags.js";import{withoutHash as ot}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as E,SIDEBAR_PREFIX as rt,CONFIG_FILE_NAME as K}from"../../../constants/common.js";import{CATALOG_OUTPUT_FILE_NAME as at}from"../../constants/common.js";import{findDeepFirst as M}from"../../../utils/tree/find-deep-first.js";import{isDefined as X}from"../../../utils/guards/is-defined.js";import{partition as it}from"../../../utils/array/partition.js";import{collectPropValueDeep as N}from"../../../utils/tree/collect-prop-value-deep.js";import{envConfig as nt}from"../../config/env-config.js";import{isLocalLink as st}from"../../../utils/path/is-local-link.js";import{normalizeRouteSlug as Y}from"../../../utils/path/normalize-route-slug.js";import{slash as lt}from"../../../utils/path/slash.js";import{parsePathVersions as ct}from"../../../utils/path/parse-path-versions.js";import{reporter as k}from"../../tools/notifiers/reporter.js";import{logger as B}from"../../tools/notifiers/logger.js";import{sha1 as ft}from"../../utils/crypto/sha1.js";import{collectItemsLinkedToSidebars as dt,resolveItems as J}from"../nav-utils.js";import{getExcludedFromLinkCheckerPatterns as ut,getSidebarReferences as mt,hasCircularDependency as gt}from"./utils.js";import{getLocaleFromRelativePath as pt}from"../../fs/utils/get-locale-from-relative-path.js";import{isSystemRouteSlug as ht}from"../../utils/system-routes.js";import{ENTITIES_MAP_GLOBAL_DATA_KEY as St}from"../../constants/plugins/catalog-entities.js";import{telemetryTraceStep as yt}from"../../../cli/telemetry/helpers/trace-step.js";import{isPathIgnored as Ft}from"../../utils/paths.js";const It=180,bt=170,Dt=10;async function Jt({contentDir:f}){return{id:"sidebars",async afterRoutesCreated(o,i){await yt("build.plugin.sidebars",async()=>{const{cache:p,fs:d}=i,b=o.getConfig(),D=new Map,P=new Set,x=[E,...d.localeFolders],$=o.getGlobalData()[St]||{},j=new Map;let R=d.scan(/sidebars.yaml$/).map(({relativePath:t})=>t).filter(t=>!Ft(t,b.ignore??[])&&t);const G=await mt(i,f,R),Q=it(R.filter(t=>!G.has(t)),t=>{const l=ct(t);return l?`@versioned/${l.versionFolderPath}\0${l.filePathInVersion}`:t}),_=ut(b),Z=await dt(b?.navbar,o,i,{navFile:K,excludedFromLinkCheckerPatterns:_});let C;const T=gt(G);T&&Array.isArray(T)&&await k.panicOnBuildContentError(`Sidebar references have circular dependency. Please check your sidebar files.
|
|
2
2
|
Circular dependency chain: ${T.reverse().join(" -> ")}
|
|
3
|
-
`);for(const t of Q){const
|
|
3
|
+
`);for(const t of Q){const l=(await Promise.all(t.map(async n=>{const e=(await p.load(n,"yaml")).data;if(!Array.isArray(e)){await k.panicOnBuildContentErrorForRealFile('Invalid sidebar contents at %rp, items should be an array, got "%s"',n,d,n,typeof e);return}return{items:e,sidebarRelativePath:n,locale:pt(n)}}))).filter(X),a=(await A(l))?.firstLink;C||(C=a)}const H=Object.entries(b?.catalogClassic??{});for(const t of x){for(const[e,c]of H)await z(e,c,t);const l={},a=new Set,n=o.getAllRoutesForLocale(t);for(const e of n)if(W(e)&&e.fsPath&&!a.has(e.fsPath)){a.add(e.fsPath);let s=u.posix.dirname(e.fsPath);const h=u.parse(s).root;do l[s]=(l[s]||0)+1,s=u.dirname(s);while(s&&s!="."&&h!=s)}for(const e of n){if(D.has(e.slug))continue;const c=W(e),s=u.dirname(e.fsPath),h=l[s]===1,m=vt(e.baseSlug||e.slug);c&&h?await A([{items:[{directory:s}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}]):e.getSidebar!==void 0&&await A([{items:[{page:e.fsPath}],sidebarRelativePath:"sidebar.yaml_"+m,locale:t}])}for(const[e,c]of H)await z(e,c,t,!0)}if(R.length===0)for(const t of x){B.verbose("Creating default sidebar");const l=t===E,a=`sidebars.yaml${l?"":"_"+t}`,n=l?"":`${d.localizationFolder}/${t}`,e=(await A([{items:[{directory:`./${n}`}],sidebarRelativePath:a,locale:t,ignoredRoutes:P}]))?.firstLink;C||(C=e)}if(!o.getRouteBySlug("/")&&!o.getConfig().redirects?.["/"]){const l=o.getAllRoutes().find(n=>!ht(n.slug)),a=C?C.link:l?.baseSlug??null;if(a){const n=ot(a);o.addRedirect("/",{to:n,type:302}),B.info("Creating default redirect for index page => %s",n)}}const U=nt.REDOCLY_METADATA_OUTPUT_FOLDER;U&&(B.info("Writing catalog data..."),tt(u.join(U,at),JSON.stringify(Object.fromEntries(j.entries()))));function W(t){return P.has(t.slug)||$[t.fsPath]}async function A(t){if(t.length===0)return;const a=(await Promise.all(t.map(async({items:m,locale:I,sidebarRelativePath:g,ignoredRoutes:L})=>{const r=await J(m,u.dirname(u.join(f,g)),o,i,{locale:I,ignoredRoutes:L,navFile:g,excludedFromLinkCheckerPatterns:_});if(!r){await k.panicOnBuild("Failed to resolve sidebar configuration. Make sure %rp is valid",g);return}return r}))).flat().filter(X),n=N(a,"routeSlug"),e=t[0].sidebarRelativePath,c=q(e),s=new Set;for(const m of n){const I=o.getRouteBySlug(m)?.fsPath??"",g=$[I];g&&(Array.from(s).find(r=>r.key===g.key&&r.version===g.version)||s.add(g)),o.addRouteSharedData(m,"sidebar",c),D.set(Y(m),a)}const h=s.size===1?Array.from(s)[0]:void 0;return await o.createSharedData(c,{relatedNavbarItem:Z?.get(e),items:a,catalogEntity:h?{key:h.key,version:h.version}:void 0}),{firstLink:M(a,m=>!!m.link),resolved:a}}async function z(t,l,a,n=!1){const e=structuredClone(l);a&&a!==E&&e.items.forEach(r=>{r.directory=u.posix.join(d.localizationFolder||"",a,r.directory||"")});let c=await J(e.items,f,o,i,{groupCustomSidebars:!0,locale:a,navFile:K,excludedFromLinkCheckerPatterns:_});if(!c){await k.panicOnBuild(`Failed to resolve catalog configuration. Make sure catalog ${t} has valid config`);return}Ct(c);const s=a===E?"":"/"+a.toLowerCase(),h=a===E?"":`-${a}`,m=Y(u.posix.join(s,e.slug));if(n)for(const r of c){const S=M(r.items||[],F=>!!F.routeSlug);if(!S?.routeSlug)continue;const y=D.get(S.routeSlug);if(!y)continue;const O=N(y,"routeSlug"),w="current-catalog-info-"+r.routeSlug+h,v={catalog:{label:e.title,titleTranslationKey:e.titleTranslationKey,link:m,icon:e?.icon},item:{label:r.metadata?.title,link:r.link,icon:r.icon}};await o.createSharedData(w,v);for(const F of O)o.addRouteSharedData(F,"current-catalog-info",w),P.add(F);const V=M(y,F=>!!F.link&&!F.external&&st(F.link)&&(!r.version||F.version===r.version));V&&(r.sidebar=[{...V,items:void 0}])}const I={},g=new Set;for(const r of c){if(!(r.routeSlug||r.sidebar?.[0]?.routeSlug)||!r.fsPath||g.has(r.fsPath))continue;g.add(r.fsPath);const y=u.dirname(r.fsPath);I[y]=(I[y]||0)+1}if(n){const r=await o.createSharedData("catalog-"+t+h,c.flatMap(S=>{const y=u.dirname(S.fsPath??""),O=I[y]===1,w=v=>({...v,fsPath:O?y:v.fsPath??""});return S.type==="group"&&S.items?.every(v=>v.type==="group")?(S.items||[]).map(w):w(S)}));o.addRouteSharedData(m,"catalog",r),Pt(a,c,j,I)}const L=N(c,"routeSlug");for(const r of L)P.add(r)}})}}}function Pt(f,o,i,p){if(f===E)for(const d of o){const b=d.routeSlug||d.sidebar?.[0]?.routeSlug;if(!b||!d.fsPath)continue;const D=u.dirname(d.fsPath),P=p[D]===1;i.set(b,{rootFileFsPath:d.fsPath,fsPath:P?D:d.fsPath,metadata:d.metadata||{},title:d.metadata?.title||d.label||"Untitled",version:d.version||"latest"})}}function Ct(f){const o=i=>{typeof i.metadata?.description=="string"&&(i.metadata={...i.metadata,description:et(i.metadata.description)})};for(const i of f)if(i.routeSlug)o(i);else for(const p of i.items||[])o(p)}function q(f){return rt+lt(f)}async function qt(f,o,i){const p=u.posix.join(u.dirname(f),o);return await i.exists(p)?q(p):(await k.panicOnBuildContentErrorForRealFile("File %rp: Failed to create relative path for sidebars.yaml using %s",f,i,f,o),null)}function vt(f){const o=f.replaceAll("/","_");if(o.length>It){const i=o.slice(0,bt),p=ft(f).slice(0,Dt).replaceAll("/","_");return i+p}else return o}export{qt as resolveSidebarId,Jt as sidebarsPlugin,Ct as stripMarkdocFromDescriptions};
|
package/dist/server/store.d.ts
CHANGED
package/dist/server/store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import b from"@markdoc/markdoc";import{getPathnameForLocale as A}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as R}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as y}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as H,writeStaticData as N}from"./utils/static-data.js";import{parseAndResolveMarkdoc as V}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as S}from"./entitlements/entitlements-provider.js";import{isL10nPath as q}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as K}from"./utils/globs.js";import{replaceEnvVariablesDeep as U}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as x}from"./utils/redirects/find-redirect.js";import{followRedirectChain as J}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ae="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#e={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#t=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:a}){this.#r=s,this.outdir=e,this.serverMode=t,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(e,s){const t=this.listeners.get(e);t?t.add(s):this.listeners.set(e,new Set([s]))}queueEvent=(e,s,...t)=>{this.#t.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const a of this.listeners.get(e)||new Set)s?a(s,...t):a(...t)};startPluginsRun(){this.clear(),this.#o=new Promise(e=>{this.#i=e})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const e of this.#t.values())this.runListeners(...e);this.#t.clear()}startEsbuildRun(){this.#n=new Promise(e=>{this.#c=e})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const e=S.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?e.canAccessFeature(D[a]):!0));this.#s={...s,tags:t}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const s=this.globalData,t={...this.globalData,...e};this.globalData=t,JSON.stringify(t)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,t)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await V(e,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&r.partials?.length)for(const i of t.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(e){return(await e.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(e){return(await e.cache.load(".","asyncapi-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=R(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:t,unsetEnvVars:a,replacedValues:r}=U(e);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!S.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(e).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=t,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const s=h(e).toLowerCase(),t=x(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(y(t.to)){const a=h(t.to).toLowerCase();if(!a.endsWith("*")&&J(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:t.to,type:t.type}};createSharedData=async(e,s,t)=>{if(t&&this.#e[e]===t)return e;const a=JSON.stringify(s),r=t??k(a);return this.#e[e]===r||(this.#e[e]=r,await B(e,a,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const a=L(e),r=this.routesSharedData.get(a)||{};r[s]=t,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${e}, ${s}, ${t}`)};getRouteSharedDataByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=e=>{const s=this.getGlobalConfig(m)||{},t=this.routesPartials.get(e);if(!t||t.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(t),o=Array.from(t);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=e=>{const t={...K(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=A(e,g,r.code,a);this.addRouteSharedData(o,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s)this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(o=>o.name.toLowerCase())),r=[...(this.config.responseHeaders[e]??[]).filter(o=>!t.has(o.name.toLowerCase())),...s];this.config.responseHeaders[e]=r};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,a=this.getRedirect(e);return t&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!y(s.to))return!0;const t=h(s.to);return this.routesBySlug.has(t)};getRoutesByTemplateId=e=>this.newRoutes.filter(s=>s.templateId===e);getAllRoutesForLocale=(e=g)=>{const s=Array.from(this.routesBySlug.values()),t=e.toLowerCase();return s.filter(a=>e===g?!q(a.fsPath):a.slug.startsWith(`/${t}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,s)=>(this.templates.set(e,s),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,s)=>(this.apiRoutesRequestHandlers.set(e,s),e);clearRequestHandlersByPrefix=e=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(e)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(e,s)=>(this.serverPropsGetters.set(e,s),e);registerPagePropsGetter=(e,s)=>{this.pagePropsGetters.set(e,s)};async writeRouteStaticData(e,s){const t=await this.resolveRouteStaticData(e,s,!1);t&&N(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return H(e.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},r=await e.getStaticData?.(e,a)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...e.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:t||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,s){if(!e?.length)return;const t=typeof e[0]=="string"?e.join(""):I(e);t&&(s==="head"?this.ssr.headTags.push(t):s==="preBody"?this.ssr.preBodyTags.push(t):this.ssr.postBodyTags.push(t))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[t].entries());e.push([t,r]);break;case"object":t==="config"&&e.push([t,await this.getConfigWithEnvPlaceholders()]),e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[E]=_.PLAN_GATES,s}static fromJson(e,s){const t=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":t[r]=new Map(e[r]);break;case"object":if(r==="config"){t.setGlobalConfig(e[r]);break}t[r]=e[r];break;default:throw new Error("Invalid format")}t.config[m]=Z(t.config[m]||{});const a=e[E];return a&&G("PLAN_GATES",a),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=R(e,a);if(o||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Y.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await w.panicOnBuildContentError(s)}}function Z(C){return M(C,e=>b.Ast.fromJSON(JSON.stringify(e)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Ae as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
1
|
+
import b from"@markdoc/markdoc";import{getPathnameForLocale as A}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as R}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as y}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as H,writeStaticData as N}from"./utils/static-data.js";import{parseAndResolveMarkdoc as V}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as j}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as S}from"./entitlements/entitlements-provider.js";import{isL10nPath as q}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as K}from"./utils/globs.js";import{replaceEnvVariablesDeep as U}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as x}from"./utils/redirects/find-redirect.js";import{followRedirectChain as J}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ae="userDefinedApiFunctions";class P{routesBySlug=new Map;replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#e={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#t=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:a}){this.#r=s,this.outdir=e,this.serverMode=t,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(e,s){const t=this.listeners.get(e);t?t.add(s):this.listeners.set(e,new Set([s]))}queueEvent=(e,s,...t)=>{this.#t.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const a of this.listeners.get(e)||new Set)s?a(s,...t):a(...t)};startPluginsRun(){this.clear(),this.#o=new Promise(e=>{this.#i=e})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const e of this.#t.values())this.runListeners(...e);this.#t.clear()}startEsbuildRun(){this.#n=new Promise(e=>{this.#c=e})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const e=S.instance(),s=await j(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?e.canAccessFeature(D[a]):!0));this.#s={...s,tags:t}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=e=>{const s=this.globalData,t={...this.globalData,...e};this.globalData=t,JSON.stringify(t)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,t)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await V(e,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&r.partials?.length)for(const i of t.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(e){return(await e.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(e){return(await e.cache.load(".","asyncapi-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setGlobalConfig=e=>{const s=Object.keys(e);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=R(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:t,unsetEnvVars:a,replacedValues:r}=U(e);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!S.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(e).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=t,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=e=>{const s=h(e).toLowerCase(),t=x(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!t)return null;if(y(t.to)){const a=h(t.to).toLowerCase();if(!a.endsWith("*")&&J(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:t.to,type:t.type}};createSharedData=async(e,s,t)=>{if(t&&this.#e[e]===t)return e;const a=JSON.stringify(s),r=t??k(a);return this.#e[e]===r||(this.#e[e]=r,await B(e,a,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const a=L(e),r=this.routesSharedData.get(a)||{};r[s]=t,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${e}, ${s}, ${t}`)};getRouteSharedDataByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=e=>{const s=this.getGlobalConfig(m)||{},t=this.routesPartials.get(e);if(!t||t.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(t),o=Array.from(t);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=e=>{const t={...K(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=A(e,g,r.code,a);this.addRouteSharedData(o,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s)this.mcpToolHandlers.set(t.name,{...t,importPath:e}),u.verbose("Created MCP tool %s",t.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(o=>o.name.toLowerCase())),r=[...(this.config.responseHeaders[e]??[]).filter(o=>!t.has(o.name.toLowerCase())),...s];this.config.responseHeaders[e]=r};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,a=this.getRedirect(e);return t&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!y(s.to))return!0;const t=h(s.to);return this.routesBySlug.has(t)};getRoutesByTemplateId=e=>this.newRoutes.filter(s=>s.templateId===e);getAllRoutesForLocale=(e=g)=>{const s=Array.from(this.routesBySlug.values()),t=e.toLowerCase();return s.filter(a=>e===g?!q(a.fsPath):a.slug.startsWith(`/${t}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=e=>this.templates.get(e);getRequestHandler=e=>this.apiRoutesRequestHandlers.get(e);createTemplate=(e,s)=>(this.templates.set(e,s),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};createRequestHandler=(e,s)=>(this.apiRoutesRequestHandlers.set(e,s),e);clearRequestHandlersByPrefix=e=>{for(const s of this.apiRoutesRequestHandlers.keys())s.startsWith(e)&&this.apiRoutesRequestHandlers.delete(s)};registerServerPropsGetter=(e,s)=>(this.serverPropsGetters.set(e,s),e);registerPagePropsGetter=(e,s)=>{this.pagePropsGetters.set(e,s)};async writeRouteStaticData(e,s){const t=await this.resolveRouteStaticData(e,s,!1);t&&N(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return H(e.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},r=await e.getStaticData?.(e,a)||{},o=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...e.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:t||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,s){if(!e?.length)return;const t=typeof e[0]=="string"?e.join(""):I(e);t&&(s==="head"?this.ssr.headTags.push(t):s==="preBody"?this.ssr.preBodyTags.push(t):this.ssr.postBodyTags.push(t))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[t].entries());e.push([t,r]);break;case"object":t==="config"&&e.push([t,await this.getConfigWithEnvPlaceholders()]),e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[E]=_.PLAN_GATES,s}static fromJson(e,s){const t=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":t[r]=new Map(e[r]);break;case"object":if(r==="config"){t.setGlobalConfig(e[r]);break}t[r]=e[r];break;default:throw new Error("Invalid format")}t.config[m]=Z(t.config[m]||{});const a=e[E];return a&&G("PLAN_GATES",a),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=R(e,a);if(o||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Y.includes(t));if(e.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await w.panicOnBuildContentError(s)}}function Z(C){return M(C,e=>b.Ast.fromJSON(JSON.stringify(e)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Ae as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import picomatch from 'picomatch';
|
|
2
2
|
export declare const getDeeperGlobPattern: (a: ReturnType<typeof picomatch.scan>, b: ReturnType<typeof picomatch.scan>) => import("picomatch/lib/scan").State;
|
|
3
3
|
export declare function pathMatchesGlobPattern(relativePath: string, pattern: string): boolean;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function getMostSpecificMatchingGlobKey(relativePath: string, globMap?: Record<string, unknown>): string | undefined;
|
|
5
|
+
export declare function resolveGlobMapValue<T>(relativePath: string, globMap?: Record<string, T>): T | undefined;
|
|
5
6
|
export declare function convertGlobToRegex(glob: string): RegExp | undefined;
|
|
6
7
|
//# sourceMappingURL=globs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import s from"picomatch";import{minimatch as
|
|
1
|
+
import s from"picomatch";import{minimatch as l}from"minimatch";import u from"is-glob";import c from"path";import{removeTrailingSlash as f}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as m}from"../../utils/url/remove-leading-slash.js";const p=(t,e)=>{const n=t.tokens??[],o=e.tokens??[];if(t.isGlob!==e.isGlob)return t.isGlob?e:t;if(n.length!==o.length)return n.length>o.length?t:e;for(let r=0;r<n.length;r++){if(n[r].isGlob!==o[r].isGlob)return n[r].isGlob?e:t;if(n[r].value!==o[r].value)return n[r].value.length>o[r].value.length?t:e}return t};function h(t,e){if(u(e)){if(l(t,e))return!0}else{const n=f(m(c.posix.normalize(e))),o=t.startsWith(n+"/");if(t===n||o)return!0}return!1}function a(t,e){if(!e)return;const n=[];for(const i of Object.keys(e))h(t,i)&&n.push(i);if(!n.length)return;const o=n.map(i=>s.scan(i,{tokens:!0,parts:!0}));let r=o[0];for(let i=1;i<o.length;i++)r=p(r,o[i]);return r.input}function v(t,e){const n=a(t,e);return n!=null&&e?e[n]:void 0}function y(t){const e=s.makeRe(t);return e||void 0}export{y as convertGlobToRegex,p as getDeeperGlobPattern,a as getMostSpecificMatchingGlobKey,h as pathMatchesGlobPattern,v as resolveGlobMapValue};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import y from"path";import T from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@redocly/reef",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.134.0-next.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"@opentelemetry/sdk-trace-web": "2.6.1",
|
|
30
30
|
"@opentelemetry/semantic-conventions": "1.40.0",
|
|
31
31
|
"@redocly/ajv": "8.18.0",
|
|
32
|
-
"@redocly/openapi-core": "2.
|
|
32
|
+
"@redocly/openapi-core": "2.31.2",
|
|
33
33
|
"@shikijs/transformers": "3.21.0",
|
|
34
34
|
"@tanstack/react-query": "5.62.3",
|
|
35
35
|
"@tanstack/react-table": "8.21.3",
|
|
@@ -90,14 +90,14 @@
|
|
|
90
90
|
"xpath": "0.0.34",
|
|
91
91
|
"yaml-ast-parser": "0.0.43",
|
|
92
92
|
"zod": "^3.25.76",
|
|
93
|
-
"@redocly/
|
|
94
|
-
"@redocly/config": "0.
|
|
95
|
-
"@redocly/
|
|
96
|
-
"@redocly/
|
|
97
|
-
"@redocly/
|
|
98
|
-
"@redocly/
|
|
99
|
-
"@redocly/
|
|
100
|
-
"@redocly/
|
|
93
|
+
"@redocly/asyncapi-docs": "1.11.0-next.1",
|
|
94
|
+
"@redocly/config": "0.49.0",
|
|
95
|
+
"@redocly/graphql-docs": "1.11.0-next.1",
|
|
96
|
+
"@redocly/openapi-docs": "3.22.0-next.1",
|
|
97
|
+
"@redocly/portal-legacy-ui": "0.17.0-next.0",
|
|
98
|
+
"@redocly/portal-plugin-mock-server": "0.19.0-next.1",
|
|
99
|
+
"@redocly/realm-asyncapi-sdk": "0.12.0-next.1",
|
|
100
|
+
"@redocly/theme": "0.66.0-next.1"
|
|
101
101
|
},
|
|
102
102
|
"peerDependencies": {
|
|
103
103
|
"react": "^19.2.4",
|