@redocly/reef 0.141.0-next.1 → 0.141.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/constants/common.d.ts +2 -0
  3. package/dist/constants/common.js +1 -1
  4. package/dist/constants/l10n/langs/ar.js +1 -1
  5. package/dist/constants/l10n/langs/de.js +1 -1
  6. package/dist/constants/l10n/langs/en.js +1 -1
  7. package/dist/constants/l10n/langs/es.js +1 -1
  8. package/dist/constants/l10n/langs/fr.js +1 -1
  9. package/dist/constants/l10n/langs/hi.js +1 -1
  10. package/dist/constants/l10n/langs/it.js +1 -1
  11. package/dist/constants/l10n/langs/ja.js +1 -1
  12. package/dist/constants/l10n/langs/ko.js +1 -1
  13. package/dist/constants/l10n/langs/pl.js +1 -1
  14. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  15. package/dist/constants/l10n/langs/pt.js +1 -1
  16. package/dist/constants/l10n/langs/ru.js +1 -1
  17. package/dist/constants/l10n/langs/uk.js +1 -1
  18. package/dist/constants/l10n/langs/zh.js +1 -1
  19. package/dist/server/constants/entitlements.js +1 -1
  20. package/dist/server/entitlements/entitlements-provider.d.ts +4 -0
  21. package/dist/server/entitlements/entitlements-provider.js +1 -1
  22. package/dist/server/entitlements/plan-denied-markdoc-tags.d.ts +6 -0
  23. package/dist/server/entitlements/plan-denied-markdoc-tags.js +1 -0
  24. package/dist/server/fs/fast-mtime.js +3 -3
  25. package/dist/server/plugins/config-parser/format-error.js +2 -2
  26. package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
  27. package/dist/server/plugins/markdown/compiler.d.ts +3 -3
  28. package/dist/server/plugins/markdown/compiler.js +1 -1
  29. package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +2 -0
  30. package/dist/server/plugins/markdown/markdoc/markdoc-options.js +1 -1
  31. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.d.ts +4 -1
  32. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -1
  33. package/dist/server/plugins/mcp/index.js +1 -1
  34. package/dist/server/plugins/mcp/types.d.ts +1 -0
  35. package/dist/server/ssr/server-side-props/get-default-static-props.d.ts +1 -0
  36. package/dist/server/store.js +1 -1
  37. package/dist/server/types/plugins/common.d.ts +2 -0
  38. package/dist/types/entitlements.d.ts +4 -0
  39. package/package.json +6 -6
