@redocly/redoc-reef 0.140.0-next.6 → 0.140.0-next.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/dist/api-schemas/mcp-fetch-count.d.ts +2 -18
- package/dist/api-schemas/otel-traces.d.ts +7 -1345
- package/dist/api-schemas/otel-traces.js +1 -1
- package/dist/api-schemas/search-facets.d.ts +3 -31
- package/dist/api-schemas/search.d.ts +6 -52
- package/dist/cli/build/index.js +1 -1
- package/dist/cli/eject/resolveEjectParams.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.d.ts +2 -0
- package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.js +1 -1
- package/dist/client/app/useGlobalData.d.ts +1 -1
- package/dist/client/providers/post-message/use-post-message.d.ts +1 -1
- package/dist/compiled/@redocly/pii/index.mjs +1 -0
- package/dist/compiled/@redocly/pii/package.json +1 -1
- package/dist/markdoc/tags/openapi-code-sample.js +1 -1
- package/dist/server/api-routes/execute-api-route.js +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/config/env-config.d.ts +26 -24
- package/dist/server/config/env-schema.d.ts +87 -326
- package/dist/server/config/env-schemas/api-urls.d.ts +2 -14
- package/dist/server/config/env-schemas/auth.d.ts +10 -32
- package/dist/server/config/env-schemas/catalog.d.ts +6 -9
- package/dist/server/config/env-schemas/database.d.ts +2 -8
- package/dist/server/config/env-schemas/environment-detection.d.ts +20 -18
- package/dist/server/config/env-schemas/feature-flags.d.ts +29 -33
- package/dist/server/config/env-schemas/feature-flags.js +1 -1
- package/dist/server/config/env-schemas/organization-project.d.ts +3 -21
- package/dist/server/config/env-schemas/scorecards.d.ts +2 -6
- package/dist/server/config/env-schemas/search.d.ts +9 -15
- package/dist/server/config/env-schemas/server-config.d.ts +6 -31
- package/dist/server/config/env-schemas/site.d.ts +1 -5
- package/dist/server/config/env-schemas/ssr.d.ts +7 -12
- package/dist/server/config/env-schemas/telemetry.d.ts +1 -7
- package/dist/server/esbuild/plugins/themes-resolver.js +3 -3
- package/dist/server/external-plugins/resolve-external-plugins.js +1 -1
- package/dist/server/node-bundle-entry.js +1 -1
- package/dist/server/plugins/api-docs/definition-access.d.ts +22 -0
- package/dist/server/plugins/api-docs/definition-access.js +1 -0
- package/dist/server/plugins/api-docs/index.js +1 -1
- package/dist/server/plugins/api-docs/options.js +1 -1
- package/dist/server/plugins/api-docs/spec-download.api.js +1 -1
- package/dist/server/plugins/config-parser/index.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-openapi-code-samples.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +1 -3
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/errors.d.ts +0 -5
- package/dist/server/plugins/mcp/handlers/errors.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/servers/mcp-server.js +2 -2
- package/dist/server/plugins/mcp/types.d.ts +10 -0
- package/dist/server/plugins/mcp/utils/available-tools.d.ts +5 -0
- package/dist/server/plugins/mcp/utils/available-tools.js +1 -0
- package/dist/server/plugins/mcp/workers/worker-context.d.ts +4 -0
- package/dist/server/plugins/mcp/workers/worker-context.js +1 -0
- package/dist/server/plugins/scorecard-classic/template/Grid/GridHeader.js +3 -3
- package/dist/server/store-config.d.ts +33 -0
- package/dist/server/store-config.js +1 -0
- package/dist/server/store.d.ts +10 -15
- package/dist/server/store.js +1 -1
- package/dist/server/tools/notifiers/formatter.js +1 -1
- package/dist/server/tools/notifiers/helpers/colors.d.ts +1 -1
- package/dist/server/types/plugins/api-routes.d.ts +4 -1
- package/dist/server/utils/envs/env-boolean-string.d.ts +9 -3
- package/dist/server/utils/envs/get-api-route-allowed-env-variables.d.ts +2 -0
- package/dist/server/utils/envs/get-api-route-allowed-env-variables.js +1 -1
- package/dist/server/utils/envs/interpolate-env-variables.d.ts +5 -1
- package/dist/server/utils/envs/interpolate-env-variables.js +1 -1
- package/dist/server/utils/envs/load-env-variables.js +1 -1
- package/dist/server/utils/envs/replace-env-variables-deep.d.ts +17 -9
- package/dist/server/utils/envs/replace-env-variables-deep.js +1 -1
- package/dist/server/utils/rbac.d.ts +2 -1
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/web-server/middleware/jsonValidatorMiddleware.d.ts +5 -325
- package/dist/server/workers/mcp-tool-worker-methods.d.ts +7 -0
- package/dist/server/workers/mcp-tool-worker-methods.js +1 -0
- package/dist/server/workers/mcp-tool-worker-pool.d.ts +0 -1
- package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
- package/dist/server/workers/mcp-tool-worker.js +1 -1
- package/dist/server/workers/types.d.ts +4 -8
- package/dist/server/workers/worker-config.d.ts +33 -0
- package/dist/server/workers/worker-config.js +1 -0
- package/package.json +8 -8
- package/dist/compiled/@redocly/pii/index.js +0 -1
- package/dist/server/plugins/mcp/utils/available-sandbox-tools.d.ts +0 -4
- package/dist/server/plugins/mcp/utils/available-sandbox-tools.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withPathPrefix as g}from"@redocly/theme/core/utils";import{importApiRoutesHandler as h}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as D}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as E}from"../../../persistence/kv/services/kv-service.js";import{envConfig as l}from"../../../config/env-config.js";import{acceptsHtml as R}from"../../../utils/ai-agent-detection.js";import{handleErrorPageRender as T}from"../../../web-server/utils.js";import{MCP_DOCS_SERVER_HANDLER_ID as _,MCP_NOT_ALLOWED_TEMPLATE_ID as w}from"../../../constants/mcp.js";import{resolvePublicBaseUrl as S}from"../../../web-server/utils/resolve-public-base-url.js";import{getForwardedOrigin as q}from"../../../web-server/utils/get-request-origin.js";import{applyEdgeRateLimit as C}from"../gateway-mcp/rate-limit/request-limiter/apply-edge-rate-limit.js";import{fetchCountSecret as O}from"../gateway-mcp/rate-limit/fetch-limiter/fetch-count-secret.js";async function
|
|
1
|
+
import{withPathPrefix as g}from"@redocly/theme/core/utils";import{importApiRoutesHandler as h}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as D}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as E}from"../../../persistence/kv/services/kv-service.js";import{envConfig as l}from"../../../config/env-config.js";import{acceptsHtml as R}from"../../../utils/ai-agent-detection.js";import{handleErrorPageRender as T}from"../../../web-server/utils.js";import{MCP_DOCS_SERVER_HANDLER_ID as _,MCP_NOT_ALLOWED_TEMPLATE_ID as w}from"../../../constants/mcp.js";import{resolvePublicBaseUrl as S}from"../../../web-server/utils/resolve-public-base-url.js";import{getForwardedOrigin as q}from"../../../web-server/utils/get-request-origin.js";import{applyEdgeRateLimit as C}from"../gateway-mcp/rate-limit/request-limiter/apply-edge-rate-limit.js";import{fetchCountSecret as O}from"../gateway-mcp/rate-limit/fetch-limiter/fetch-count-secret.js";async function K(i,t,e){const n=t.req.raw;if(i.requestHandlerId===_&&n.method==="GET"&&R(n.headers.get("accept"))&&e.globalData.mcpData?.docs?.enabled)return T(t,e,{slug:i.slug},405,w);const r=t.get("auth"),o=await C(n,e);if(o)return o;const s=await e.resolveRouteStaticData(i)||{},c=g(i.slug),{requestHandlers:m}=await h(e.serverOutDir),p=m[i.requestHandlerId],d=(await p()).default,u=async()=>await E.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:l.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:l.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),f=D({honoCtx:t,ctx:{user:{teams:r.teams,email:r.claims.email,claims:r.claims,idpAccessToken:r.idpAccessToken,idpId:r.claims.idpId,isAuthenticated:r.isAuthenticated},config:e.config,outdir:e.outdir,baseUrl:q(t.req.raw)},telemetry:A,getKv:u}),a=await d(t.req.raw,f,{...s,props:{...s.props,routeSlug:c,outdir:e.outdir,fetchCountSecret:O(),skills:e.config.skills?.hide===!0?[]:e.getSkills(),skillsBaseUrl:S(e,t),configFile:e.configFile}});return a instanceof Response?a:typeof a=="string"?new Response(a,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(a),{headers:{"Content-Type":"application/json"}})}export{K as handleMcpRequest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{secretStore as d}from"../gateway-mcp/secret-store.js";import{rejectCredential as _}from"../gateway-mcp/credential-validation.js";import{buildAllowedHostMatchers as
|
|
1
|
+
import{readRequestBody as C}from"@modelcontextprotocol/server";import{secretStore as d}from"../gateway-mcp/secret-store.js";import{rejectCredential as _}from"../gateway-mcp/credential-validation.js";import{buildAllowedHostMatchers as T}from"../gateway-mcp/fetch/allowed-hosts.js";import{assertUrlAllowed as A}from"../gateway-mcp/fetch/ssrf-guard.js";import{readCappedBody as R,getDefaultAgent as P}from"../gateway-mcp/fetch/fetch-bridge.js";import{logger as x}from"../../../tools/notifiers/logger.js";import{FORM_ACTIONS as k}from"./credentials-page/constants.js";import{credentialSchemesOf as w,schemeFieldName as f}from"./credentials-page/form-contract.js";import{formPage as O}from"./credentials-page/form-page.js";import{htmlDocument as N}from"./credentials-page/layout.js";import{declinedPage as I,expiredPage as j,outcomePage as D}from"./credentials-page/outcome-pages.js";const $={"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","X-Frame-Options":"DENY","Referrer-Policy":"no-referrer","Content-Security-Policy":"default-src 'none'; style-src 'unsafe-inline'; img-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'"},M=3e4,B=64*1024,F=64*1024,U=/^bearer\s+/i,X=/^\d+$/,H=async(e,t,o)=>{const n=await t.getKv(),r=J(e,t.baseUrl,o);if(e.method==="GET"){const i=new URL(e.url).searchParams.get("token")??"",a=await d.peekElicitation(n,i);return a?E({kv:n,site:r,token:i,target:a},{},200):p(r)}if(e.method==="POST"){const i=await C(e,F);if(i.tooLarge)return new Response("Payload Too Large",{status:413});const a=await new Response(i.text,{headers:{"Content-Type":e.headers.get("content-type")??""}}).formData(),c=u(a,"token"),s=await d.peekElicitation(n,c);if(!s)return p(r);const l={kv:n,site:r,token:c,target:s,form:a};switch(u(a,"action")){case k.remove:return b(l,K(s,u(a,"scheme")));case k.removeAll:return b(l,w(s));case k.decline:return Y(l);default:return L(l)}}return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, POST"}})};async function L(e){const{target:t,form:o}=e,n=w(t),r=n.map((s,l)=>u(o,f("client_id",l)).trim()),i=s=>E(e,{error:s,clientIds:r},400),a=G(n,o);if("error"in a)return i(a.error);if(a.writes.length===0)return i(z(n));const c=[];for(const s of a.writes){if(s.kind!=="exchange"){c.push(s);continue}const l=await W(s.auth,s.clientId,s.clientSecret);if(!l.ok)return x.warn(`gateway oauth2 client_credentials exchange failed for ${t.api}: ${l.reason}`),i(y(n,s.schemeIndex,"client_id","We could not exchange those client credentials for a token. Check the client ID and secret, then try again."));c.push({kind:"set",scheme:s.scheme,secret:l.secret})}return v(e,c)}function G(e,t){const o=[];for(const[n,r]of e.entries()){const i=u(t,f("secret",n)).trim();if(i){const s=_(r.auth,i);if(s)return{error:y(e,n,"secret",s)};o.push({kind:"set",scheme:r.name,secret:Q(r.auth,i)});continue}if(r.auth.kind!=="oauth2ClientCredentials")continue;const a=u(t,f("client_id",n)).trim(),c=u(t,f("client_secret",n)).trim();if(a&&c)o.push({kind:"exchange",scheme:r.name,schemeIndex:n,auth:r.auth,clientId:a,clientSecret:c});else if(a||c)return{error:y(e,n,a?"client_secret":"client_id","Enter both the client ID and the client secret, or leave both blank.")}}return{writes:o}}function z(e){return e.length>1?{message:"Fill in at least one credential before saving."}:{message:e[0].auth.kind==="oauth2ClientCredentials"?"Enter an access token, or the client ID and the client secret, before saving.":"Enter a value before saving.",schemeIndex:0,field:"secret"}}function y(e,t,o,n){return{message:e.length>1?`${e[t].name}: ${n}`:n,schemeIndex:t,field:o}}async function b(e,t){const{kv:o,target:n}=e,r=await d.getStoredSchemes(o,n.subject,n.api),i=t.filter(a=>r[a.name]).map(a=>({kind:"remove",scheme:a.name}));return i.length===0?E(e,{error:{message:"No credential is stored there, so there is nothing to remove."}},400):v(e,i)}function K(e,t){const o=X.test(t)?w(e)[Number(t)]:void 0;return o?[o]:[]}async function Y({kv:e,site:t,token:o}){return await d.consumeElicitation(e,o)?h(t,I(),200):p(t)}async function v({kv:e,site:t,token:o},n){const r=await d.consumeElicitation(e,o);if(!r)return p(t);for(const c of n)c.kind==="remove"?await d.deleteSecret(e,r.subject,r.api,c.scheme):await d.setSecret(e,r.subject,r.api,c.scheme,c.secret);const i=await d.getStoredSchemes(e,r.subject,r.api),a={action:n.some(c=>c.kind==="set")?"saved":"removed",schemes:n.map(c=>c.scheme),stored:Object.keys(i).sort()};return h(t,D(r,a),200)}async function E({kv:e,site:t,token:o,target:n},r,i){const a=await d.getStoredSchemes(e,n.subject,n.api);return h(t,O({site:t,target:n,token:o,stored:a,...r}),i)}function J(e,t,o){const n=o?.props?.branding??{},r=t&&URL.canParse(t)?t:e.url;return{...n,host:new URL(r).host}}async function W(e,t,o){try{const n=T([{url:e.tokenUrl}]),r=A(e.tokenUrl,n),i=new AbortController,a=setTimeout(()=>i.abort(),M);let c;try{c=await fetch(r,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"client_credentials",client_id:t,client_secret:o}),redirect:"manual",signal:i.signal,dispatcher:P()})}finally{clearTimeout(a)}if(!c.ok)return m(`token endpoint returned ${c.status}`);let s;try{s=await R(c,B)}catch{return m("token response exceeded the size cap")}let l;try{l=JSON.parse(s)}catch{return m("token response was not valid JSON")}const S=typeof l=="object"&&l!==null&&"access_token"in l?l.access_token:void 0,g=typeof S=="string"?S.trim():"";return g?_(e,g)?m("token response had an access_token that cannot be sent in a header"):{ok:!0,secret:{header:"Authorization",value:`Bearer ${g}`}}:m("token response had no access_token")}catch(n){return m(n instanceof Error?n.message:String(n))}}function m(e){return{ok:!1,reason:e}}function u(e,t){const o=e.get(t);return typeof o=="string"?o:""}function h(e,t,o){return new Response(N(t,e.colorScheme),{status:o,headers:$})}function p(e){return h(e,j(),404)}function Q(e,t){return e.kind==="apiKey"?{header:e.header,value:t}:e.kind==="cookie"?{header:"Cookie",value:`${e.name}=${t}`}:e.kind==="bearer"||e.kind==="oauth2ClientCredentials"?{header:"Authorization",value:V(t)}:{header:"Authorization",value:t}}function V(e){return`Bearer ${e.replace(U,"")}`}var de=H;export{de as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as C,MANAGE_API_CREDENTIALS_TOOL_NAME as k,SUBMIT_FEEDBACK_TOOL_NAME as S}from"../constants.js";import{isAnonymousSessionToolAvailable as U}from"../docs-mcp/tools/core/create-anonymous-session.js";import{isManageApiCredentialsToolAvailable as w,manageApiCredentials as y,manageApiCredentialsSchema as H}from"../codemode/tools/manage-credentials.js";import{EXECUTE_TOOL_SCHEMA as h,executeToolTitle as I}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as R,CODE_MODE_TOOL_NAMES as M,FETCH_TOOL_NAME as B}from"../codemode/constants.js";import{buildCodeModeInstructions as F,buildExecuteDescription as x}from"../codemode/prompts.js";import{toToolListEntries as z}from"../codemode/build-tool-list.js";import{composeExecuteAnnotations as X,getActiveCapabilities as Y}from"../codemode/capabilities/index.js";import{describeToolsSchema as j,describeTools as G}from"../codemode/tools/describe-tools.js";import{availableTools as g}from"../utils/available-tools.js";import{resolveDocsSiteUrl as K}from"../utils/docs-site-url.js";import{isToolDisabledByCaller as b}from"../utils/disabled-tools.js";import{toRegisterToolConfig as N}from"../utils/tool-registration.js";import{createMcpServer as P,createToolDispatch as W,extractSerializableContext as q}from"./mcp-server.js";const J=new Set([...M].filter(s=>s!==S));function D(s,t){const e=t.schema;if(s)return e;const{sessionHandle:u,...T}=e.properties;return{...e,properties:T}}function Q(s){return Object.fromEntries(s.map(t=>[t.name,t.schema]))}async function pe({name:s,tools:t,context:e,skills:u=[],getKv:T}){const l=q(e),n=e.mcpMode==="code",c=n?Y(e):[],O=c.some(o=>o.id===B),m=n?await g(t.filter(o=>!M.has(o.name)),l):[],_=z(m,c),E=U(e)&&!b(C,e.metadata),v=n&&w(e)&&!b(k,e.metadata),p=P(s,n?F(O,_):void 0),A={getClientCapabilities:()=>p.server.getClientCapabilities(),getKv:T},f=W(n?{...l,sandboxToolSchemas:Q(m)}:l,A);if(n){const o=X(m,c,e.config?.mcp),r=[{tool:{...h,title:I(o),description:x(O,_,K(e.config?.seo?.siteUrl,e.baseUrl)),schema:D(E,h),annotations:o},callback:f(R)},{tool:j(m,c),callback:G(m,c,e)}],i=t.find(a=>a.name===S);i&&!b(i.name,e.metadata)&&r.push({tool:i,callback:f(i.name)});const d=t.find(a=>a.name===C);if(d&&E&&r.push({tool:d,callback:f(d.name)}),v){const a=H(e);r.push({tool:{...a,schema:D(E,a)},callback:y(l,A)})}for(const{tool:a,callback:L}of r)p.registerTool(a.name,N(a),L)}else{const o=t.filter(i=>!J.has(i.name)),r=new Set((await g(o,l)).map(i=>i.name));for(const i of o){const d=p.registerTool(i.name,N({...i,outputSchema:void 0}),f(i.name));r.has(i.name)||d.disable()}}for(const o of u)p.registerResource(o.slug,o.uri,{title:o.name,description:o.description,mimeType:"text/markdown"},async()=>({contents:[{uri:o.uri,mimeType:"text/markdown",text:o.content}]}));return p}export{pe as createDocsMcpServer};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{McpServer as C}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as U,MCP_TOOL_WORKER_KEY as O}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as L}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as F,stripAuthRequiredMeta as k,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{acceptedCredentialsLink as D,buildCredentialsAcceptedHint as K,buildCredentialsToolHint as N,buildUpstreamCredentialFallback as q,buildUpstreamCredentialInputRequired as j,credentialElicitationAnswer as P,dedupeElicitation as v,isStatelessRequest as H,schemeLabelOf as $,supportsUrlElicitation as B}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as y,resolveUpstreamApiAuth as W}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as G,resolveSecretSubject as V}from"../gateway-mcp/subject.js";import{toWorkerContext as X}from"../workers/worker-context.js";const Y=6e4,J=1e4;function de(e,t){return new C({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},maxToolInputElements:J,...t?{instructions:t}:{}})}function me(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,u=H(s.mcpReq),a=i?V(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const c=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await L.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let l;const p=async()=>{l=await c();const m={toolName:r,args:n,context:X({...e,upstreamSecrets:l}),extra:re(s)};return await U.exec(O,[m],{timeout:Y})};let d=await p();const f=F(d);if(f.length>0&&i&&!o)return k(T(d,[{type:"text",text:G}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${u?"2026-07-28":"2025"} clientElicitation=${Q(t)}`);const m=await t.getKv(),h=await Z(e,f),w=f.map(_=>x(_,h)),E=z(l),g=u?await ee(e,s,w,o,m,E,h,t):await te(e,w,o,m,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":d=await p();break;case"prependText":d=T(d,[{type:"text",text:g.text},...d.content]);break;case"none":break}}return k(d)}}function T(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function Q(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function Z(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await W(e,n));return r}function x(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??y};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function z(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function I(e,t){return e.status===401&&!t.has(b(e))}function R(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?$(r.schemes,n):void 0}function M(e,t){return e.map(r=>N(r,R(r,t))).join(`
|
|
2
2
|
|
|
3
|
-
`)}function A(e,t,r,n,
|
|
3
|
+
`)}function A(e,t,r,n,s){const[i,...u]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??y,c=i.schemes&&i.schemes.length>1?i.schemes:void 0,l=c?void 0:R(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...l?{schemeLabel:l}:{},...c?{acceptedSchemes:c}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:u.map(p=>p.name)}}}async function ee(e,t,r,n,s,i,u,a){const o=P(t.mcpReq.inputResponses);if(o==="declined")return{kind:"none"};const c=r.filter(p=>I(p,i));if(c.length===0)return{kind:"prependText",text:M(r,u)};if(o==="accepted"){const p=await D(t.mcpReq.requestState(),{kv:s,subject:n,baseUrl:e.baseUrl??"",apis:c.map(f=>f.api)}),d=p?.apiName??c[0].name;return{kind:"prependText",text:K(d,p?.url)}}const l=A(e,c,n,s,u);return B(a?.getClientCapabilities())?{kind:"inputRequired",result:await j(l)}:{kind:"prependText",text:await q(l)}}async function te(e,t,r,n,s,i){const u=t.filter(c=>I(c,s));if(u.length===0)return{kind:"prependText",text:M(t,i)};const a=A(e,u,r,n,i);return{kind:"prependText",text:await v(`${r}:${b(u[0])}`,()=>q(a))}}function re(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function fe(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,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,fetchCountRequest:e.fetchCountRequest,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,requestId:e.requestId,messageId:e.messageId,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,configFile:e.configFile,fs:void 0}}export{de as createMcpServer,me as createToolDispatch,fe as extractSerializableContext};
|
|
@@ -6,6 +6,7 @@ import type { McpToolSchema } from '../../types';
|
|
|
6
6
|
import type { Skill } from '../../types/plugins/skills.js';
|
|
7
7
|
import type { UpstreamSecrets } from './gateway-mcp/secret-store.js';
|
|
8
8
|
import type { SiteBranding } from './handlers/credentials-page/types.js';
|
|
9
|
+
import type { StoreConfigFile, WorkerConfig } from '../../workers/worker-config.js';
|
|
9
10
|
type ObjectValues<T> = T[keyof T];
|
|
10
11
|
export type McpServerType = ObjectValues<typeof McpServerType>;
|
|
11
12
|
export type McpErrorCodeTypes = ObjectValues<typeof McpErrorCodes>;
|
|
@@ -40,6 +41,7 @@ export type McpDocsStaticData = PageStaticData & {
|
|
|
40
41
|
tools?: McpToolSchema[];
|
|
41
42
|
skills?: Skill[];
|
|
42
43
|
skillsBaseUrl?: string;
|
|
44
|
+
configFile?: StoreConfigFile;
|
|
43
45
|
};
|
|
44
46
|
};
|
|
45
47
|
export type CredentialsPageStaticData = PageStaticData & {
|
|
@@ -117,6 +119,11 @@ export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | k
|
|
|
117
119
|
internalBaseUrl?: string;
|
|
118
120
|
sandboxToolSchemas?: Record<string, Record<string, unknown>>;
|
|
119
121
|
fs?: McpToolFileSystem;
|
|
122
|
+
configFile?: StoreConfigFile;
|
|
123
|
+
};
|
|
124
|
+
/** `McpToolContext` as it crosses to a worker. */
|
|
125
|
+
export type McpToolWorkerContext = Omit<McpToolContext, 'config' | 'fs' | 'configFile'> & {
|
|
126
|
+
config: WorkerConfig;
|
|
120
127
|
};
|
|
121
128
|
export type McpToolHandler<TArgs extends ToolArgs = ToolArgs> = (args: TArgs, context: McpToolContext, extra: McpToolExtra) => Promise<McpToolWorkerResponse | McpToolJsonValue>;
|
|
122
129
|
export type McpToolIsAvailable = (context: McpToolContext) => boolean | Promise<boolean>;
|
|
@@ -130,6 +137,9 @@ export type McpToolExecutionParams = {
|
|
|
130
137
|
context: McpToolContext;
|
|
131
138
|
extra: McpToolExtra;
|
|
132
139
|
};
|
|
140
|
+
export type McpToolWorkerParams = Omit<McpToolExecutionParams, 'context'> & {
|
|
141
|
+
context: McpToolWorkerContext;
|
|
142
|
+
};
|
|
133
143
|
export type CustomMcpToolsState = {
|
|
134
144
|
registeredToolNames: string[];
|
|
135
145
|
warnedNoOutputSchemaTools: Set<string>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { McpToolSchema } from '../../../types';
|
|
2
|
+
import type { McpToolContext } from '../types.js';
|
|
3
|
+
/** The candidates this request may use. Asks the worker pool only when a candidate is gated. */
|
|
4
|
+
export declare function availableTools(candidates: McpToolSchema[], context: McpToolContext): Promise<McpToolSchema[]>;
|
|
5
|
+
//# sourceMappingURL=available-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{logger as n}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as m,MCP_TOOL_AVAILABILITY_KEY as s}from"../../../workers/mcp-tool-worker-pool.js";import{toWorkerContext as f}from"../workers/worker-context.js";import{isToolDisabledByCaller as p}from"./disabled-tools.js";async function d(o,r){const a=o.filter(t=>!p(t.name,r.metadata)),e=a.filter(t=>t.hasAvailabilityGate).map(t=>t.name);if(e.length===0)return a;let i;try{i=await m.exec(s,[{toolNames:e,context:f(r)}],{timeout:1e4})}catch(t){return l(a,t instanceof Error?t.message:String(t))}return!i||typeof i!="object"?l(a,"the worker returned no availability map"):a.filter(t=>i[t.name]!==!1)}function l(o,r){const a=o.filter(e=>e.hasAvailabilityGate);return n.warn(`MCP tool availability is unknown (${r}); the tool list drops the gated tools: ${a.map(e=>e.name).join(", ")}.`),o.filter(e=>!e.hasAvailabilityGate)}export{d as availableTools};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { McpToolContext, McpToolWorkerContext } from '../types.js';
|
|
2
|
+
export declare function toWorkerContext({ config, configFile, fs: _fs, ...context }: McpToolContext): McpToolWorkerContext;
|
|
3
|
+
export declare function fromWorkerContext(context: McpToolWorkerContext): McpToolContext;
|
|
4
|
+
//# sourceMappingURL=worker-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{readWorkerConfig as f,toWorkerConfig as t}from"../../../workers/worker-config.js";function g({config:o,configFile:r,fs:e,...n}){return{...n,config:t(o,r)}}function c(o){return{...o,config:f(o.config)}}export{c as fromWorkerContext,g as toWorkerContext};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import r from"react";import t from"styled-components";import{flexRender as g}from"@tanstack/react-table";const w=({headerGroups:e,gridTemplateColumns:i,groupHeaderTitle:
|
|
1
|
+
import r from"react";import t from"styled-components";import{flexRender as g}from"@tanstack/react-table";const w=({headerGroups:e,gridTemplateColumns:i,groupHeaderTitle:d})=>r.createElement(p,null,d&&r.createElement(u,{gridTemplateColumns:i,role:"row"},r.createElement(c,{gridColumn:"1",role:"columnheader"}),r.createElement(c,{gridColumn:"2 / -1",role:"columnheader"},r.createElement("span",null,d))),e.map((a,m)=>r.createElement(b,{key:`header-group-${m}`,gridTemplateColumns:i,role:"row"},a.headers.map((o,s)=>{const l=g(o.column.columnDef.header,o.getContext()),n=o.column.getIsSorted();return r.createElement(x,{key:o.id,gridColumn:s+1,$sortable:o.column.getCanSort(),role:"columnheader","aria-sort":n==="asc"?"ascending":n==="desc"?"descending":void 0},o.column.getCanSort()?r.createElement(h,{type:"button",onClick:o.column.getToggleSortingHandler()},l,r.createElement(f,{"aria-hidden":"true"},n?n==="desc"?"\u25BE":"\u25B4":"\u21D5")):l)})))),p=t.div`
|
|
2
2
|
border: 1px solid var(--border-color-primary);
|
|
3
3
|
min-width: 775px;
|
|
4
4
|
`,u=t.div`
|
|
@@ -37,7 +37,7 @@ import r from"react";import t from"styled-components";import{flexRender as g}fro
|
|
|
37
37
|
&:first-child {
|
|
38
38
|
justify-content: flex-start;
|
|
39
39
|
}
|
|
40
|
-
`,
|
|
40
|
+
`,h=t.button`
|
|
41
41
|
display: block;
|
|
42
42
|
width: 100%;
|
|
43
43
|
height: 100%;
|
|
@@ -50,6 +50,6 @@ import r from"react";import t from"styled-components";import{flexRender as g}fro
|
|
|
50
50
|
color: inherit;
|
|
51
51
|
text-align: inherit;
|
|
52
52
|
cursor: pointer;
|
|
53
|
-
`,
|
|
53
|
+
`,f=t.span`
|
|
54
54
|
font-family: monospace;
|
|
55
55
|
`;export{w as GridHeader};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RedoclyConfig } from '@redocly/config';
|
|
2
|
+
import type { WildcardRedirectsTree } from './types';
|
|
3
|
+
import { readEnvVariable } from './utils/envs/read-env-variable.js';
|
|
4
|
+
export type ComputedRedoclyConfig = {
|
|
5
|
+
configFilePath: string;
|
|
6
|
+
linkTags?: string;
|
|
7
|
+
headScriptTags?: string;
|
|
8
|
+
postBodyScriptTags?: string;
|
|
9
|
+
preBodyScriptTags?: string;
|
|
10
|
+
wildcardRedirectsTree: WildcardRedirectsTree;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
};
|
|
13
|
+
export type StoreConfig = WithRequired<RedoclyConfig, 'redirects'> & ComputedRedoclyConfig;
|
|
14
|
+
export declare function createDefaultStoreConfig(): StoreConfig;
|
|
15
|
+
/** Resolves the env placeholders in a copy of `entries` and normalizes `seo.siteUrl`. */
|
|
16
|
+
export declare function resolveConfigEntries(entries: Partial<RedoclyConfig>): {
|
|
17
|
+
config: Partial<RedoclyConfig>;
|
|
18
|
+
unsetEnvVars: string[];
|
|
19
|
+
replacedValues: Record<string, {
|
|
20
|
+
original: string;
|
|
21
|
+
replaced: string;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The store config of a build output: the defaults, overridden by the parsed JSON of its config
|
|
26
|
+
* file, which this changes in place. `env` holds each value that `readEnv` returned: a reader of
|
|
27
|
+
* only these values gives the same config. The partials stay JSON, never `undefined`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveStoreConfig(fileEntries: Partial<RedoclyConfig>, readEnv?: typeof readEnvVariable): {
|
|
30
|
+
config: StoreConfig;
|
|
31
|
+
env: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=store-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{removeTrailingSlash as a}from"../utils/url/remove-trailing-slash.js";import{MARKDOC_PARTIALS_DATA_KEY as c}from"./constants/common.js";import{readEnvVariable as l}from"./utils/envs/read-env-variable.js";import{replaceEnvVariablesDeep as f,replaceEnvVariablesInPlace as u}from"./utils/envs/replace-env-variables-deep.js";function d(){return{configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}}}function S(e){const{resolvedObj:r,unsetEnvVars:o,replacedValues:i}=f(e);return s(r),{config:r,unsetEnvVars:o,replacedValues:i}}function U(e,r=l){const o={};u(e,t=>{const n=r(t);return n!==void 0&&(o[t]=n),n}),s(e);const i={...d(),...e};return i[c]||={},{config:i,env:o}}function s(e){const r=e.seo?.siteUrl?.trim();r&&(e.seo={...e.seo,siteUrl:URL.canParse(r)?new URL(r).origin:a(r)})}export{d as createDefaultStoreConfig,S as resolveConfigEntries,U as resolveStoreConfig};
|
package/dist/server/store.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { type Node } from '@redocly/markdoc';
|
|
2
2
|
import type { JSX } from 'react';
|
|
3
3
|
import type { CommonError, GlobalData } from '../types/index.js';
|
|
4
|
-
import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts,
|
|
4
|
+
import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts, StaticFilePaths, RedirectOptions, McpToolRegistration, McpToolSchema, MarkdocOptions } from './types';
|
|
5
5
|
import type { Skill } from './types/plugins/skills.js';
|
|
6
6
|
import type { RedoclyConfig, RedirectConfig, CompilationError, PageStaticData } from '@redocly/config';
|
|
7
7
|
import type { SearchFacet } from '@redocly/theme/core/types';
|
|
8
8
|
import type { BundledApiDefinition } from './plugins/api-docs/loader.js';
|
|
9
9
|
import type { SearchEngine } from './plugins/search/engines/search-engine.js';
|
|
10
|
+
import type { StoreConfig } from './store-config.js';
|
|
11
|
+
import type { StoreConfigFile } from './workers/worker-config.js';
|
|
10
12
|
import { KvService } from './persistence/kv/services/kv-service.js';
|
|
11
13
|
export declare const USER_DEFINED_API_FUNCTIONS_COUNTER_KEY = "userDefinedApiFunctions";
|
|
12
14
|
type LifecycleEventType = 'global-data-updated' | 'shared-data-updated' | 'routes-updated' | 'build-updated' | 'build-started' | 'errors-updated' | 'pages-updated';
|
|
@@ -16,15 +18,6 @@ export type StoreOptions = {
|
|
|
16
18
|
serverOutDir: string;
|
|
17
19
|
serverMode?: boolean;
|
|
18
20
|
};
|
|
19
|
-
export type ComputedRedoclyConfig = {
|
|
20
|
-
configFilePath: string;
|
|
21
|
-
linkTags?: string;
|
|
22
|
-
headScriptTags?: string;
|
|
23
|
-
postBodyScriptTags?: string;
|
|
24
|
-
preBodyScriptTags?: string;
|
|
25
|
-
wildcardRedirectsTree: WildcardRedirectsTree;
|
|
26
|
-
[key: string]: unknown;
|
|
27
|
-
};
|
|
28
21
|
export declare class Store {
|
|
29
22
|
#private;
|
|
30
23
|
routesBySlug: Map<string, PageRouteDetails>;
|
|
@@ -62,7 +55,9 @@ export declare class Store {
|
|
|
62
55
|
globalData: GlobalData;
|
|
63
56
|
/** Whether `POST /authorize` mints dev sessions: set by `realm develop` (unless `--no-dev-login`) and `realm build --devLogin`. */
|
|
64
57
|
devLogin: boolean;
|
|
65
|
-
config:
|
|
58
|
+
config: StoreConfig;
|
|
59
|
+
/** Set when the store loads from a build output: the workers then read the config from this file. */
|
|
60
|
+
configFile?: StoreConfigFile;
|
|
66
61
|
serverMode: boolean;
|
|
67
62
|
serverOutDir: string;
|
|
68
63
|
outdir: string;
|
|
@@ -157,10 +152,10 @@ export declare class Store {
|
|
|
157
152
|
resolveRouteStaticData(route: RouteDetails, _context?: LifecycleContext, skipLastModified?: boolean): Promise<PageStaticData>;
|
|
158
153
|
addSsrComponents(components: JSX.Element[] | string[], position: 'head' | 'preBody' | 'postBody'): void;
|
|
159
154
|
clear: () => void;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
static
|
|
155
|
+
/** Writes the files that `fromServerFiles` reads. The config file keeps the env placeholders. */
|
|
156
|
+
writeServerFiles(): Promise<void>;
|
|
157
|
+
/** Loads the store from the files of a build output. The config resolves from the current env. */
|
|
158
|
+
static fromServerFiles(options: StoreOptions): Promise<Store>;
|
|
164
159
|
getConfigWithEnvPlaceholders(): Promise<RedoclyConfig>;
|
|
165
160
|
reportUnsetEnvVars(): Promise<void>;
|
|
166
161
|
}
|
package/dist/server/store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import A from"@redocly/markdoc";import{parseAndResolveMarkdoc as T}from"./plugins/markdown/compiler.js";import{getPathnameForLocale as M}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as O,MARKDOC_PARTIALS_DATA_KEY as m,MARKDOC_PARTIALS_DEPS_KEY as k}from"./constants/common.js";import{GATED_MARKDOC_TAGS as R}from"./constants/entitlements.js";import{isObject as L}from"../utils/guards/is-object.js";import{mapObject as H}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as D}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as u}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as h}from"./tools/notifiers/logger.js";import{sha1 as F}from"./utils/crypto/sha1.js";import{envConfig as G,setEnv as _}from"./config/env-config.js";import{KvService as B}from"./persistence/kv/services/kv-service.js";import{SandboxContext as I}from"./utils/sandbox-context.js";import{writeSharedData as N}from"./utils/index.js";import{renderComponents as V}from"./ssr/render.js";import{readStaticData as q,writeStaticData as j}from"./utils/static-data.js";import{getMarkdocOptions as U}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as v}from"./entitlements/entitlements-provider.js";import{isRouteReserved as x}from"./plugins/get-reserved-routes.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as J}from"./utils/globs.js";import{replaceEnvVariablesDeep as W}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as $}from"./utils/redirects/find-redirect.js";import{followRedirectChain as z}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as Y}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as Z}from"../cli/telemetry/helpers/trace-step.js";const E={routesBySlug:"map",staticFilePaths:"object",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map",skills:"map",devLogin:"object"},P="PLAN_GATES",Q=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],ke="userDefinedApiFunctions";class b{routesBySlug=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;#o=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#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;#a=new Map;constructor({outdir:e,contentDir:s,serverMode:t=!1,serverOutDir:r}){this.#i=s,this.outdir=e,this.serverMode=t,this.serverOutDir=r,I.register({serverOutDir:r,readRoots:[e,process.cwd()]}),this.userCodeReady=new Promise(a=>{this.#n=a})}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.#a.set(e+String(s),[e,s,...t])};runListeners=(e,s,...t)=>{for(const r of this.listeners.get(e)||new Set)s?r(s,...t):r(...t)};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.#a.values())this.runListeners(...e);this.#a.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 Z("com.redocly.build.reloadMarkdocOptions",async()=>{const e=v.instance(),s=await U(this.serverOutDir),t=Object.fromEntries(Object.entries(s.tags).filter(([r])=>R[r]!=null?e.canAccessFeature(R[r]):!0));this.#o={...s,tags:t}})}get markdocOptions(){return{...this.#o,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()=>B.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:e,context:s,deps:t,resource:r})=>{const{data:{info:a,ast:i},compoundHash:l}=await T(e,this.markdocOptions,{actions:this,context:s},r);for(const o of a.sharedDataDeps||[]){for(const n of t?.routeSlugs||[])this.addRouteSharedData(n,o,o);for(const n of t?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(o),this.sharedDataDeps.set(n,c)}}for(const o of a.dynamicMarkdocComponents||[]){for(const n of t?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(o),this.routesDynamicComponents.set(n,c)}for(const n of t?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(o),this.sharedDataMarkdocComponents.set(n,c)}}if(t?.routeSlugs&&a.partials?.length)for(const o of t.routeSlugs){const n=this.routesPartials.get(o)||[];for(const c of a.partials)n.includes(c)||n.push(c);this.routesPartials.set(o,n)}return{info:a,ast:i,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 s=Object.keys(e);for(const l of s)for(const o in this.replacedEnvVars)if(o===l||o.startsWith(`${l}:`)){const n=o.split(":"),{error:c,value:d}=y(e,n);(c||d!==this.replacedEnvVars[o].replaced)&&delete this.replacedEnvVars[o]}const{resolvedObj:t,unsetEnvVars:r,replacedValues:a}=W(e);for(const l of r)this.unsetEnvVars.add(l);Object.assign(this.replacedEnvVars,a);const i=t.seo?.siteUrl?.trim();i&&(t.seo={...t.seo,siteUrl:URL.canParse(i)?new URL(i).origin:D(i)}),Object.assign(this.config,t)};getConfig=()=>this.config;getGlobalConfig=e=>this.config[e];getSearchFacets=()=>this.searchFacets;addRedirect=(e,s,t={})=>{if(!v.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const i=u(e).toLowerCase();this.config.redirects[i]=s;const{trackOriginalSource:l=!0}=t,o=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(o)&&!o.includes(i)&&o.push(i),i.endsWith("*")&&Y(this.config.wildcardRedirectsTree,i)};getRedirect=e=>{const s=u(e).toLowerCase(),t=$(s,this.config.redirects,this.config.wildcardRedirectsTree,this.staticFilePaths);if(!t)return null;if(S(t.to)){const r=u(t.to).toLowerCase();if(!r.endsWith("*")&&z(r,[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.#t[e]===t)return e;const r=JSON.stringify(s),a=t??F(r);return this.#t[e]===a||(this.#t[e]=a,await N(e,r,this.outdir),this.queueEvent("shared-data-updated",e)),e};addRouteSharedData=(e,s,t)=>{const r=D(e),a=this.routesSharedData.get(r)||{};a[s]=t,this.routesSharedData.set(r,a),h.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 r=this.getGlobalConfig(k)||{},a=new Set(t),i=Array.from(t);for(let o=0;o<i.length;o++){const n=i[o],c=r[n]?.partials??[];for(const d of c)a.has(d)||(a.add(d),i.push(d))}const l={};for(const o of a)s[o]&&(l[o]=s[o]);return l};addRoute=e=>{const t={...J(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:t}),h.verbose("Created route %s",e.slug)};addRouteSharedDataToAllLocales=(e,s,t)=>{const r=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(a=>({code:a,name:a}));for(const a of r){const i=M(e,g,a.code,r);this.addRouteSharedData(i,s,t)}};addApiRoute=e=>{this.apiRoutes.push(e),h.verbose("Created API route %s",e.slug)};addMcpTools=(e,s)=>{for(const t of s){const r=this.mcpToolHandlers.get(t.name);r&&r.importPath!==e&&h.warn('MCP tool "%s" from %s overwrites the tool registered from %s',t.name,e,r.importPath),this.mcpToolHandlers.set(t.name,{...t,importPath:e}),h.verbose("Created MCP tool %s",t.name)}};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());markGatedMcpTools=e=>{for(const s of e){const t=this.mcpToolHandlers.get(s);t&&this.mcpToolHandlers.set(s,{...t,hasAvailabilityGate:!0})}};addSkills=e=>{for(const s of e)this.skills.set(s.slug,s),h.verbose("Discovered skill %s",s.slug)};getSkills=()=>Array.from(this.skills.values());removeMcpTools=e=>{for(const s of e)this.mcpToolHandlers.delete(s)};addMiddleware=e=>{this.middleware.push(e),h.verbose("Created middleware %s",e.id)};setResourceResponseHeaders=(e,s)=>{this.config.responseHeaders||(this.config.responseHeaders={});const t=new Set(s.map(i=>i.name.toLowerCase())),a=[...(this.config.responseHeaders[e]??[]).filter(i=>!t.has(i.name.toLowerCase())),...s];this.config.responseHeaders[e]=a};getRouteByFsPath=e=>{const s=this.routesByFsPath.get(e);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(e,s={})=>{const{followRedirect:t=!0}=s,r=this.getRedirect(e);return t&&r?this.routesBySlug.get(u(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e)||x(e,this.getConfig()))return!0;const s=this.getRedirect(e);if(!s)return!1;if(!S(s.to))return!0;const t=u(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(r=>e===g?!K(r.fsPath):r.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&&j(e.slug,t,this.outdir)}async resolveRouteStaticData(e,s,t){if(this.serverMode)return q(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[e.slug]},resource:f})},a=await e.getStaticData?.(e,r)||{},i=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=>i.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(e.slug,p,p))}const o=this.getGlobalConfig("seo"),n=a?.frontmatter||{};return{...a,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await e.getNavText?.()}},props:{...a.props,dynamicMarkdocComponents:Array.from(i),metadata:{...a?.props?.metadata,...e.metadata},seo:{title:O,...o,...a.props?.seo,siteUrl:o?.siteUrl},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(""):V(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.skills.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const e=[];for(const[t,r]of Object.entries(E))switch(r){case"map":{const a=Array.from(this[t].entries());e.push([t,a]);break}case"object":if(t==="config"){e.push([t,await this.getConfigWithEnvPlaceholders()]);break}e.push([t,this[t]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(e);return s[P]=G.PLAN_GATES,s}static fromJson(e,s){const t=new b(s);for(const[a,i]of Object.entries(E))switch(i){case"map":t[a]=new Map(e[a]);break;case"object":if(a==="config"){t.setGlobalConfig(e[a]);break}t[a]=e[a];break;default:throw new Error("Invalid format")}t.config[m]=X(t.config[m]||{});const r=e[P];return r&&_("PLAN_GATES",r),t}async getConfigWithEnvPlaceholders(){const e=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:t}=this.replacedEnvVars[s],r=s.split(":"),a=r.pop(),{error:i,value:l}=y(e,r);if(i||!L(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[a]=t}return e}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const e=Array.from(this.unsetEnvVars).filter(t=>!Q.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 X(C){return H(C,e=>A.Ast.fromJSON(JSON.stringify(e)))}export{b as Store,ke as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
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 v}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 w}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as B}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as u}from"../utils/path/normalize-route-slug.js";import{isLocalLink as E}from"../utils/path/is-local-link.js";import{reporter as P}from"./tools/notifiers/reporter.js";import{logger as h}from"./tools/notifiers/logger.js";import{sha1 as I}from"./utils/crypto/sha1.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 W}from"./ssr/render.js";import{readStaticData as $,writeStaticData as z}from"./utils/static-data.js";import{getMarkdocOptions as Y}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as C}from"./entitlements/entitlements-provider.js";import{isRouteReserved as Z}from"./plugins/get-reserved-routes.js";import{isL10nPath as Q}from"./fs/utils/is-l10n-path.js";import{resolveGlobMapValue as X}from"./utils/globs.js";import{createDefaultStoreConfig as ee,resolveConfigEntries as te,resolveStoreConfig as se}from"./store-config.js";import{findRedirect as re}from"./utils/redirects/find-redirect.js";import{followRedirectChain as oe}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as ae}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as ie}from"../cli/telemetry/helpers/trace-step.js";const b={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"},O="store.json",A="store-config.json",T="PLAN_GATES",ne=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ue="userDefinedApiFunctions";class S{routesBySlug=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=ee();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,J.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 ie("com.redocly.build.reloadMarkdocOptions",async()=>{const e=C.instance(),t=await Y(this.serverOutDir),s=Object.fromEntries(Object.entries(t.tags).filter(([r])=>v[r]!=null?e.canAccessFeature(v[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()=>q.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}=w(e,i);(n||l!==this.replacedEnvVars[c].replaced)&&delete this.replacedEnvVars[c]}const{config:s,unsetEnvVars:r,replacedValues:o}=te(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(!C.instance().canAccessFeature("redirects")&&e!=="/")return;this.config.redirects||(this.config.redirects={});const a=u(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("*")&&ae(this.config.wildcardRedirectsTree,a)};getRedirect=e=>{const t=u(e).toLowerCase(),s=re(t,this.config.redirects,this.config.wildcardRedirectsTree,this.staticFilePaths);if(!s)return null;if(E(s.to)){const r=u(s.to).toLowerCase();if(!r.endsWith("*")&&oe(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 K(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),h.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 d of l)o.has(d)||(o.add(d),a.push(d))}const c={};for(const i of o)t[i]&&(c[i]=t[i]);return c};addRoute=e=>{const s={...X(e.fsPath,this.config.metadataGlobs),...e.metadata||{}};this.newRoutes.push({...e,metadata:s}),h.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),h.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&&h.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}),h.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),h.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),h.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);return s&&r?this.routesBySlug.get(u(r.to)):this.routesBySlug.get(e)};hasRouteOrRedirectBySlug=e=>{if(this.routesBySlug.has(e)||Z(e,this.getConfig()))return!0;const t=this.getRedirect(e);if(!t)return!1;if(!E(t.to))return!0;const s=u(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?!Q(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)};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 $(e.slug,this.outdir);const r={...this,contentDir:this.contentDir,parseMarkdoc:({input:l,context:d,resource:f})=>this.parseMarkdoc({input:l,context:d,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 d=this.sharedDataMarkdocComponents.get(l);d&&d.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(""):W(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.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(b))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]=j.PLAN_GATES,t}static#g(e,t){const s=new S(t);for(const[o,a]of Object.entries(b))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&&V("PLAN_GATES",r),s}async writeServerFiles(){x(this.serverOutDir),D(g(this.serverOutDir,O),JSON.stringify(this.#p())),D(g(this.serverOutDir,A),JSON.stringify(await this.getConfigWithEnvPlaceholders()))}static async fromServerFiles(e){const t=g(e.serverOutDir,A),{config:s,env:r}=se(JSON.parse(await R(t,"utf8")));s[y]=ce(s[y]);const o=JSON.parse(await R(g(e.serverOutDir,O),"utf8")),a=S.#g(o,e);a.config=s;const c=Object.fromEntries(Object.entries(r).filter(([i])=>U(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}=w(e,r);if(a||!_(c)&&!Array.isArray(c)){await P.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=>!ne.includes(s));if(e.length===0)return;const t=`Failed to resolve config. The following environment variables are not set: ${e.join(", ")}`;await P.panicOnBuildContentError(t)}}function ce(M){return N(M,e=>k.Ast.fromJSON(JSON.stringify(e)))}export{S as Store,Ue as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import*as E from"node:path";import{envConfig as R}from"../../config/env-config.js";import{maskEmail as T,maskSubject as C,removePii as w,removePiiFromUrl as $}from"../../../compiled/@redocly/pii/index.
|
|
1
|
+
import*as E from"node:path";import{envConfig as R}from"../../config/env-config.js";import{maskEmail as T,maskSubject as C,removePii as w,removePiiFromUrl as $}from"../../../compiled/@redocly/pii/index.mjs";import{red as x,green as A,bold as F,blue as l,gray as r,yellow as b,cyan as v}from"./helpers/colors.js";function P(e,s){return s?e:w(e)}var n;(function(e){e.INFO="INFO",e.WARN="WARN",e.ERROR="ERROR",e.SUCCESS="SUCCESS",e.VERBOSE="VERBOSE",e.HTTP="HTTP"})(n||(n={}));const I={[n.VERBOSE]:0,[n.HTTP]:1,[n.INFO]:2,[n.SUCCESS]:2,[n.WARN]:3,[n.ERROR]:4};function J(e,s){return I[e]>=I[s]}function W(e){if(!e)return;const s=e.toUpperCase();if(s in n)return s}const H={[n.INFO]:l,[n.SUCCESS]:A,[n.WARN]:b,[n.ERROR]:x,[n.HTTP]:v,[n.VERBOSE]:r},N={"%ap":e=>l(E.resolve(e)),"%rp":e=>l(E.relative(process.cwd(),e)),"%s":e=>e?.toString(),"%c":e=>l(e)},M={format(e){return R.REDOCLY_LOG_FORMAT==="JSON"?y(e):U(e)},interpolate(e,...s){const u=Object.keys(N).map(a=>`(${a})`).join("|"),o=new RegExp(u,"g");let i,c=e;for(;(i=o.exec(e))!==null;){i.index===o.lastIndex&&o.lastIndex++;const a=s.shift();if(a===void 0)break;const t=i[0];c=c.replace(t,N[t](a))}return c}};var z=M;const U=e=>{const{level:s,message:u,duration:o,context:i,preSanitized:c}=e,a=R.isRuntimeMode,t=[H[s](F(`[${s.toLowerCase()}]`))];if(a&&t.push(r(`time="${j()}"`)),i){const{email:m,ipAddress:f,subject:d,method:S,pathname:p,statusCode:h,teams:g,apiFunction:O}=i;O&&t.push(l(`fn="${O}"`)),h&&t.push(D(h)),e.level===n.HTTP&&(S&&t.push(r(`method="${S}"`)),p&&t.push(r(`path="${$(p)}"`))),f&&t.push(r(`ip="${f}"`)),m&&t.push(r(`email="${T(m)}"`)),d&&t.push(r(`sub="${C(d)}"`)),g?.length&&t.push(r(`teams="${g.join(", ")}"`))}if(u){const m=a?`msg="${String(P(u,c)).replaceAll?.('"','\\"')}"`:String(u);t.push(m)}return e.level===n.HTTP&&i?.userAgent&&t.push(r(`agent="${i.userAgent}"`)),o&&t.push(V(o)),t.join(" ")+`
|
|
2
2
|
`},y=({context:e,message:s,preSanitized:u,...o})=>{const{method:i,pathname:c,statusCode:a,userAgent:t,subject:m,email:f,teams:d,apiFunction:S}=e||{},p={...o,email:f&&T(f),subject:m&&C(m),teams:d,apiFunction:S,...o.level===n.HTTP?{method:i,pathname:String($(c)),statusCode:a,userAgent:t}:{message:String(P(String(s??""),u))}};return R.isRuntimeMode&&(p.time=j()),JSON.stringify(p,["time","level","scope","message","duration","method","pathname","statusCode","userAgent","subject","ipAddress","email","apiFunction"])+`
|
|
3
3
|
`},D=e=>(e%500<100?x:e%400<100?b:A)(`status="${e}"`),j=()=>{const e=new Date().getTimezoneOffset()*6e4;return new Date(Date.now()-e).toISOString().slice(0,-1)},V=e=>r(`dur="${Math.round(e)}ms"`);export{n as LogLevel,z as default,W as parseLogLevel,J as shouldLog};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
declare const colorsAreEnabled: boolean;
|
|
2
|
-
declare const red
|
|
2
|
+
declare const { red, green, bold, blue, gray, yellow, cyan }: import("colorette").Colorette;
|
|
3
3
|
declare const stripColors: (input: string) => string;
|
|
4
4
|
export { red, gray, green, blue, bold, yellow, cyan, colorsAreEnabled, stripColors };
|
|
5
5
|
//# sourceMappingURL=colors.d.ts.map
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { ApiFunctionsBasicContext } from '../../types';
|
|
2
|
+
import type { WorkerConfig } from '../../workers/worker-config.js';
|
|
2
3
|
export type ApiRoutesWorkerParams = {
|
|
3
4
|
maxResponseSizeMB?: number;
|
|
4
5
|
slug: string;
|
|
5
6
|
requestHandlerId: string;
|
|
6
|
-
ctxData: ApiFunctionsBasicContext
|
|
7
|
+
ctxData: Omit<ApiFunctionsBasicContext, 'config'> & {
|
|
8
|
+
config: WorkerConfig;
|
|
9
|
+
};
|
|
7
10
|
staticData: Record<string, unknown>;
|
|
8
11
|
serverOutDir: string;
|
|
9
12
|
req: {
|
|
@@ -3,10 +3,16 @@ import { z } from 'zod';
|
|
|
3
3
|
* Env vars that are set as the strings `"true"` or `"false"`, parsed to booleans.
|
|
4
4
|
* Any other value fails validation.
|
|
5
5
|
*/
|
|
6
|
-
export declare function envBooleanStringOptional(): z.
|
|
7
|
-
|
|
6
|
+
export declare function envBooleanStringOptional(): z.ZodPipe<z.ZodOptional<z.ZodEnum<{
|
|
7
|
+
false: "false";
|
|
8
|
+
true: "true";
|
|
9
|
+
}>>, z.ZodTransform<boolean | undefined, "false" | "true" | undefined>>;
|
|
10
|
+
export declare function envBooleanStringDefaultFalse(): z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
11
|
+
false: "false";
|
|
12
|
+
true: "true";
|
|
13
|
+
}>>, z.ZodTransform<boolean, "false" | "true">>;
|
|
8
14
|
/**
|
|
9
15
|
* Like {@link envBooleanStringOptional}, but also accepts `"1"` as true (common for `CI`).
|
|
10
16
|
*/
|
|
11
|
-
export declare function envCiBooleanOptional(): z.
|
|
17
|
+
export declare function envCiBooleanOptional(): z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"true">, z.ZodLiteral<"false">, z.ZodLiteral<"1">]>>, z.ZodTransform<boolean | undefined, "1" | "false" | "true" | undefined>>;
|
|
12
18
|
//# sourceMappingURL=env-boolean-string.d.ts.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export declare const EXCLUDED_ENV_VARS: string[];
|
|
2
|
+
/** Whether a worker may see the env variable `name`. */
|
|
3
|
+
export declare function isAllowedEnv(name: string): boolean;
|
|
2
4
|
export declare function getAllowedEnvs(): Record<string, string | undefined>;
|
|
3
5
|
//# sourceMappingURL=get-api-route-allowed-env-variables.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=["AUTH_URL","BH_API_URL","HOME","HOSTNAME","INSPECT_MODE","INTERNAL_API_USERNAME","JWT_SECRET_KEY","METRICS_API_PORT","NODE","NODE_OPTIONS","NODE_VERSION","OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","PATH","PLAN_GATES","PORTAL_ID","PWD","SERVER_EDITOR_APP_URL","SHLVL","SUBSCRIPTION_IN_TRIAL","TERM","TYPESENSE_API_URL","UV_USE_IO_URING","VAULT_TOKEN","WEB_SERVER_IDLE_TIMEOUT","YARN_VERSION","npm_config_cache","npm_config_local_prefix","npm_config_user_agent","npm_execpath","npm_node_execpath","npm_package_json","npm_package_name","npm_package_version"],n=["NOMAD_"];function T(){return Object.fromEntries(Object.entries(process.env).filter(([_])
|
|
1
|
+
const e=["AUTH_URL","BH_API_URL","HOME","HOSTNAME","INSPECT_MODE","INTERNAL_API_USERNAME","JWT_SECRET_KEY","METRICS_API_PORT","NODE","NODE_OPTIONS","NODE_VERSION","OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","PATH","PLAN_GATES","PORTAL_ID","PWD","SERVER_EDITOR_APP_URL","SHLVL","SUBSCRIPTION_IN_TRIAL","TERM","TYPESENSE_API_URL","UV_USE_IO_URING","VAULT_TOKEN","WEB_SERVER_IDLE_TIMEOUT","YARN_VERSION","npm_config_cache","npm_config_local_prefix","npm_config_user_agent","npm_execpath","npm_node_execpath","npm_package_json","npm_package_name","npm_package_version"],n=["NOMAD_"];function T(_){return!e.includes(_)&&!n.some(E=>_.startsWith(E))}function R(){return Object.fromEntries(Object.entries(process.env).filter(([_])=>T(_)))}export{e as EXCLUDED_ENV_VARS,R as getAllowedEnvs,T as isAllowedEnv};
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import { readEnvVariable } from './read-env-variable.js';
|
|
2
|
+
/** False when `value` has no env variable template. Cheaper than `interpolateEnvVariables`. */
|
|
3
|
+
export declare function mayHaveEnvVariables(value: string): boolean;
|
|
1
4
|
/**
|
|
2
5
|
* Interpolates environment variables in a string using the format {{ process.env.VARIABLE_NAME }}.
|
|
3
6
|
* Supports optional quoted default values applied when the variable is not set,
|
|
4
7
|
* e.g. {{ process.env.VARIABLE_NAME || "default" }} (both `|` and `||` separators are accepted).
|
|
5
8
|
*
|
|
6
9
|
* @param value - The string containing environment variable templates to interpolate
|
|
10
|
+
* @param readEnv - Returns the value of an environment variable; reads `process.env` by default
|
|
7
11
|
* @returns An object containing:
|
|
8
12
|
* - interpolatedValue: The string with all environment variables replaced with their values
|
|
9
13
|
* - unsetVars: Array of environment variable names that were not found and had no default
|
|
10
14
|
* - interpolatedVars: Array of environment variable names that were successfully resolved
|
|
11
15
|
*/
|
|
12
|
-
export declare function interpolateEnvVariables(value: string): {
|
|
16
|
+
export declare function interpolateEnvVariables(value: string, readEnv?: typeof readEnvVariable): {
|
|
13
17
|
interpolatedValue: string;
|
|
14
18
|
unsetVars: string[];
|
|
15
19
|
interpolatedVars: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readEnvVariable as d}from"./read-env-variable.js";const
|
|
1
|
+
import{readEnvVariable as d}from"./read-env-variable.js";const f=/{{\s*process\.env\.([A-Z0-9_]+)\s*(?:\|\|?\s*(?:"([^"]*)"|'([^']*)')\s*)?}}/gi;function p(a){return a.includes("{{")}function u(a,c=d){let e=a;const s=new Set,t=new Set,i=[...a.matchAll(f)];for(const n of i){const r=n[1].toUpperCase(),o=n[2]??n[3],l=c(r);l!==void 0?(e=e.replace(n[0],l),t.add(r)):o!==void 0?(e=e.replace(n[0],o),t.add(r)):s.add(r)}return{interpolatedValue:e,unsetVars:Array.from(s),interpolatedVars:Array.from(t)}}export{u as interpolateEnvVariables,p as mayHaveEnvVariables};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as o from"dotenv";import*as n from"path";import{simpleGit as
|
|
1
|
+
import*as o from"dotenv";import*as n from"path";import{simpleGit as E}from"simple-git";import{envConfig as s,reloadEnvConfig as c,setEnv as p}from"../../config/env-config.js";import{readEnvVariable as m}from"../../utils/envs/read-env-variable.js";import{sanitizeBranchName as f}from"../../utils/envs/sanitize-branch-name.js";async function l(e){try{return(await E(e??process.cwd()).revparse(["--abbrev-ref","HEAD"])).trim()}catch{return""}}const _=["REDOCLY_EXP_REPLAY_GRAPHQL_ENABLED","REDOCLY_EXP_REPLAY_ASYNCAPI_ENABLED"];async function d(e){const a=Object.fromEntries(_.map(t=>[t,m(t)]));o.config({path:n.resolve(e??"",".env")}),c();const i=s.PUBLIC_REDOCLY_BRANCH_NAME||await l(e);if(i){const t=f(i);o.config({path:n.resolve(e??"",`.env.branch.${t}`),override:!0}),c()}const v=s.REDOCLY_ENV;let r;switch(v){case"production":r=".env.production";break;case"preview":r=".env.preview";break;default:r=".env.development";break}o.config({path:n.resolve(e??"",r),override:!0}),p(a)}export{d as loadEnvVariables};
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
import { readEnvVariable } from './read-env-variable.js';
|
|
2
|
+
type EnvReplacement = {
|
|
3
|
+
unsetEnvVars: string[];
|
|
4
|
+
interpolatedEnvVars: string[];
|
|
5
|
+
replacedValues: Record<string, {
|
|
6
|
+
original: string;
|
|
7
|
+
replaced: string;
|
|
8
|
+
}>;
|
|
9
|
+
};
|
|
1
10
|
/**
|
|
2
11
|
* Recursively traverses an object or array and interpolates environment variables in all string values.
|
|
3
12
|
* Keeps track of the path to each modified value and maintains a record of original and replaced values.
|
|
4
13
|
*
|
|
5
14
|
* @param obj - The object or array to process
|
|
6
|
-
* @param currentPath - Array of keys representing current position in object tree
|
|
7
15
|
*
|
|
8
16
|
* @returns An object containing:
|
|
9
|
-
* - resolvedObj:
|
|
17
|
+
* - resolvedObj: A copy of the plain objects and arrays, with all environment variables replaced
|
|
10
18
|
* - unsetEnvVars: Array of environment variable names that were not found
|
|
11
19
|
* - interpolatedEnvVars: Array of environment variable names that were successfully resolved
|
|
12
20
|
* - replacedValues: Record of paths where values were replaced, with original and new values
|
|
@@ -14,13 +22,13 @@
|
|
|
14
22
|
* For usage examples and test cases, see:
|
|
15
23
|
* [unit tests](./__tests__/env.test.ts)
|
|
16
24
|
*/
|
|
17
|
-
export declare function replaceEnvVariablesDeep<T extends Record<string, unknown> | Array<unknown>>(obj: T
|
|
25
|
+
export declare function replaceEnvVariablesDeep<T extends Record<string, unknown> | Array<unknown>>(obj: T): EnvReplacement & {
|
|
18
26
|
resolvedObj: T;
|
|
19
|
-
unsetEnvVars: string[];
|
|
20
|
-
interpolatedEnvVars: string[];
|
|
21
|
-
replacedValues: Record<string, {
|
|
22
|
-
original: string;
|
|
23
|
-
replaced: string;
|
|
24
|
-
}>;
|
|
25
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* `replaceEnvVariablesDeep` without the copy: changes the strings of `container` in place.
|
|
30
|
+
* `readEnv` returns the value of an environment variable; it reads `process.env` by default.
|
|
31
|
+
*/
|
|
32
|
+
export declare function replaceEnvVariablesInPlace(container: object, readEnv?: typeof readEnvVariable): EnvReplacement;
|
|
33
|
+
export {};
|
|
26
34
|
//# sourceMappingURL=replace-env-variables-deep.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject as
|
|
1
|
+
import{isObject as c}from"../../../utils/guards/is-object.js";import{interpolateEnvVariables as E,mayHaveEnvVariables as b}from"./interpolate-env-variables.js";import{readEnvVariable as v}from"./read-env-variable.js";function g(r){const n=p(r);return{resolvedObj:n,...A(n)}}function A(r,n=v){const t=new Set,f=new Set,l={},i=[],V=u=>{const o=u;for(const a in o){const e=o[a];if(typeof e=="string"){if(!b(e))continue;const{interpolatedValue:d,unsetVars:y,interpolatedVars:m}=E(e,n);y.forEach(s=>t.add(s)),m.forEach(s=>f.add(s)),m.length>0&&(o[a]=d,l[[...i,a].join(":")]={original:e,replaced:d})}else(c(e)||Array.isArray(e))&&(i.push(a),V(e),i.pop())}};return(c(r)||Array.isArray(r))&&V(r),{unsetEnvVars:Array.from(t),interpolatedEnvVars:Array.from(f),replacedValues:l}}function p(r){return Array.isArray(r)?r.map(p):c(r)?Object.fromEntries(Object.entries(r).map(([n,t])=>[n,p(t)])):r}export{g as replaceEnvVariablesDeep,A as replaceEnvVariablesInPlace};
|
|
@@ -2,6 +2,7 @@ import '../node-crypto-polyfill.js';
|
|
|
2
2
|
import { REDOCLY_TEAMS_RBAC, REDOCLY_ROUTE_RBAC } from '@redocly/config';
|
|
3
3
|
import type { RbacConfig, RbacScopeItems, RedoclyConfig, SsoConfig } from '@redocly/config';
|
|
4
4
|
import type { AuthDetails } from '../types';
|
|
5
|
+
import type { ApiDefinitionAccess } from '../plugins/api-docs/definition-access.js';
|
|
5
6
|
import type { ContentFs } from '../fs/content-fs.js';
|
|
6
7
|
import type { RbacFeatures } from '../../constants/common.js';
|
|
7
8
|
export type ProjectRole = 'NONE' | 'READ' | 'TRIAGE' | 'WRITE' | 'MAINTAIN' | 'ADMIN';
|
|
@@ -33,7 +34,7 @@ export declare function canDownloadApiDefinition(pathname: string, rbacConfig: R
|
|
|
33
34
|
isAuthenticated?: boolean;
|
|
34
35
|
email?: string;
|
|
35
36
|
teams?: string[];
|
|
36
|
-
}): boolean;
|
|
37
|
+
}, definitionAccess?: ApiDefinitionAccess): boolean;
|
|
37
38
|
export declare function canAccessAsset(pathname: string, rbacConfig: RbacConfig, requiresLogin: boolean, directoryPaths: Record<string, string>, user?: {
|
|
38
39
|
isAuthenticated?: boolean;
|
|
39
40
|
email?: string;
|