@@ -1 +1 @@
1
- import k from"@redocly/markdoc";import{writeFileSync as D}from"node:fs";import{readFile as R}from"node:fs/promises";import{join as g}from"node:path";import{parseAndResolveMarkdoc as F}from"./plugins/markdown/compiler.js";import{getPathnameForLocale as L}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as m}from"../constants/common.js";import{DEFAULT_TITLE as H,MARKDOC_PARTIALS_DATA_KEY as y,MARKDOC_PARTIALS_DEPS_KEY as G}from"./constants/common.js";import{GATED_MARKDOC_TAGS as S}from"./constants/entitlements.js";import{isObject as _}from"../utils/guards/is-object.js";import{mapObject as N}from"../utils/object/map-object.js";import{getValueDeep as v}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as B}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as d}from"../utils/path/normalize-route-slug.js";import{isLocalLink as E}from"../utils/path/is-local-link.js";import{reporter as C}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as I}from"./utils/crypto/sha1.js";import{FileNotFoundError as j}from"./utils/fs.js";import{resolveAssetPath as V}from"./utils/resolve-asset-path.js";import{envConfig as q,setEnv as J}from"./config/env-config.js";import{KvService as U}from"./persistence/kv/services/kv-service.js";import{SandboxContext as x}from"./utils/sandbox-context.js";import{isAllowedEnv as K}from"./utils/envs/get-api-route-allowed-env-variables.js";import{ensureDir as $,writeSharedData as W}from"./utils/index.js";import{renderComponents as z}from"./ssr/render.js";import{readStaticData as Y,writeStaticData as Z}from"./utils/static-data.js";import{getMarkdocOptions as Q}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as P}from"./entitlements/entitlements-provider.js";import{isRouteReserved as X}from"./plugins/get-reserved-routes.js";import{isL10nPath as ee}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as te}from"./utils/globs.js";import{createDefaultStoreConfig as se,resolveConfigEntries as re,resolveStoreConfig as oe}from"./store-config.js";import{findRedirect as ae}from"./utils/redirects/find-redirect.js";import{followRedirectChain as ie}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as ne}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as ce}from"../cli/telemetry/helpers/trace-step.js";const A={routesBySlug:"map",staticFilePaths:"object",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map",devLogin:"object"},b="store.json",O="store-config.json",T="PLAN_GATES",le=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],We="userDefinedApiFunctions";class w{routesBySlug=new Map;routeAliases=new Map;staticFilePaths={};replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;skills=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};devLogin=!1;#a=void 0;config=se();configFile;#i;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#n;userCodeReady;#s=Promise.resolve();#c;#l=Promise.resolve();#d;#h=Promise.resolve();#u;#e=!1;#r=0;#f=0;#o=new Map;constructor({outdir:e,contentDir:t,serverMode:s=!1,serverOutDir:r}){this.#i=t,this.outdir=e,this.serverMode=s,this.serverOutDir=r,x.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(o=>{this.#n=o})}on(e,t){const s=this.listeners.get(e);s?s.add(t):this.listeners.set(e,new Set([t]))}queueEvent=(e,t,...s)=>{this.#o.set(e+String(t),[e,t,...s])};runListeners=(e,t,...s)=>{for(const r of this.listeners.get(e)||new Set)t?r(t,...s):r(...s)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#l,this.#h])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#o.values())this.runListeners(...e);this.#o.clear()}startEsbuildRun(){this.#l=new Promise(e=>{this.#d=e})}finishEsbuildRun(){this.#d?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#h=new Promise(e=>{this.#u=e}))}noteRequestHandlersEntryBuildStart(){this.#f=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#f||(this.#e=!1,this.#u?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#i}markUserCodeReady(){this.#n?.(!0)}async reloadMarkdocOptions(){await ce("com.redocly.build.reloadMarkdocOptions",async()=>{const e=P.instance(),t=await Q(this.serverOutDir),s=Object.fromEntries(Object.entries(t.tags).filter(([r])=>S[r]!=null?e.canAccessFeature(S[r]):!0));this.#a={...t,tags:s}})}get markdocOptions(){return{...this.#a,partials:this.getGlobalConfig(y),themeConfig:this.config.markdown}}setGlobalData=e=>{const t=this.globalData,s={...this.globalData,...e};this.globalData=s,JSON.stringify(s)!==JSON.stringify(t)&&this.queueEvent("global-data-updated",void 0,s)};getGlobalData=()=>this.globalData;getKv=async()=>U.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:t,deps:s,resource:r})=>{const{data:{info:o,ast:a},compoundHash:c}=await F(e,this.markdocOptions,{actions:this,context:t},r);for(const i of o.sharedDataDeps||[]){for(const n of s?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of s?.sharedDataIds||[]){const l=this.sharedDataDeps.get(n)||new Set;l.add(i),this.sharedDataDeps.set(n,l)}}for(const i of o.dynamicMarkdocComponents||[]){for(const n of s?.routeSlugs||[]){const l=this.routesDynamicComponents.get(n)||new Set;l.add(i),this.routesDynamicComponents.set(n,l)}for(const n of s?.sharedDataIds||[]){const l=this.sharedDataMarkdocComponents.get(n)||new Set;l.add(i),this.sharedDataMarkdocComponents.set(n,l)}}if(s?.routeSlugs&&o.partials?.length)for(const i of s.routeSlugs){const n=this.routesPartials.get(i)||[];for(const l of o.partials)n.includes(l)||n.push(l);this.routesPartials.set(i,n)}return{info:o,ast:a,compoundHash:c}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setStaticFilePaths=e=>{this.staticFilePaths=e};setGlobalConfig=e=>{const t=Object.keys(e);for(const a of t)for(const c in this.replacedEnvVars)if(c===a||c.startsWith(`${a}:`)){const i=c.split(":"),{error:n,value:l}=v(e,i);(n||l!==this.replacedEnvVars[c].replaced)&&delete this.replacedEnvVars[c]}const{config:s,unsetEnvVars:r,replacedValues:o}=re(e);for(const a of r)this.unsetEnvVars.add(a);Object.assign(this.replacedEnvVars,o),Object.assign(this.config,s)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,t,s={})=>{if(!P.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const a=d(e).toLowerCase();this.config.redirects[a]=t;const{trackOriginalSource:c=!0}=s,i=this.getGlobalConfig("originalRedirectSources");c&&Array.isArray(i)&&!i.includes(a)&&i.push(a),a.endsWith("*")&&ne(this.config.wildcardRedirectsTree,a)};getRedirect=e=>{const t=d(e).toLowerCase(),s=ae(t,this.config.redirects,this.config.wildcardRedirectsTree,this.staticFilePaths);if(!s)return null;if(E(s.to)){const r=d(s.to).toLowerCase();if(!r.endsWith("*")&&ie(r,[t],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:s.to,type:s.type}};createSharedData=async(e,t,s)=>{if(s&&this.#t[e]===s)return e;const r=JSON.stringify(t),o=s??I(r);return this.#t[e]===o||(this.#t[e]=o,await W(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,t,s)=>{const r=B(e),o=this.routesSharedData.get(r)||{};o[t]=s,this.routesSharedData.set(r,o),u.verbose(`Adding shared data to ${e}, ${t}, ${s}`)};getRouteSharedDataByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.routesSharedData.get(t)||{}:{}};getPartialsForRoute=e=>{const t=this.getGlobalConfig(y)||{},s=this.routesPartials.get(e);if(!s||s.length===0)return{};const r=this.getGlobalConfig(G)||{},o=new Set(s),a=Array.from(s);for(let i=0;i<a.length;i++){const n=a[i],l=r[n]?.partials??[];for(const h of l)o.has(h)||(o.add(h),a.push(h))}const c={};for(const i of o)t[i]&&(c[i]=t[i]);return c};addRoute=e=>{const s={...te(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:s}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,t,s)=>{const r=[m,...this.lifecycleContext?.fs.localeFolders||[]].map(o=>({code:o,name:o}));for(const o of r){const a=L(e,m,o.code,r);this.addRouteSharedData(a,t,s)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,t)=>{for(const s of t){const r=this.mcpToolHandlers.get(s.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',s.name,e,r.importPath);const o=s.hasAvailabilityGate??(r?.importPath===e?r.hasAvailabilityGate:void 0);this.mcpToolHandlers.set(s.name,{...s,importPath:e,hasAvailabilityGate:o}),u.verbose("Created MCP tool %s",s.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const t of e){const s=this.mcpToolHandlers.get(t);s&&this.mcpToolHandlers.set(t,{...s,hasAvailabilityGate:!0})}};addSkills=e=>{for(const t of e)this.skills.set(t.slug,t),u.verbose("Discovered skill %s",t.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const t of e)this.mcpToolHandlers.delete(t)};addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,t)=>{this.config.responseHeaders||(this.config.responseHeaders={});const s=new Set(t.map(a=>a.name.toLowerCase())),o=[...(this.config.responseHeaders[e]??[]).filter(a=>!s.has(a.name.toLowerCase())),...t];this.config.responseHeaders[e]=o};getRouteByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.getRouteBySlug(t):void 0};getRouteBySlug=(e,t={})=>{const{followRedirect:s=!0}=t,r=this.getRedirect(e);if(s&&r)return this.routesBySlug.get(d(r.to));const o=s?this.routeAliases.get(d(e).toLowerCase()):void 0;return this.routesBySlug.get(o??e)};addRouteAlias=(e,t)=>{this.routeAliases.set(d(e).toLowerCase(),d(t))};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e)||this.routeAliases.has(d(e).toLowerCase())||X(e,this.getConfig()))return!0;const t=this.getRedirect(e);if(!t)return!1;if(!E(t.to))return!0;const s=d(t.to);return this.routesBySlug.has(s)};getRoutesByTemplateId=e=>this.newRoutes.filter(t=>t.templateId===e);getAllRoutesForLocale=(e=m)=>{const t=Array.from(this.routesBySlug.values()),s=e.toLowerCase();return t.filter(r=>e===m?!ee(r.fsPath):r.slug.startsWith(`/${s}`))};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,t)=>(this.templates.set(e,t),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};copyAsset=async(e,t)=>{const s=this.lifecycleContext?.fs;if(!s)throw new Error(`Cannot copy asset ${e}: the content file system is not ready`);try{const r=await V(e,s,{fromFileRelativePath:t,contentDir:this.contentDir,outdir:this.outdir});if(!r)throw new Error(`Cannot copy asset ${e}`);return r}catch(r){if(r instanceof j)return null;throw r}};createRequestHandler=(e,t)=>(this.apiRoutesRequestHandlers.set(e,t),e);clearRequestHandlersByPrefix=e=>{for(const t of this.apiRoutesRequestHandlers.keys())t.startsWith(e)&&this.apiRoutesRequestHandlers.delete(t)};registerServerPropsGetter=(e,t)=>(this.serverPropsGetters.set(e,t),e);registerPagePropsGetter=(e,t)=>{this.pagePropsGetters.set(e,t)};async writeRouteStaticData(e,t){const s=await this.resolveRouteStaticData(e,t,!1);s&&Z(e.slug,s,this.outdir)}async resolveRouteStaticData(e,t,s){if(this.serverMode)return Y(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:l,context:h,resource:f})=>this.parseMarkdoc({input:l,context:h,deps:{routeSlugs:[e.slug]},resource:f})},o=await e.getStaticData?.(e,r)||{},a=new Set(this.routesDynamicComponents.get(e.slug)),c=this.routesSharedData.get(e.slug)||{};for(const l of Object.values(c)){const h=this.sharedDataMarkdocComponents.get(l);h&&h.forEach(p=>a.add(p));const f=this.sharedDataDeps.get(l);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=o?.frontmatter||{};return{...o,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...o.props,dynamicMarkdocComponents:Array.from(a),metadata:{...o?.props?.metadata,...e.metadata},seo:{title:H,...i,...o.props?.seo,siteUrl:i?.siteUrl},compilationErrors:this.compilationErrors},lastModified:s||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,t){if(!e?.length)return;const s=typeof e[0]=="string"?e.join(""):z(e);s&&(t==="head"?this.ssr.headTags.push(s):t==="preBody"?this.ssr.preBodyTags.push(s):this.ssr.postBodyTags.push(s))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.routeAliases.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};#p(){const e=[];for(const[s,r]of Object.entries(A))switch(r){case"map":{const o=Array.from(this[s].entries());e.push([s,o]);break}case"object":e.push([s,this[s]]);break;default:throw new Error("Invalid format")}const t=Object.fromEntries(e);return t[T]=q.PLAN_GATES,t}static#g(e,t){const s=new w(t);for(const[o,a]of Object.entries(A))switch(a){case"map":s[o]=new Map(e[o]);break;case"object":s[o]=e[o];break;default:throw new Error("Invalid format")}const r=e[T];return r&&J("PLAN_GATES",r),s}async writeServerFiles(){$(this.serverOutDir),D(g(this.serverOutDir,b),JSON.stringify(this.#p())),D(g(this.serverOutDir,O),JSON.stringify(await this.getConfigWithEnvPlaceholders()))}static async fromServerFiles(e){const t=g(e.serverOutDir,O),{config:s,env:r}=oe(JSON.parse(await R(t,"utf8")));s[y]=de(s[y]);const o=JSON.parse(await R(g(e.serverOutDir,b),"utf8")),a=w.#g(o,e);a.config=s;const c=Object.fromEntries(Object.entries(r).filter(([i])=>K(i)));return a.configFile={path:t,env:c,config:{...s}},a}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const t in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[t],r=t.split(":"),o=r.pop(),{error:a,value:c}=v(e,r);if(a||!_(c)&&!Array.isArray(c)){await C.panicOnBuild(`Failed to replace env var with env name for ${t}`);continue}c[o]=s}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(s=>!le.includes(s));if(e.length===0)return;const t=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await C.panicOnBuildContentError(t)}}function de(M){return N(M,e=>k.Ast.fromJSON(JSON.stringify(e)))}export{w as Store,We as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
1
+ import T from"@redocly/markdoc";import{writeFileSync as w}from"node:fs";import{readFile as R}from"node:fs/promises";import{join as g}from"node:path";import{parseAndResolveMarkdoc as M}from"./plugins/markdown/compiler.js";import{getPathnameForLocale as k}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as m}from"../constants/common.js";import{DEFAULT_TITLE as F,MARKDOC_PARTIALS_DATA_KEY as y,MARKDOC_PARTIALS_DEPS_KEY as L}from"./constants/common.js";import{isObject as H}from"../utils/guards/is-object.js";import{mapObject as N}from"../utils/object/map-object.js";import{getValueDeep as S}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as G}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as d}from"../utils/path/normalize-route-slug.js";import{isLocalLink as v}from"../utils/path/is-local-link.js";import{reporter as E}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as _}from"./utils/crypto/sha1.js";import{FileNotFoundError as B}from"./utils/fs.js";import{resolveAssetPath as I}from"./utils/resolve-asset-path.js";import{envConfig as j,setEnv as V}from"./config/env-config.js";import{KvService as q}from"./persistence/kv/services/kv-service.js";import{SandboxContext as J}from"./utils/sandbox-context.js";import{isAllowedEnv as U}from"./utils/envs/get-api-route-allowed-env-variables.js";import{ensureDir as x,writeSharedData as K}from"./utils/index.js";import{renderComponents as $}from"./ssr/render.js";import{readStaticData as W,writeStaticData as z}from"./utils/static-data.js";import{getMarkdocOptions as Y}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as Z}from"./entitlements/entitlements-provider.js";import{getPlanDeniedMarkdocTags as Q}from"./entitlements/plan-denied-markdoc-tags.js";import{isRouteReserved as X}from"./plugins/get-reserved-routes.js";import{isL10nPath as ee}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as te}from"./utils/globs.js";import{createDefaultStoreConfig as se,resolveConfigEntries as re,resolveStoreConfig as oe}from"./store-config.js";import{findRedirect as ae}from"./utils/redirects/find-redirect.js";import{followRedirectChain as ie}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as ne}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as le}from"../cli/telemetry/helpers/trace-step.js";const P={routesBySlug:"map",staticFilePaths:"object",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map",devLogin:"object"},C="store.json",A="store-config.json",b="PLAN_GATES",ce=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],We="userDefinedApiFunctions";class D{routesBySlug=new Map;routeAliases=new Map;staticFilePaths={};replacedEnvVars={};unsetEnvVars=new Set;lifecycleContext;newRoutes=[];#t={};routesByFsPath=new Map;apiRoutes=[];middleware=[];routesSharedData=new Map;sharedDataDeps=new Map;sharedDataMarkdocComponents=new Map;routesDynamicComponents=new Map;routesPartials=new Map;ssr={preBodyTags:[],postBodyTags:[],headTags:[]};searchFacets=new Map;searchEngine;templates=new Map;browserPlugins=new Set;apiRoutesRequestHandlers=new Map;mcpToolHandlers=new Map;skills=new Map;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};devLogin=!1;#a=void 0;#i={};config=se();configFile;#n;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#l;userCodeReady;#s=Promise.resolve();#c;#d=Promise.resolve();#h;#u=Promise.resolve();#f;#e=!1;#r=0;#p=0;#o=new Map;constructor({outdir:e,contentDir:t,serverMode:s=!1,serverOutDir:r}){this.#n=t,this.outdir=e,this.serverMode=s,this.serverOutDir=r,J.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(o=>{this.#l=o})}on(e,t){const s=this.listeners.get(e);s?s.add(t):this.listeners.set(e,new Set([t]))}queueEvent=(e,t,...s)=>{this.#o.set(e+String(t),[e,t,...s])};runListeners=(e,t,...s)=>{for(const r of this.listeners.get(e)||new Set)t?r(t,...s):r(...s)};startPluginsRun(){this.clear(),this.#s=new Promise(e=>{this.#c=e})}waitForPluginsLifecycle(){return Promise.all([this.#s,this.#d,this.#u])}waitForPluginsRun(){return this.#s}finishPluginsRun(){this.#c?.();for(const e of this.#o.values())this.runListeners(...e);this.#o.clear()}startEsbuildRun(){this.#d=new Promise(e=>{this.#h=e})}finishEsbuildRun(){this.#h?.()}markRequestHandlersEntryOutdated(){this.#r++,!this.#e&&(this.#e=!0,this.#u=new Promise(e=>{this.#f=e}))}noteRequestHandlersEntryBuildStart(){this.#p=this.#r}markRequestHandlersEntryUpdated(){this.#e&&(this.#r>this.#p||(this.#e=!1,this.#f?.()))}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#n}markUserCodeReady(){this.#l?.(!0)}async reloadMarkdocOptions(){await le("com.redocly.build.reloadMarkdocOptions",async()=>{const{userTagNames:e,...t}=await Y(this.serverOutDir),s=Q(e),r=Object.fromEntries(Object.entries(t.tags).filter(([o])=>!(o in s)));this.#a={...t,tags:r},this.#i=s})}get markdocOptions(){return{...this.#a,partials:this.getGlobalConfig(y),themeConfig:this.config.markdown,planDeniedTags:this.#i}}setGlobalData=e=>{const t=this.globalData,s={...this.globalData,...e};this.globalData=s,JSON.stringify(s)!==JSON.stringify(t)&&this.queueEvent("global-data-updated",void 0,s)};getGlobalData=()=>this.globalData;getKv=async()=>q.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:t,deps:s,resource:r})=>{const{data:{info:o,ast:a},compoundHash:l}=await M(e,this.markdocOptions,{actions:this,context:t},r);for(const i of o.sharedDataDeps||[]){for(const n of s?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of s?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of o.dynamicMarkdocComponents||[]){for(const n of s?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of s?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(s?.routeSlugs&&o.partials?.length)for(const i of s.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of o.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:o,ast:a,compoundHash:l}};async loadApiDocuments(e){return(await e.cache.load(".","api-docs")).data}setSearchEngine(e){this.searchEngine=e}setSearchFacets=e=>{this.searchFacets=e};setStaticFilePaths=e=>{this.staticFilePaths=e};setGlobalConfig=e=>{const t=Object.keys(e);for(const a of t)for(const l in this.replacedEnvVars)if(l===a||l.startsWith(`${a}:`)){const i=l.split(":"),{error:n,value:c}=S(e,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{config:s,unsetEnvVars:r,replacedValues:o}=re(e);for(const a of r)this.unsetEnvVars.add(a);Object.assign(this.replacedEnvVars,o),Object.assign(this.config,s)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,t,s={})=>{if(!Z.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const a=d(e).toLowerCase();this.config.redirects[a]=t;const{trackOriginalSource:l=!0}=s,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(a)&&i.push(a),a.endsWith("*")&&ne(this.config.wildcardRedirectsTree,a)};getRedirect=e=>{const t=d(e).toLowerCase(),s=ae(t,this.config.redirects,this.config.wildcardRedirectsTree,this.staticFilePaths);if(!s)return null;if(v(s.to)){const r=d(s.to).toLowerCase();if(!r.endsWith("*")&&ie(r,[t],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:s.to,type:s.type}};createSharedData=async(e,t,s)=>{if(s&&this.#t[e]===s)return e;const r=JSON.stringify(t),o=s??_(r);return this.#t[e]===o||(this.#t[e]=o,await K(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,t,s)=>{const r=G(e),o=this.routesSharedData.get(r)||{};o[t]=s,this.routesSharedData.set(r,o),u.verbose(`Adding shared data to ${e}, ${t}, ${s}`)};getRouteSharedDataByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.routesSharedData.get(t)||{}:{}};getPartialsForRoute=e=>{const t=this.getGlobalConfig(y)||{},s=this.routesPartials.get(e);if(!s||s.length===0)return{};const r=this.getGlobalConfig(L)||{},o=new Set(s),a=Array.from(s);for(let i=0;i<a.length;i++){const n=a[i],c=r[n]?.partials??[];for(const h of c)o.has(h)||(o.add(h),a.push(h))}const l={};for(const i of o)t[i]&&(l[i]=t[i]);return l};addRoute=e=>{const s={...te(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:s}),u.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,t,s)=>{const r=[m,...this.lifecycleContext?.fs.localeFolders||[]].map(o=>({code:o,name:o}));for(const o of r){const a=k(e,m,o.code,r);this.addRouteSharedData(a,t,s)}};addApiRoute=e=>{this.apiRoutes.push(e),u.verbose("Created API route %s",e.slug)};addMcpTools=(e,t)=>{for(const s of t){const r=this.mcpToolHandlers.get(s.name);r&&r.importPath!==e&&u.warn('MCP tool "%s" from %s overwrites the tool registered from %s',s.name,e,r.importPath);const o=s.hasAvailabilityGate??(r?.importPath===e?r.hasAvailabilityGate:void 0);this.mcpToolHandlers.set(s.name,{...s,importPath:e,hasAvailabilityGate:o}),u.verbose("Created MCP tool %s",s.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const t of e){const s=this.mcpToolHandlers.get(t);s&&this.mcpToolHandlers.set(t,{...s,hasAvailabilityGate:!0})}};addSkills=e=>{for(const t of e)this.skills.set(t.slug,t),u.verbose("Discovered skill %s",t.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const t of e)this.mcpToolHandlers.delete(t)};addMiddleware=e=>{this.middleware.push(e),u.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,t)=>{this.config.responseHeaders||(this.config.responseHeaders={});const s=new Set(t.map(a=>a.name.toLowerCase())),o=[...(this.config.responseHeaders[e]??[]).filter(a=>!s.has(a.name.toLowerCase())),...t];this.config.responseHeaders[e]=o};getRouteByFsPath=e=>{const t=this.routesByFsPath.get(e);return t?this.getRouteBySlug(t):void 0};getRouteBySlug=(e,t={})=>{const{followRedirect:s=!0}=t,r=this.getRedirect(e);if(s&&r)return this.routesBySlug.get(d(r.to));const o=s?this.routeAliases.get(d(e).toLowerCase()):void 0;return this.routesBySlug.get(o??e)};addRouteAlias=(e,t)=>{this.routeAliases.set(d(e).toLowerCase(),d(t))};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e)||this.routeAliases.has(d(e).toLowerCase())||X(e,this.getConfig()))return!0;const t=this.getRedirect(e);if(!t)return!1;if(!v(t.to))return!0;const s=d(t.to);return this.routesBySlug.has(s)};getRoutesByTemplateId=e=>this.newRoutes.filter(t=>t.templateId===e);getAllRoutesForLocale=(e=m)=>{const t=Array.from(this.routesBySlug.values()),s=e.toLowerCase();return t.filter(r=>e===m?!ee(r.fsPath):r.slug.startsWith(`/${s}`))};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,t)=>(this.templates.set(e,t),e);addBrowserPlugin=e=>{this.browserPlugins.add(e)};copyAsset=async(e,t)=>{const s=this.lifecycleContext?.fs;if(!s)throw new Error(`Cannot copy asset ${e}: the content file system is not ready`);try{const r=await I(e,s,{fromFileRelativePath:t,contentDir:this.contentDir,outdir:this.outdir});if(!r)throw new Error(`Cannot copy asset ${e}`);return r}catch(r){if(r instanceof B)return null;throw r}};createRequestHandler=(e,t)=>(this.apiRoutesRequestHandlers.set(e,t),e);clearRequestHandlersByPrefix=e=>{for(const t of this.apiRoutesRequestHandlers.keys())t.startsWith(e)&&this.apiRoutesRequestHandlers.delete(t)};registerServerPropsGetter=(e,t)=>(this.serverPropsGetters.set(e,t),e);registerPagePropsGetter=(e,t)=>{this.pagePropsGetters.set(e,t)};async writeRouteStaticData(e,t){const s=await this.resolveRouteStaticData(e,t,!1);s&&z(e.slug,s,this.outdir)}async resolveRouteStaticData(e,t,s){if(this.serverMode)return W(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:h,resource:f})=>this.parseMarkdoc({input:c,context:h,deps:{routeSlugs:[e.slug]},resource:f})},o=await e.getStaticData?.(e,r)||{},a=new Set(this.routesDynamicComponents.get(e.slug)),l=this.routesSharedData.get(e.slug)||{};for(const c of Object.values(l)){const h=this.sharedDataMarkdocComponents.get(c);h&&h.forEach(p=>a.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const i=this.getGlobalConfig("seo"),n=o?.frontmatter||{};return{...o,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...o.props,dynamicMarkdocComponents:Array.from(a),metadata:{...o?.props?.metadata,...e.metadata},seo:{title:F,...i,...o.props?.seo,siteUrl:i?.siteUrl},compilationErrors:this.compilationErrors},lastModified:s||!e.fsPath?null:await this.lifecycleContext?.fs.getLastModified(e.fsPath)}}addSsrComponents(e,t){if(!e?.length)return;const s=typeof e[0]=="string"?e.join(""):$(e);s&&(t==="head"?this.ssr.headTags.push(s):t==="preBody"?this.ssr.preBodyTags.push(s):this.ssr.postBodyTags.push(s))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.routeAliases.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};#g(){const e=[];for(const[s,r]of Object.entries(P))switch(r){case"map":{const o=Array.from(this[s].entries());e.push([s,o]);break}case"object":e.push([s,this[s]]);break;default:throw new Error("Invalid format")}const t=Object.fromEntries(e);return t[b]=j.PLAN_GATES,t}static#m(e,t){const s=new D(t);for(const[o,a]of Object.entries(P))switch(a){case"map":s[o]=new Map(e[o]);break;case"object":s[o]=e[o];break;default:throw new Error("Invalid format")}const r=e[b];return r&&V("PLAN_GATES",r),s}async writeServerFiles(){x(this.serverOutDir),w(g(this.serverOutDir,C),JSON.stringify(this.#g())),w(g(this.serverOutDir,A),JSON.stringify(await this.getConfigWithEnvPlaceholders()))}static async fromServerFiles(e){const t=g(e.serverOutDir,A),{config:s,env:r}=oe(JSON.parse(await R(t,"utf8")));s[y]=de(s[y]);const o=JSON.parse(await R(g(e.serverOutDir,C),"utf8")),a=D.#m(o,e);a.config=s;const l=Object.fromEntries(Object.entries(r).filter(([i])=>U(i)));return a.configFile={path:t,env:l,config:{...s}},a}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const t in this.replacedEnvVars){const{original:s}=this.replacedEnvVars[t],r=t.split(":"),o=r.pop(),{error:a,value:l}=S(e,r);if(a||!H(l)&&!Array.isArray(l)){await E.panicOnBuild(`Failed to replace env var with env name for ${t}`);continue}l[o]=s}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(s=>!ce.includes(s));if(e.length===0)return;const t=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await E.panicOnBuildContentError(t)}}function de(O){return N(O,e=>T.Ast.fromJSON(JSON.stringify(e)))}export{D as Store,We as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
@@ -31,6 +31,8 @@ export type ResolveItemsOptions = {
31
31
  };
32
32
  export type MarkdocOptions = Partial<Omit<MarkdocConfigProps, 'relativePath'>> & {
33
33
  themeConfig?: RedoclyConfig['markdown'];
34
+ /** The tags the project's plan lacks, each with the message a page shows in place of the tag. */
35
+ planDeniedTags?: Record<string, string>;
34
36
  };
35
37
  export type GetStaticDataContext = {
36
38
  getRouteByFsPath: (relativePath: string) => PageRouteDetails<PageStaticData, PageProps> | undefined;
@@ -46,6 +46,10 @@ export type PlanGates = {
46
46
  [FEATURE.sdkGeneration]: boolean;
47
47
  /** Absent at runtime from legacy tokens, which keep every npm package. */
48
48
  [FEATURE.customPackages]: boolean;
49
+ /** Absent at runtime from tokens signed before the claim, which keep the project's Markdoc tags. */
50
+ [FEATURE.customMarkdocTags]: boolean;
51
+ /** Absent at runtime from tokens signed before the claim, which keep the tools in `@mcp` folders. */
52
+ [FEATURE.customMcpTools]: boolean;
49
53
  /** The new-pricing tier of the order; `null` or absent for legacy orders. */
50
54
  pricingTier?: PricingTier | null;
51
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/reef",
3
- "version": "0.141.0-next.1",
3
+ "version": "0.141.0-next.3",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,14 +33,14 @@
33
33
  "@opentelemetry/sdk-trace-web": "2.8.0",
34
34
  "@opentelemetry/semantic-conventions": "1.40.0",
35
35
  "@redocly/ajv": "8.18.0",
36
- "@redocly/api-docs": "0.6.0-next.1",
37
- "@redocly/config": "0.72.1",
36
+ "@redocly/api-docs": "0.6.0-next.3",
37
+ "@redocly/config": "0.73.0",
38
38
  "@redocly/markdoc": "0.7.0-beta.2",
39
- "@redocly/openapi-core": "2.73.0",
39
+ "@redocly/openapi-core": "2.75.0",
40
40
  "@redocly/portal-legacy-ui": "0.19.0",
41
- "@redocly/portal-plugin-mock-server": "0.25.0",
41
+ "@redocly/portal-plugin-mock-server": "0.26.0-next.0",
42
42
  "@redocly/realm-asyncapi-sdk": "0.17.0",
43
- "@redocly/theme": "0.73.0-next.0",
43
+ "@redocly/theme": "0.73.0-next.1",
44
44
  "@shikijs/transformers": "3.21.0",
45
45
  "@tanstack/react-query": "5.62.3",
46
46
  "@tanstack/react-table": "8.21.3",