@redocly/reef 0.132.0-next.9 → 0.133.0-next.0
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 +136 -2
- package/dist/cli/build/copy-env-files.js +1 -1
- package/dist/cli/develop.js +1 -1
- package/dist/cli/telemetry/index.js +1 -1
- package/dist/client/app/Link.js +1 -1
- package/dist/client/app/hooks/catalog/useFetchCatalogEntityRevisions.js +1 -1
- package/dist/client/app/search/message-handlers.js +1 -1
- package/dist/client/types/ai-search.d.ts +6 -2
- package/dist/constants/common.d.ts +2 -1
- package/dist/constants/common.js +1 -1
- package/dist/server/config/env-config.d.ts +157 -8
- package/dist/server/config/env-config.js +1 -1
- package/dist/server/config/env-schema.d.ts +148 -185
- package/dist/server/config/env-schema.js +1 -3
- package/dist/server/config/env-schemas/auth.d.ts +4 -4
- package/dist/server/config/env-schemas/auth.js +1 -1
- package/dist/server/config/env-schemas/catalog.d.ts +2 -2
- package/dist/server/config/env-schemas/catalog.js +1 -1
- package/dist/server/config/env-schemas/environment-detection.d.ts +13 -13
- package/dist/server/config/env-schemas/environment-detection.js +1 -1
- package/dist/server/config/env-schemas/feature-flags.d.ts +9 -6
- package/dist/server/config/env-schemas/feature-flags.js +1 -1
- package/dist/server/config/env-schemas/search.d.ts +1 -1
- package/dist/server/config/env-schemas/search.js +1 -1
- package/dist/server/config/env-schemas/server-config.d.ts +2 -2
- package/dist/server/config/env-schemas/server-config.js +1 -1
- package/dist/server/constants/entitlements.js +1 -1
- package/dist/server/esbuild/esbuild-logger.js +3 -3
- package/dist/server/esbuild/esbuild.js +2 -2
- package/dist/server/persistence/kv/repositories/kv-remote-repository.d.ts +2 -0
- package/dist/server/persistence/kv/repositories/kv-remote-repository.js +2 -2
- package/dist/server/persistence/kv/services/kv-service.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/local/catalog-entities-local-write-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/base.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/fs-entities-extractor.js +1 -1
- package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
- package/dist/server/plugins/default-theme/index.js +1 -1
- package/dist/server/plugins/enforce-login/index.js +1 -1
- package/dist/server/plugins/entitlements/utils/get-billed-catalog-build-pages-count.js +1 -1
- package/dist/server/plugins/lifecycle.js +1 -1
- package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +1 -0
- package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/search.js +2 -2
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/types.d.ts +1 -0
- package/dist/server/plugins/nav-utils.js +1 -1
- package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +26 -26
- package/dist/server/plugins/openapi-docs/utils.js +1 -1
- package/dist/server/plugins/scorecards/plugin.js +1 -1
- package/dist/server/providers/database/base-repository.d.ts +1 -0
- package/dist/server/providers/database/base-repository.js +5 -1
- package/dist/server/providers/database/database-preconnect-service.js +1 -1
- package/dist/server/providers/database/pagination/utils/extract-equal-filter-clause-value.d.ts +6 -0
- package/dist/server/providers/database/pagination/utils/extract-equal-filter-clause-value.js +1 -0
- package/dist/server/providers/database/pagination/utils/index.d.ts +1 -0
- package/dist/server/providers/database/pagination/utils/index.js +1 -1
- package/dist/server/providers/database/utils/storage-limit-validator.d.ts +13 -0
- package/dist/server/providers/database/utils/storage-limit-validator.js +1 -0
- package/dist/server/store.js +1 -1
- package/dist/server/telemetry/index.js +1 -1
- package/dist/server/tools/notifiers/formatter.js +3 -3
- package/dist/server/tools/notifiers/helpers/colors.js +1 -1
- package/dist/server/utils/envs/env-boolean-string.d.ts +12 -0
- package/dist/server/utils/envs/env-boolean-string.js +1 -0
- package/dist/server/utils/envs/load-env-variables.js +1 -1
- package/dist/server/utils/is-catalog-entities-enabled.js +1 -1
- package/dist/server/utils/is-scorecards-enabled.js +1 -1
- package/dist/server/utils/lifecycle-hooks.js +1 -1
- package/dist/server/version.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-revisions.js +1 -1
- package/dist/server/web-server/routes/cors-proxy.d.ts +2 -1
- package/dist/server/web-server/routes/cors-proxy.js +2 -2
- package/dist/server/web-server/routes/dynamic-route.js +1 -1
- package/dist/server/web-server/routes/feedback.js +1 -1
- package/dist/server/web-server/routes/index.js +1 -1
- package/dist/server/web-server/routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/otel/otel.d.ts +2 -16
- package/dist/server/web-server/routes/otel/otel.js +1 -1
- package/dist/server/web-server/routes/otel/otlp.d.ts +4 -1
- package/dist/server/web-server/routes/otel/otlp.js +1 -1
- package/dist/server/web-server/routes/static-content.js +1 -1
- package/dist/server/web-server/utils/content-type.d.ts +2 -0
- package/dist/server/web-server/utils/content-type.js +1 -0
- package/dist/types/entitlements.d.ts +1 -0
- package/package.json +13 -13
- package/dist/server/config/env-schemas/test.d.ts +0 -22
- package/dist/server/config/env-schemas/test.js +0 -1
- package/dist/server/utils/envs/write-env-variable.d.ts +0 -18
- package/dist/server/utils/envs/write-env-variable.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{REDOCLY_TEAMS_RBAC as i}from"@redocly/config";import{combineUrls as
|
|
1
|
+
import{REDOCLY_TEAMS_RBAC as i}from"@redocly/config";import{combineUrls as p}from"@redocly/theme/core/utils";import{FEEDBACK_TYPES as c}from"../../../constants/common.js";import{normalizeRouteSlug as h}from"../../../utils/path/normalize-route-slug.js";function u(t){const{contentItems:o,sidebarItems:n,routeSlug:r,navItem:s}=t;let b=!0;for(const e of o){let a;switch(e.type){case"group":n.push({type:"separator",label:e.name,[i]:e[i]}),u({...t,contentItems:e.items,sidebarItems:n});break;case"tag":a=p(r,e.href);const m={type:"group",label:e.name,items:[],link:a,routeSlug:a,[i]:e[i]};n.push(m),u({routeSlug:r,contentItems:e.items,sidebarItems:m.items||[],navItem:s});break;case"operation":case"schema":case"rsrc":case"prompt":case"tool":e.isWebhook&&b&&(n.push({type:"separator",label:"Webhooks",variant:"secondary"}),b=!1),a=p(r,e.href),n.push({type:"link",label:e.name,httpVerb:e.type==="operation"?e.httpVerb:e.type,routeSlug:h(a),badges:e.badges,link:a,deprecated:e.deprecated,isAdditionalOperation:e.isAdditionalOperation,[i]:e[i]});break;case"section":if(e.depth===-1)continue;a=p(r,e.href);const l=e.href==="/",g={type:e.items.length?"group":"link",label:l&&s?.label?s.label:e.name,labelTranslationKey:s?.labelTranslationKey,routeSlug:a.split("#")[0]===r?r:h(a),link:a,items:[],...l&&s?.icon&&{icon:typeof s.icon=="object"?s.icon.srcSet:s.icon},...l&&s?.badges&&{badges:s.badges}};n.push(g),e.items.length&&u({routeSlug:r,contentItems:e.items,sidebarItems:g.items});break}}}function S({item:t}){return t.id===""?!0:t.type!=="group"||t.description!==""}const I=t=>(typeof t=="string"?t:t?.raw)?.replace(/\[(.*?)\][\[\(].*?[\]\)]/g,"$1")||"";function A(t){if(!t)return;let o="";const{type:n,settings:r}=t;switch(n){case c.RATING:o="Rate this section";break;case c.SENTIMENT:o="Was this section helpful?";break;case c.MOOD:o="Was this section helpful?";break;case c.COMMENT:o="Share your feedback about this section";break;case c.SCALE:o="How would you rate this section?";break}return{...t,settings:{...r,label:r?.label||o}}}function E(t){return(typeof t=="string"?t:t?.raw||"").replace(/<[^>]*>/g,"").replace(/```([\s\S]*?)```/g,"$1").replace(/`([^`]+)`/g,"$1").replace(/\*\*(.*?)\*\*/g,"$1").replace(/\*(.*?)\*/g,"$1").trim()}export{u as convertOpenAPIDocs2Sidebar,A as normalizeFeedbackOptions,I as removeMarkdownLinks,S as shouldAddRoute,E as stripFormatting};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{envConfig as c}from"../../config/env-config.js";import{SCORECARDS_BASE_SLUG as i,SCORECARDS_TEMPLATE_ID as n}from"../../constants/plugins/scorecards.js";import{getTemplatePath as d}from"./utils/get-template-path.js";import{telemetryTraceStep as l}from"../../../cli/telemetry/helpers/trace-step.js";async function u(){return{id:"Scorecards",requiredEntitlements:["scorecards"],async processContent(e,r){await l("build.plugin.scorecards",async s=>{if(c.NEW_SCORECARDS_ENABLED
|
|
1
|
+
import{envConfig as c}from"../../config/env-config.js";import{SCORECARDS_BASE_SLUG as i,SCORECARDS_TEMPLATE_ID as n}from"../../constants/plugins/scorecards.js";import{getTemplatePath as d}from"./utils/get-template-path.js";import{telemetryTraceStep as l}from"../../../cli/telemetry/helpers/trace-step.js";async function u(){return{id:"Scorecards",requiredEntitlements:["scorecards"],async processContent(e,r){await l("build.plugin.scorecards",async s=>{if(!c.NEW_SCORECARDS_ENABLED)return;const t=(await r.getConfig()).scorecards;s?.setAttribute("config",JSON.stringify(t));const{logger:o}=r;o.info("Scorecards plugin started");const a=e.createTemplate(n,d("../template/index.js"));e.addRoute({duplicateInAllLocales:!0,slug:i,fsPath:"",templateId:a,excludeFromSidebar:!0,hasClientRoutes:!0,getNavText:()=>Promise.resolve("Scorecards"),getStaticData:async()=>({props:{scorecardsConfig:t}})}),o.info("Scorecards plugin finished")})}}}var C=u;export{C as default,u as scorecardsPlugin};
|
|
@@ -9,6 +9,7 @@ export declare abstract class BaseRepository {
|
|
|
9
9
|
protected constructor(dbConnection: DatabaseConnection);
|
|
10
10
|
close(): Promise<void>;
|
|
11
11
|
sync(): Promise<void>;
|
|
12
|
+
protected getTableSizeInBytes(tableName: string): Promise<number>;
|
|
12
13
|
isNonRemoteDatabaseMode: () => boolean;
|
|
13
14
|
}
|
|
14
15
|
//# sourceMappingURL=base-repository.d.ts.map
|
|
@@ -1 +1,5 @@
|
|
|
1
|
-
import{envConfig as i}from"../../config/env-config.js";import{SQLD_REMOTE_DATABASE_URL_NO_DEPLOYMENT_YET_VAR as
|
|
1
|
+
import{sql as a}from"drizzle-orm";import{envConfig as i}from"../../config/env-config.js";import{SQLD_REMOTE_DATABASE_URL_NO_DEPLOYMENT_YET_VAR as o}from"../../constants/plugins/catalog-entities.js";class n{static#t="ORGANIZATION_ID";static#e="PROJECT_ID";organizationId;projectId;databaseClient;path;constructor(e){const t=this.isNonRemoteDatabaseMode();this.organizationId=this.#i(t),this.projectId=this.#n(t),this.databaseClient=e.client,this.path=e.path}async close(){await this.databaseClient.close()}async sync(){await this.databaseClient.sync()}async getTableSizeInBytes(e){const s=(await this.databaseClient.client.run(a`
|
|
2
|
+
SELECT COALESCE(SUM(pgsize), 0) AS bytes
|
|
3
|
+
FROM dbstat
|
|
4
|
+
WHERE name = ${e}
|
|
5
|
+
`)).rows[0]?.bytes,r=Number(s??0);return Number.isFinite(r)?r:0}#i=e=>{const t=i.ORGANIZATION_ID;if(t)return t;if(e)return n.#t;throw new Error("ORGANIZATION_ID environment variable is required. Ensure it is set in your environment configuration.")};#n=e=>{const t=i.PROJECT_ID;if(t)return t;if(e)return n.#e;throw new Error("PROJECT_ID environment variable is required. Ensure it is set in your environment configuration.")};isNonRemoteDatabaseMode=()=>i.SQLD_REMOTE_DATABASE_URL===o||!i.SQLD_REMOTE_DATABASE_AUTH_TOKEN}export{n as BaseRepository};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as o}from"../../tools/notifiers/logger.js";import{envConfig as n}from"../../config/env-config.js";import{DatabaseConnectionFactory as i}from"./database-connection-factory.js";class t{static#t=!1;static async init(e){if(!(n.REDOCLY_INTERNAL_DEV
|
|
1
|
+
import{logger as o}from"../../tools/notifiers/logger.js";import{envConfig as n}from"../../config/env-config.js";import{DatabaseConnectionFactory as i}from"./database-connection-factory.js";class t{static#t=!1;static async init(e){if(!(n.REDOCLY_INTERNAL_DEV||n.CI)&&!t.#t)try{await t.#e(e)==="PRECONNECTED"&&(t.#t=!0)}catch(r){o.error("Failed to preconnect to sqld remote database",r)}}static#e=async e=>await i.create("sqld-remote",{baseDbDir:e})?(o.info("Sqld remote database preconnected"),"PRECONNECTED"):(o.warn("Sqld remote database preconnect failed"),"NOT_PRECONNECTED")}export{t as DatabasePreconnectService};
|
package/dist/server/providers/database/pagination/utils/extract-equal-filter-clause-value.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Filter } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* First top-level equal clause for `camelField` after portal filter field transforms (camelCase → snake_case).
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractEqualFilterClauseValue(filter: Filter | undefined, camelField: string): string | null;
|
|
6
|
+
//# sourceMappingURL=extract-equal-filter-clause-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{isFilterCondition as u}from"../types.js";import{transformToSnakeCase as a}from"./transform-to-snake-case.js";function c(i,e){const o=a(e),l=t=>{if(u(t)){for(const r of t.conditions){const n=l(r);if(n)return n}return null}if(t.operator==="equal"&&t.field===o&&!t.modifier&&!t.parentFields?.length){const r=t.value;return typeof r=="string"&&r.length>0?r:null}return null};return i?l(i):null}export{c as extractEqualFilterClauseValue};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./create-cursor.js";export*from"./decode-cursor.js";export*from"./is-base-64.js";export*from"./is-nested-condition.js";export*from"./is-simple-condition.js";export*from"./map-operator.js";export*from"./transform-condition.js";export*from"./transform-to-camel-case.js";export*from"./transform-to-snake-case.js";
|
|
1
|
+
export*from"./create-cursor.js";export*from"./decode-cursor.js";export*from"./extract-equal-filter-clause-value.js";export*from"./is-base-64.js";export*from"./is-nested-condition.js";export*from"./is-simple-condition.js";export*from"./map-operator.js";export*from"./transform-condition.js";export*from"./transform-to-camel-case.js";export*from"./transform-to-snake-case.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type StorageLimitValidationParams = {
|
|
2
|
+
storageLimitGb: number;
|
|
3
|
+
currentTotalBytes: number;
|
|
4
|
+
existingEntryBytes: number;
|
|
5
|
+
incomingEntryBytes: number;
|
|
6
|
+
errorMessagePrefix: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class StorageLimitValidator {
|
|
9
|
+
#private;
|
|
10
|
+
validate({ storageLimitGb, currentTotalBytes, existingEntryBytes, incomingEntryBytes, errorMessagePrefix, }: StorageLimitValidationParams): void;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=storage-limit-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class t{validate({storageLimitGb:e,currentTotalBytes:s,existingEntryBytes:B,incomingEntryBytes:n,errorMessagePrefix:d}){const c=t.#t(e),r=s+n-B;if(r>c){const o=r-c;throw new Error(`${d} exceeded: ${t.#e(r)} GB / ${t.#e(c)} GB (exceeded by ${t.#c(o)})`)}}static#e(e){return(e/(1024*1024*1024)).toFixed(2)}static#t(e){return e*1024*1024*1024}static#c(e){return e>=1024*1024?`${(e/(1024*1024)).toFixed(2)} MB`:e>=1024?`${(e/1024).toFixed(2)} KB`:`${e} B`}}export{t as StorageLimitValidator};
|
package/dist/server/store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import A from"@markdoc/markdoc";import{getPathnameForLocale as C}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{writeEnvVariable as _}from"./utils/envs/write-env-variable.js";import{envConfig as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as V}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as H}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as R}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as U}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as q}from"./utils/redirects/find-redirect.js";import{followRedirectChain as x}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Tt="userDefinedApiFunctions";class P{routesBySlug=new Map;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;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#e=new Map;constructor({outdir:t,contentDir:s,serverMode:e=!1,serverOutDir:a}){this.#r=s,this.outdir=t,this.serverMode=e,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(t,s){const e=this.listeners.get(t);e?e.add(s):this.listeners.set(t,new Set([s]))}queueEvent=(t,s,...e)=>{this.#e.set(t+String(s),[t,s,...e])};runListeners=(t,s,...e)=>{for(const a of this.listeners.get(t)||new Set)s?a(s,...e):a(...e)};startPluginsRun(){this.clear(),this.#o=new Promise(t=>{this.#i=t})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const t of this.#e.values())this.runListeners(...t);this.#e.clear()}startEsbuildRun(){this.#n=new Promise(t=>{this.#c=t})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const t=R.instance(),s=await H(this.serverOutDir),e=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?t.canAccessFeature(D[a]):!0));this.#s={...s,tags:e}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=t=>{const s=this.globalData,e={...this.globalData,...t};this.globalData=e,JSON.stringify(e)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,e)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:t,context:s,deps:e,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(t,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of e?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of e?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of e?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of e?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(e?.routeSlugs&&r.partials?.length)for(const i of e.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(t){return(await t.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(t){return(await t.cache.load(".","asyncapi-docs")).data}setSearchEngine(t){this.searchEngine=t}setSearchFacets=t=>{this.searchFacets=t};setGlobalConfig=t=>{const s=Object.keys(t);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(t,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:e,unsetEnvVars:a,replacedValues:r}=J(t);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,e)};getConfig=()=>this.config;getGlobalConfig=t=>this.config[t];getSearchFacets=()=>this.searchFacets;addRedirect=(t,s,e={})=>{if(!R.instance().canAccessFeature("redirects")&&t!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(t).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=e,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=t=>{const s=h(t).toLowerCase(),e=q(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!e)return null;if(S(e.to)){const a=h(e.to).toLowerCase();if(!a.endsWith("*")&&x(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:e.to,type:e.type}};createSharedData=async(t,s,e)=>{if(e&&this.#t[t]===e)return t;const a=JSON.stringify(s),r=e??k(a);return this.#t[t]===r||(this.#t[t]=r,await B(t,a,this.outdir),this.queueEvent("shared-data-updated",t)),t};addRouteSharedData=(t,s,e)=>{const a=L(t),r=this.routesSharedData.get(a)||{};r[s]=e,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${t}, ${s}, ${e}`)};getRouteSharedDataByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=t=>{const s=this.getGlobalConfig(m)||{},e=this.routesPartials.get(t);if(!e||e.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(e),o=Array.from(e);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=t=>{const e={...U(t.fsPath,this.config.metadataGlobs),...t.metadata||{}};this.newRoutes.push({...t,metadata:e}),u.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,s,e)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=C(t,g,r.code,a);this.addRouteSharedData(o,s,e)}};addApiRoute=t=>{this.apiRoutes.push(t),u.verbose("Created API route %s",t.slug)};addMcpTools=(t,s)=>{for(const e of s)this.mcpToolHandlers.set(e.name,{...e,importPath:t}),u.verbose("Created MCP tool %s",e.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=t=>{this.middleware.push(t),u.verbose("Created middleware %s",t.id)};getRouteByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(t,s={})=>{const{followRedirect:e=!0}=s,a=this.getRedirect(t);return e&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(t)};hasRouteOrRedirectBySlug=t=>{if(this.routesBySlug.has(t))return!0;const s=this.getRedirect(t);if(!s)return!1;if(!S(s.to))return!0;const e=h(s.to);return this.routesBySlug.has(e)};getRoutesByTemplateId=t=>this.newRoutes.filter(s=>s.templateId===t);getAllRoutesForLocale=(t=g)=>{const s=Array.from(this.routesBySlug.values()),e=t.toLowerCase();return s.filter(a=>t===g?!K(a.fsPath):a.slug.startsWith(`/${e}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=t=>this.templates.get(t);getRequestHandler=t=>this.apiRoutesRequestHandlers.get(t);createTemplate=(t,s)=>(this.templates.set(t,s),t);addBrowserPlugin=t=>{this.browserPlugins.add(t)};createRequestHandler=(t,s)=>(this.apiRoutesRequestHandlers.set(t,s),t);registerServerPropsGetter=(t,s)=>(this.serverPropsGetters.set(t,s),t);registerPagePropsGetter=(t,s)=>{this.pagePropsGetters.set(t,s)};async writeRouteStaticData(t,s){const e=await this.resolveRouteStaticData(t,s,!1);e&&V(t.slug,e,this.outdir)}async resolveRouteStaticData(t,s,e){if(this.serverMode)return N(t.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[t.slug]},resource:f})},r=await t.getStaticData?.(t,a)||{},o=new Set(this.routesDynamicComponents.get(t.slug)),l=this.routesSharedData.get(t.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(t.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await t.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...t.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:e||!t.fsPath?null:await this.lifecycleContext?.fs.getLastModified(t.fsPath)}}addSsrComponents(t,s){if(!t?.length)return;const e=typeof t[0]=="string"?t.join(""):I(t);e&&(s==="head"?this.ssr.headTags.push(e):s==="preBody"?this.ssr.preBodyTags.push(e):this.ssr.postBodyTags.push(e))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const t=[];for(const[e,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[e].entries());t.push([e,r]);break;case"object":e==="config"&&t.push([e,await this.getConfigWithEnvPlaceholders()]),t.push([e,this[e]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(t);return s[E]=G.PLAN_GATES,s}static fromJson(t,s){const e=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":e[r]=new Map(t[r]);break;case"object":if(r==="config"){e.setGlobalConfig(t[r]);break}e[r]=t[r];break;default:throw new Error("Invalid format")}e.config[m]=Z(e.config[m]||{});const a=t[E];return a&&_("PLAN_GATES",a),e}async getConfigWithEnvPlaceholders(){const t=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:e}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=y(t,a);if(o||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=e}return t}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const t=Array.from(this.unsetEnvVars).filter(e=>!Y.includes(e));if(t.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${t.join(", ")}`;await w.panicOnBuildContentError(s)}}function Z(b){return M(b,t=>A.Ast.fromJSON(JSON.stringify(t)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Tt as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
1
|
+
import A from"@markdoc/markdoc";import{getPathnameForLocale as C}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as g}from"../constants/common.js";import{DEFAULT_TITLE as T}from"./constants/common.js";import{GATED_MARKDOC_TAGS as D}from"./constants/entitlements.js";import{isObject as O}from"../utils/guards/is-object.js";import{mapObject as M}from"../utils/object/map-object.js";import{getValueDeep as y}from"../utils/object/get-value-deep.js";import{removeTrailingSlash as L}from"../utils/url/remove-trailing-slash.js";import{normalizeRouteSlug as h}from"../utils/path/normalize-route-slug.js";import{isLocalLink as S}from"../utils/path/is-local-link.js";import{reporter as w}from"./tools/notifiers/reporter.js";import{logger as u}from"./tools/notifiers/logger.js";import{sha1 as k}from"./utils/crypto/sha1.js";import{envConfig as _,setEnv as G}from"./config/env-config.js";import{KvService as F}from"./persistence/kv/services/kv-service.js";import{writeSharedData as B}from"./utils/index.js";import{renderComponents as I}from"./ssr/render.js";import{readStaticData as N,writeStaticData as V}from"./utils/static-data.js";import{parseAndResolveMarkdoc as j}from"./plugins/markdown/compiler.js";import{getMarkdocOptions as H}from"./plugins/markdown/markdoc/markdoc-options.js";import{EntitlementsProvider as R}from"./entitlements/entitlements-provider.js";import{isL10nPath as K}from"./fs/utils/is-l10n-path.js";import{resolveMetadataGlobs as U}from"./utils/globs.js";import{replaceEnvVariablesDeep as J}from"./utils/envs/replace-env-variables-deep.js";import{findRedirect as q}from"./utils/redirects/find-redirect.js";import{followRedirectChain as x}from"./utils/redirects/follow-redirect-chain.js";import{addWildcardRedirectToTree as W}from"./utils/redirects/add-wildcard-redirect-to-tree.js";import{telemetryTraceStep as $}from"../cli/telemetry/helpers/trace-step.js";const v={routesBySlug:"map",apiRoutes:"object",middleware:"object",routesByFsPath:"map",routesSharedData:"map",globalData:"object",config:"object",ssr:"object",searchFacets:"map",routesPartials:"map",mcpToolHandlers:"map"},m="markdown/partials",z="markdown/partials-deps",E="PLAN_GATES",Y=["OAUTH_CLIENT_ID","OAUTH_CLIENT_SECRET","ORGANIZATION_SLUG","ORGANIZATION_ID","ORG_ID"],Ct="userDefinedApiFunctions";class P{routesBySlug=new Map;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;serverPropsGetters=new Map;pagePropsGetters=new Map;listeners=new Map;globalData={};#s=void 0;config={configFilePath:"",redirects:{},wildcardRedirectsTree:{},access:{rbac:{},requiresLogin:!1},directoryPermissions:{},devLogin:!1,ssoDirect:{}};#r;serverMode;serverOutDir;outdir;buildRevision=0;hasSitemap=!1;compilationErrors=[];#a;userCodeReady;#o=Promise.resolve();#i;#n=Promise.resolve();#c;#e=new Map;constructor({outdir:t,contentDir:s,serverMode:e=!1,serverOutDir:a}){this.#r=s,this.outdir=t,this.serverMode=e,this.serverOutDir=a,this.userCodeReady=new Promise(r=>{this.#a=r})}on(t,s){const e=this.listeners.get(t);e?e.add(s):this.listeners.set(t,new Set([s]))}queueEvent=(t,s,...e)=>{this.#e.set(t+String(s),[t,s,...e])};runListeners=(t,s,...e)=>{for(const a of this.listeners.get(t)||new Set)s?a(s,...e):a(...e)};startPluginsRun(){this.clear(),this.#o=new Promise(t=>{this.#i=t})}waitForPluginsLifecycle(){return Promise.all([this.#o,this.#n])}finishPluginsRun(){this.#i?.();for(const t of this.#e.values())this.runListeners(...t);this.#e.clear()}startEsbuildRun(){this.#n=new Promise(t=>{this.#c=t})}finishEsbuildRun(){this.#c?.()}get contentDir(){if(this.serverMode)throw new Error("contentDir should not be used in server mode");return this.#r}markUserCodeReady(){this.#a?.(!0)}async reloadMarkdocOptions(){await $("build.reload_markdoc_options",async()=>{const t=R.instance(),s=await H(this.serverOutDir),e=Object.fromEntries(Object.entries(s.tags).filter(([a])=>D[a]!=null?t.canAccessFeature(D[a]):!0));this.#s={...s,tags:e}})}get markdocOptions(){return{...this.#s,partials:this.getGlobalConfig(m),themeConfig:this.config.markdown}}setGlobalData=t=>{const s=this.globalData,e={...this.globalData,...t};this.globalData=e,JSON.stringify(e)!==JSON.stringify(s)&&this.queueEvent("global-data-updated",void 0,e)};getGlobalData=()=>this.globalData;getKv=async()=>F.getInstance({baseDbDir:this.serverOutDir});parseMarkdoc=async({input:t,context:s,deps:e,resource:a})=>{const{data:{info:r,ast:o},compoundHash:l}=await j(t,this.markdocOptions,{actions:this,context:s},a);for(const i of r.sharedDataDeps||[]){for(const n of e?.routeSlugs||[])this.addRouteSharedData(n,i,i);for(const n of e?.sharedDataIds||[]){const c=this.sharedDataDeps.get(n)||new Set;c.add(i),this.sharedDataDeps.set(n,c)}}for(const i of r.dynamicMarkdocComponents||[]){for(const n of e?.routeSlugs||[]){const c=this.routesDynamicComponents.get(n)||new Set;c.add(i),this.routesDynamicComponents.set(n,c)}for(const n of e?.sharedDataIds||[]){const c=this.sharedDataMarkdocComponents.get(n)||new Set;c.add(i),this.sharedDataMarkdocComponents.set(n,c)}}if(e?.routeSlugs&&r.partials?.length)for(const i of e.routeSlugs){const n=this.routesPartials.get(i)||[];for(const c of r.partials)n.includes(c)||n.push(c);this.routesPartials.set(i,n)}return{info:r,ast:o,compoundHash:l}};async loadOpenApiDefinitions(t){return(await t.cache.load(".","load-oas-docs")).data}async loadAsyncApiDefinitions(t){return(await t.cache.load(".","asyncapi-docs")).data}setSearchEngine(t){this.searchEngine=t}setSearchFacets=t=>{this.searchFacets=t};setGlobalConfig=t=>{const s=Object.keys(t);for(const o of s)for(const l in this.replacedEnvVars)if(l===o||l.startsWith(`${o}:`)){const i=l.split(":"),{error:n,value:c}=y(t,i);(n||c!==this.replacedEnvVars[l].replaced)&&delete this.replacedEnvVars[l]}const{resolvedObj:e,unsetEnvVars:a,replacedValues:r}=J(t);for(const o of a)this.unsetEnvVars.add(o);Object.assign(this.replacedEnvVars,r),Object.assign(this.config,e)};getConfig=()=>this.config;getGlobalConfig=t=>this.config[t];getSearchFacets=()=>this.searchFacets;addRedirect=(t,s,e={})=>{if(!R.instance().canAccessFeature("redirects")&&t!=="/")return;this.config.redirects||(this.config.redirects={});const o=h(t).toLowerCase();this.config.redirects[o]=s;const{trackOriginalSource:l=!0}=e,i=this.getGlobalConfig("originalRedirectSources");l&&Array.isArray(i)&&!i.includes(o)&&i.push(o),o.endsWith("*")&&W(this.config.wildcardRedirectsTree,o)};getRedirect=t=>{const s=h(t).toLowerCase(),e=q(s,this.config.redirects,this.config.wildcardRedirectsTree);if(!e)return null;if(S(e.to)){const a=h(e.to).toLowerCase();if(!a.endsWith("*")&&x(a,[s],this.config.redirects,this.config.wildcardRedirectsTree).type==="cycle")return null}return{to:e.to,type:e.type}};createSharedData=async(t,s,e)=>{if(e&&this.#t[t]===e)return t;const a=JSON.stringify(s),r=e??k(a);return this.#t[t]===r||(this.#t[t]=r,await B(t,a,this.outdir),this.queueEvent("shared-data-updated",t)),t};addRouteSharedData=(t,s,e)=>{const a=L(t),r=this.routesSharedData.get(a)||{};r[s]=e,this.routesSharedData.set(a,r),u.verbose(`Adding shared data to ${t}, ${s}, ${e}`)};getRouteSharedDataByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.routesSharedData.get(s)||{}:{}};getPartialsForRoute=t=>{const s=this.getGlobalConfig(m)||{},e=this.routesPartials.get(t);if(!e||e.length===0)return{};const a=this.getGlobalConfig(z)||{},r=new Set(e),o=Array.from(e);for(let i=0;i<o.length;i++){const n=o[i],c=a[n]?.partials??[];for(const d of c)r.has(d)||(r.add(d),o.push(d))}const l={};for(const i of r)s[i]&&(l[i]=s[i]);return l};addRoute=t=>{const e={...U(t.fsPath,this.config.metadataGlobs),...t.metadata||{}};this.newRoutes.push({...t,metadata:e}),u.verbose("Created route %s",t.slug)};addRouteSharedDataToAllLocales=(t,s,e)=>{const a=[g,...this.lifecycleContext?.fs.localeFolders||[]].map(r=>({code:r,name:r}));for(const r of a){const o=C(t,g,r.code,a);this.addRouteSharedData(o,s,e)}};addApiRoute=t=>{this.apiRoutes.push(t),u.verbose("Created API route %s",t.slug)};addMcpTools=(t,s)=>{for(const e of s)this.mcpToolHandlers.set(e.name,{...e,importPath:t}),u.verbose("Created MCP tool %s",e.name)};getMcpTools=()=>Array.from(this.mcpToolHandlers.values());addMiddleware=t=>{this.middleware.push(t),u.verbose("Created middleware %s",t.id)};getRouteByFsPath=t=>{const s=this.routesByFsPath.get(t);return s?this.getRouteBySlug(s):void 0};getRouteBySlug=(t,s={})=>{const{followRedirect:e=!0}=s,a=this.getRedirect(t);return e&&a?this.routesBySlug.get(h(a.to)):this.routesBySlug.get(t)};hasRouteOrRedirectBySlug=t=>{if(this.routesBySlug.has(t))return!0;const s=this.getRedirect(t);if(!s)return!1;if(!S(s.to))return!0;const e=h(s.to);return this.routesBySlug.has(e)};getRoutesByTemplateId=t=>this.newRoutes.filter(s=>s.templateId===t);getAllRoutesForLocale=(t=g)=>{const s=Array.from(this.routesBySlug.values()),e=t.toLowerCase();return s.filter(a=>t===g?!K(a.fsPath):a.slug.startsWith(`/${e}`))};getAllRoutes=()=>Array.from(this.routesBySlug.values());getAllApiRoutes=()=>this.apiRoutes;getAllMiddleware=()=>this.middleware;getTemplate=t=>this.templates.get(t);getRequestHandler=t=>this.apiRoutesRequestHandlers.get(t);createTemplate=(t,s)=>(this.templates.set(t,s),t);addBrowserPlugin=t=>{this.browserPlugins.add(t)};createRequestHandler=(t,s)=>(this.apiRoutesRequestHandlers.set(t,s),t);registerServerPropsGetter=(t,s)=>(this.serverPropsGetters.set(t,s),t);registerPagePropsGetter=(t,s)=>{this.pagePropsGetters.set(t,s)};async writeRouteStaticData(t,s){const e=await this.resolveRouteStaticData(t,s,!1);e&&V(t.slug,e,this.outdir)}async resolveRouteStaticData(t,s,e){if(this.serverMode)return N(t.slug,this.outdir);const a={...this,contentDir:this.contentDir,parseMarkdoc:({input:c,context:d,resource:f})=>this.parseMarkdoc({input:c,context:d,deps:{routeSlugs:[t.slug]},resource:f})},r=await t.getStaticData?.(t,a)||{},o=new Set(this.routesDynamicComponents.get(t.slug)),l=this.routesSharedData.get(t.slug)||{};for(const c of Object.values(l)){const d=this.sharedDataMarkdocComponents.get(c);d&&d.forEach(p=>o.add(p));const f=this.sharedDataDeps.get(c);f&&f.forEach(p=>this.addRouteSharedData(t.slug,p,p))}const i=this.getGlobalConfig("seo"),n=r?.frontmatter||{};return{...r,frontmatter:{...n,seo:{...n?.seo,title:n?.seo?.title||await t.getNavText?.()}},props:{...r.props,dynamicMarkdocComponents:Array.from(o),metadata:{...r?.props?.metadata,...t.metadata},seo:{title:T,...i,...r.props?.seo},compilationErrors:this.compilationErrors},lastModified:e||!t.fsPath?null:await this.lifecycleContext?.fs.getLastModified(t.fsPath)}}addSsrComponents(t,s){if(!t?.length)return;const e=typeof t[0]=="string"?t.join(""):I(t);e&&(s==="head"?this.ssr.headTags.push(e):s==="preBody"?this.ssr.preBodyTags.push(e):this.ssr.postBodyTags.push(e))}clear=()=>{this.routesByFsPath.clear(),this.templates.clear(),this.newRoutes=[],this.routesBySlug.clear(),this.apiRoutes=[],this.middleware=[],this.routesSharedData.clear(),this.sharedDataDeps.clear(),this.sharedDataMarkdocComponents.clear(),this.routesDynamicComponents.clear(),this.routesPartials.clear(),this.config.redirects={},this.config.wildcardRedirectsTree={},this.config.directoryPermissions={},this.ssr={preBodyTags:[],postBodyTags:[],headTags:[]}};async toJson(){const t=[];for(const[e,a]of Object.entries(v))switch(a){case"map":const r=Array.from(this[e].entries());t.push([e,r]);break;case"object":e==="config"&&t.push([e,await this.getConfigWithEnvPlaceholders()]),t.push([e,this[e]]);break;default:throw new Error("Invalid format")}const s=Object.fromEntries(t);return s[E]=_.PLAN_GATES,s}static fromJson(t,s){const e=new P(s);for(const[r,o]of Object.entries(v))switch(o){case"map":e[r]=new Map(t[r]);break;case"object":if(r==="config"){e.setGlobalConfig(t[r]);break}e[r]=t[r];break;default:throw new Error("Invalid format")}e.config[m]=Z(e.config[m]||{});const a=t[E];return a&&G("PLAN_GATES",a),e}async getConfigWithEnvPlaceholders(){const t=JSON.parse(JSON.stringify(this.config));for(const s in this.replacedEnvVars){const{original:e}=this.replacedEnvVars[s],a=s.split(":"),r=a.pop(),{error:o,value:l}=y(t,a);if(o||!O(l)&&!Array.isArray(l)){await w.panicOnBuild(`Failed to replace env var with env name for ${s}`);continue}l[r]=e}return t}async reportUnsetEnvVars(){if(this.unsetEnvVars.size===0)return;const t=Array.from(this.unsetEnvVars).filter(e=>!Y.includes(e));if(t.length===0)return;const s=`Failed to resolve config. The following environment variables are not set: ${t.join(", ")}`;await w.panicOnBuildContentError(s)}}function Z(b){return M(b,t=>A.Ast.fromJSON(JSON.stringify(t)))}export{m as MARKDOC_PARTIALS_DATA_KEY,z as MARKDOC_PARTIALS_DEPS_KEY,P as Store,Ct as USER_DEFINED_API_FUNCTIONS_COUNTER_KEY};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AsyncApiRealmAPI as o}from"@redocly/realm-asyncapi-sdk";import{envConfig as e}from"../config/env-config.js";import{PACKAGE_NAME as t}from"../../config/product-gates.js";import{OTEL_TRACES_DEV_URL as i,TELEMETRY_ENABLED as s}from"../constants/common.js";class
|
|
1
|
+
import{AsyncApiRealmAPI as o}from"@redocly/realm-asyncapi-sdk";import{envConfig as e}from"../config/env-config.js";import{PACKAGE_NAME as t}from"../../config/product-gates.js";import{OTEL_TRACES_DEV_URL as i,TELEMETRY_ENABLED as s}from"../constants/common.js";class E extends o.Telemetry{constructor(){super(),this.updateCloudEventData(()=>({organizationId:e.ORGANIZATION_ID||"",organizationSlug:e.ORGANIZATION_SLUG||"",projectId:e.PROJECT_ID||"",projectSlug:e.PROJECT_SLUG||"",origin:"realmApi",actor:{id:"Anonymous",object:"user",uri:""},source:"server",env:e.REDOCLY_ENV}))}initialize(r=!1){this.init({otel:{serviceName:"realm-server",serviceVersion:`${t}@${e.REDOCLY_PORTAL_VERSION||""}`,collectorTraceUrl:r?i:e.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces",isProd:e.isProductionEnv,version:"1.0",tracerName:"server-telemetry",delayMillis:100},disabled:r?!e.TELEMETRY_DEV_DEBUG:!s})}}const A=new E;export{A as telemetry};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
`},
|
|
3
|
-
`},
|
|
1
|
+
import*as g from"node:path";import{envConfig as R}from"../../config/env-config.js";import{maskEmail as E}from"./helpers/privacy/mask-email.js";import{maskSubject as T}from"./helpers/privacy/mask-subject.js";import{removePii as C}from"./helpers/privacy/remove-pii.js";import{removePiiFromUrl as $}from"./helpers/privacy/remove-pii-from-url.js";import{red as x,green as A,bold as j,blue as p,gray as i,yellow as P,cyan as w}from"./helpers/colors.js";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 b={[n.VERBOSE]:0,[n.HTTP]:1,[n.INFO]:2,[n.SUCCESS]:2,[n.WARN]:3,[n.ERROR]:4};function W(e,s){return b[e]>=b[s]}function L(e){if(!e)return;const s=e.toUpperCase();if(s in n)return s}const F={[n.INFO]:p,[n.SUCCESS]:A,[n.WARN]:P,[n.ERROR]:x,[n.HTTP]:w,[n.VERBOSE]:i},I={"%ap":e=>p(g.resolve(e)),"%rp":e=>p(g.relative(process.cwd(),e)),"%s":e=>e?.toString(),"%c":e=>p(e)},v={format(e){switch(R.REDOCLY_LOG_FORMAT){case"JSON":return M(e);default:return H(e)}},interpolate(e,...s){const a=Object.keys(I).map(t=>`(${t})`).join("|"),m=new RegExp(a,"g");let o,u=e;for(;(o=m.exec(e))!==null;){o.index===m.lastIndex&&m.lastIndex++;const t=s.shift();if(t===void 0)break;const r=o[0];u=u.replace(r,I[r](t))}return u}};var z=v;const H=e=>{const{level:s,message:a,duration:m,context:o}=e,u=R.isRuntimeMode,t=[F[s](j(`[${s.toLowerCase()}]`))];if(u&&t.push(i(`time="${N()}"`)),o){const{email:r,ipAddress:f,subject:l,method:d,pathname:c,statusCode:S,teams:h,apiFunction:O}=o;O&&t.push(p(`fn="${O}"`)),S&&t.push(U(S)),e.level===n.HTTP&&(d&&t.push(i(`method="${d}"`)),c&&t.push(i(`path="${$(c)}"`))),f&&t.push(i(`ip="${f}"`)),r&&t.push(i(`email="${E(r)}"`)),l&&t.push(i(`sub="${T(l)}"`)),h?.length&&t.push(i(`teams="${h.join(", ")}"`))}if(a){const r=u?`msg="${String(C(a)).replaceAll?.('"','\\"')}"`:String(a);t.push(r)}return e.level===n.HTTP&&o?.userAgent&&t.push(i(`agent="${o.userAgent}"`)),m&&t.push(y(m)),t.join(" ")+`
|
|
2
|
+
`},M=({context:e,message:s,...a})=>{const{method:m,pathname:o,statusCode:u,userAgent:t,subject:r,email:f,teams:l,apiFunction:d}=e||{},c={...a,email:f&&E(f),subject:r&&T(r),teams:l,apiFunction:d,...a.level===n.HTTP?{method:m,pathname:String($(o)),statusCode:u,userAgent:t}:{message:String(C(s))}};return R.isRuntimeMode&&(c.time=N()),JSON.stringify(c,["time","level","scope","message","duration","method","pathname","statusCode","userAgent","subject","ipAddress","email","apiFunction"])+`
|
|
3
|
+
`},U=e=>(e%500<100?x:e%400<100?P:A)(`status="${e}"`),N=()=>{let e=new Date().getTimezoneOffset()*6e4;return new Date(Date.now()-e).toISOString().slice(0,-1)},y=e=>i(`dur="${Math.round(e)}ms"`);export{n as LogLevel,z as default,L as parseLogLevel,W as shouldLog};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createColors as e}from"colorette";import{envConfig as l}from"../../../config/env-config.js";const r=l.
|
|
1
|
+
import{createColors as e}from"colorette";import{envConfig as l}from"../../../config/env-config.js";const r=l.REDOCLY_LOG_FORMAT!=="JSON",{red:s,green:t,bold:c,blue:n,gray:a,yellow:g,cyan:C}=e({useColor:r}),d=o=>typeof o=="string"?o.replace(/\x1B[[(?);]{0,2}(;?\d)*./g,""):o;export{n as blue,c as bold,r as colorsAreEnabled,C as cyan,a as gray,t as green,s as red,d as stripColors,g as yellow};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Env vars that are set as the strings `"true"` or `"false"`, parsed to booleans.
|
|
4
|
+
* Any other value fails validation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function envBooleanStringOptional(): z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "true" | "false" | undefined>;
|
|
7
|
+
export declare function envBooleanStringDefaultFalse(): z.ZodEffects<z.ZodDefault<z.ZodEnum<["true", "false"]>>, boolean, "true" | "false" | undefined>;
|
|
8
|
+
/**
|
|
9
|
+
* Like {@link envBooleanStringOptional}, but also accepts `"1"` as true (common for `CI`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function envCiBooleanOptional(): z.ZodEffects<z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"true">, z.ZodLiteral<"false">, z.ZodLiteral<"1">]>>, boolean | undefined, "1" | "true" | "false" | undefined>;
|
|
12
|
+
//# sourceMappingURL=env-boolean-string.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{z as n}from"zod";const t=n.enum(["true","false"]);function o(){return t.optional().transform(e=>e===void 0?void 0:e==="true")}function a(){return t.default("false").transform(e=>e==="true")}function l(){return n.union([n.literal("true"),n.literal("false"),n.literal("1")]).optional().transform(e=>e===void 0?void 0:e==="true"||e==="1")}export{a as envBooleanStringDefaultFalse,o as envBooleanStringOptional,l as envCiBooleanOptional};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as n from"dotenv";import*as a from"path";import{simpleGit as
|
|
1
|
+
import*as n from"dotenv";import*as a from"path";import{simpleGit as v}from"simple-git";import{envConfig as i,reloadEnvConfig as o}from"../../config/env-config.js";import{sanitizeBranchName as p}from"../../utils/envs/sanitize-branch-name.js";async function m(e){try{return(await v(e??process.cwd()).revparse(["--abbrev-ref","HEAD"])).trim()}catch{return""}}async function d(e){n.config({path:a.resolve(e??"",".env")}),o();const t=i.PUBLIC_REDOCLY_BRANCH_NAME||await m(e);if(t){const s=p(t);n.config({path:a.resolve(e??"",`.env.branch.${s}`),override:!0}),o()}const c=i.REDOCLY_ENV;let r;switch(c){case"production":r=".env.production";break;case"preview":r=".env.preview";break;case"development":default:r=".env.development";break}n.config({path:a.resolve(e??"",r),override:!0}),o()}export{d as loadEnvVariables};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{envConfig as
|
|
1
|
+
import{envConfig as n}from"../config/env-config.js";function e(){return n.NEW_CATALOG_ENABLED??!1}export{e as isCatalogEntitiesEnabled};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{envConfig as e}from"../config/env-config.js";import{isCatalogEntitiesEnabled as
|
|
1
|
+
import{envConfig as e}from"../config/env-config.js";import{isCatalogEntitiesEnabled as a}from"./is-catalog-entities-enabled.js";function t(r){return a()&&(e.NEW_SCORECARDS_ENABLED??!1)&&Array.isArray(r.scorecards)&&r.scorecards.length>0}export{t as isScorecardsEnabled};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as t from"path";import{cliCommandNames as r}from"../../constants/common.js";import{PUBLIC_STATIC_FOLDER as i}from"../constants/common.js";import{logger as n}from"../tools/notifiers/logger.js";import{blue as f,gray as l}from"../tools/notifiers/helpers/colors.js";import{loadEnvVariables as p}from"./envs/load-env-variables.js";import{copyFolderRecursiveSync as c}from"./fs.js";import{validateInstalledVersion as s}from"./validate-installed-version.js";import{PACKAGE_NAME as E}from"../../config/product-gates.js";import{PORTAL_VERSION as P}from"../version.js";import{setEnv as u}from"../config/env-config.js";function L(o){return o?"true":"false"}function d(o){const e={};o["log-level"]&&(e.REDOCLY_LOG_LEVEL=String(o["log-level"])),e.INSPECT_MODE="inspect"in o?L(o.inspect):"false",o.pathPrefix&&(e.REDOCLY_PREFIX_PATHS=o.pathPrefix),u(e)}function v({contentDir:o,outdir:e}){c(t.join(o,i),t.join(e,i))}async function S(o,e,m){await p(e["project-dir"]);const a=o===r.DEVELOP?" Previewing with":"Building with";switch(n.logInFooter("product",`${a} ${f(`${E}@${P}`)}`),n.logInFooter("server",` \u{1F310} Preview URL: ${l("server starting...")}`),o){case r.DEVELOP:case r.BUILD:case r.PREPARE:d(e);break;default:break}await s(),v(m)}export{S as beforeCommand};
|
package/dist/server/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as o}from"module";import{envConfig as r}from"./config/env-config.js";const i=r.REDOCLY_INTERNAL_DEV
|
|
1
|
+
import{createRequire as o}from"module";import{envConfig as r}from"./config/env-config.js";const i=r.REDOCLY_INTERNAL_DEV?"local":o(import.meta.url)("../../package.json").version;export{i as PORTAL_VERSION};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetryTraceStep as
|
|
1
|
+
import{telemetryTraceStep as y}from"../../../telemetry/helpers/trace-step.js";import{parseFilterQuery as u}from"../../../providers/database/pagination/filter.js";import{extractEqualFilterClauseValue as f}from"../../../providers/database/pagination/utils/extract-equal-filter-clause-value.js";import{CatalogEntitiesService as c}from"../../../plugins/catalog-entities/database/catalog-entities-service.js";function p(o){return async e=>y("catalog_entities.bff.revisions.get_entity_revisions",async t=>{const l=await c.getInstance({baseDbDir:o.serverOutDir}),r=e.req.query("filter");let i;try{i=u(typeof r=="string"?r:"",["catalogEntityKey"])}catch{return t?.error(new Error("Invalid filter")),e.json({message:"Invalid filter"},400)}const n=f(i,"catalogEntityKey");if(!n)return t?.error(new Error("Missing catalogEntityKey in filter")),e.json({message:"The filter query must include a non-empty catalogEntityKey clause, for example filter=catalogEntityKey:my-entity."},400);const s=e.req.query("version")??null;t?.setAttribute("queryParams",JSON.stringify({version:s,filter:r}));const a=await l.listEntityRevisions(n,s);return t?.setAttribute("totalRevisions",a.length),e.json({items:a})})}export{p as bffCatalogRevisionsHandler};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Context } from 'hono';
|
|
2
|
-
|
|
2
|
+
import type { Store } from '../../store.js';
|
|
3
|
+
export declare function corsProxyHandler(store?: Store, proxyBasePath?: string): (ctx: Context) => Promise<Response>;
|
|
3
4
|
export declare function isPrivateIp(ip: string): boolean;
|
|
4
5
|
export declare function resolveCorsProxyTarget(requestUrl: string, proxyBasePath: string): URL | null;
|
|
5
6
|
export declare const CORS_PROXY_STREAM_HEADER = "x-redocly-proxy-streaming";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
Usage: ${
|
|
1
|
+
import x from"node:dns";import{isIP as $}from"node:net";import{withPathPrefix as D}from"@redocly/theme/core/utils";import{ServerRoutes as L}from"../../../constants/common.js";import{envConfig as E}from"../../config/env-config.js";import{getRequestOrigin as k}from"../utils/get-request-origin.js";const A=new Set(["connection","keep-alive","proxy-authenticate","proxy-connection","proxy-authorization","te","trailer","transfer-encoding","upgrade","host"]),I=new Set(["cookie","cookie2","accept-encoding"]),M=new Set(["set-cookie","set-cookie2","content-encoding","content-length"]),y="x-redocly-proxy-streaming",H="x-http-method-override",S="x-redocly-cookie";function ee(o,e=D(L.CORS_PROXY)){return async t=>{const r=new URL(t.req.url).pathname;if(r===e||r===`${e}/`)return t.text(`Realm CORS proxy endpoint.
|
|
2
|
+
Usage: ${e}/https://api.example.com/path`);const s=j(t.req.url,e);if(!s)return t.text("Invalid proxied URL",400);const a=o?.getConfig().corsProxy?.allowedTargets;if(a&&a.length>0&&!a.some(u=>X(s,u)))return t.text("Target URL is not in the allowed list for CORS proxy",403);const f=k(t),h=s.origin===f,m=s.pathname===e||s.pathname.startsWith(`${e}/`);if(h&&!m)return new Response("Please use a direct request",{status:308,headers:{Location:s.toString(),Vary:"origin","Cache-Control":"private"}});const l=await N(s.hostname);if((!E.isDevelopMode||E.isReunite)&&l&&Y(l))return t.text("Requests to private network addresses are not allowed",403);const i=new Headers,P=v(t.req.raw.headers);for(const[n,u]of t.req.raw.headers)P.has(n.toLowerCase())||I.has(n.toLowerCase())||i.append(n,u);const g=i.get(S);if(g){const n=t.req.raw.headers.get("cookie")||"";i.set("cookie",n?`${n}; ${g}`:g),i.delete(S)}const O=t.req.raw.headers.get("origin")||"";z(O)&&i.delete("origin");let p=t.req.method;const R=i.get(H);R&&(p=R.toUpperCase(),i.delete(H));const w={method:p,headers:i,redirect:"manual"};p!=="GET"&&p!=="HEAD"&&t.req.raw.body&&(w.body=t.req.raw.body,w.duplex="half");let c;try{c=await fetch(s,w)}catch(n){const u=n instanceof Error?n.message:"unknown error",_=n instanceof Error&&n.cause instanceof Error?`: ${n.cause.message}`:"";return t.text(`Failed to proxy request: ${u}${_}`,502)}const T=c.headers.get("content-type")||"";if(V(T)&&t.req.raw.headers.get("sec-fetch-mode")==="navigate")return t.text("Direct browser navigation to proxied HTML or JavaScript content is not allowed",403);const d=new Headers(c.headers),q=v(c.headers);for(const n of q)d.delete(n);for(const n of M)d.delete(n);return d.set(y,"1"),d.set("x-content-type-options","nosniff"),d.has("content-type")||d.set("content-type","text/plain"),new Response(c.body,{status:c.status,statusText:c.statusText,headers:d})}}function W(o){try{return decodeURIComponent(o)}catch{return o}}function b(o){return o.replace(/^(https?):\/(?!\/)/i,"$1://")}function U(o,e){return e?o.includes("?")?e==="?"?o:`${o.endsWith("?")||o.endsWith("&")?o:`${o}&`}${e.slice(1)}`:`${o}${e}`:o}function v(o){const e=new Set(A),t=o.get("connection");if(!t)return e;for(const r of t.split(",")){const s=r.trim().toLowerCase();s&&e.add(s)}return e}function z(o){const e=o.toLowerCase();return e.includes(".redocly.app")||e.includes("localhost")}async function N(o){if($(o))return o;try{const{address:e}=await x.promises.lookup(o);return e}catch{return null}}function Y(o){const e=o.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i);return e?C(e[1]):o.includes(":")?F(o):C(o)}function C(o){const e=o.split(".").map(Number);if(e.length!==4||e.some(s=>isNaN(s)))return!0;const[t,r]=e;return t===0||t===10||t===127||t===172&&r>=16&&r<=31||t===192&&r===168||t===169&&r===254||t===100&&r>=64&&r<=127}function F(o){const e=o.toLowerCase();return e==="::1"||e==="::"||e.startsWith("fc")||e.startsWith("fd")||e.startsWith("fe80")}function X(o,e){let t;try{t=new URL(e)}catch{return!1}if(o.origin!==t.origin)return!1;const r=t.pathname.endsWith("/")?t.pathname:`${t.pathname}/`;return o.pathname.startsWith(r)||o.pathname===t.pathname}function V(o){const e=o.toLowerCase();return e.includes("text/html")||e.includes("javascript")||e.includes("application/xhtml")||e.includes("application/xml")||e.includes("image/svg")}function j(o,e){const t=new URL(o),r=t.pathname===e,s=t.pathname.startsWith(`${e}/`);if(!r&&!s)return null;const a=t.pathname.slice(e.length).replace(/^\/+/,"");if(!a)return null;const f=[a,W(a)];for(const h of f){const m=b(h),l=U(m,t.search);try{const i=new URL(l);if(i.protocol==="http:"||i.protocol==="https:")return i}catch{continue}}return null}const te=y;export{te as CORS_PROXY_STREAM_HEADER,ee as corsProxyHandler,Y as isPrivateIp,j as resolveCorsProxyTarget};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import l from"path";import{REDOCLY_ROUTE_RBAC as
|
|
1
|
+
import l from"path";import{REDOCLY_ROUTE_RBAC as _,REDOCLY_TEAMS_RBAC as T}from"@redocly/config";import{withoutPathPrefix as G,withPathPrefix as Y}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_CACHE_HEADER_VALUE as I,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as $}from"../../constants/common.js";import{removeTrailingSlash as k}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as N}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as V}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as W}from"../../config/env-config.js";import{sanitizePath as X}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as j}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as Z}from"../../../utils/path/is-path-in-folder.js";import{getLlmsTxtMdPathBySlug as J}from"../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";import{removeLeadingSlash as S}from"../../../utils/url/remove-leading-slash.js";import{processRedirects as K}from"./helpers/process-redirects.js";import{renderPage as Q,getServerProps as x}from"../../ssr/index.js";import{canAccessAsset as ee,canAccessResource as U}from"../../utils/rbac.js";import{handleErrorPageRender as M,handleUnauthorized as b,handleUnauthorizedAsset as q}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as te,MIME_TYPES as ne}from"../mime-types.js";import{fileExistsAsync as v}from"../../utils/index.js";import{isAiAgentRequest as oe}from"../../utils/ai-agent-detection.js";import{getRedirectRoute as re}from"../utils/legacy-openapi-redirects.js";import{getContentTypeHeaderValue as ae}from"../utils/content-type.js";import{telemetry as ie}from"../../../cli/telemetry/index.js";import{telemetry as se}from"../../telemetry/index.js";function De(e,D,O){return async n=>{const A=n.get("logger"),a=n.req,i=new URL(a.url),r=G(X(decodeURIComponent(i.pathname))),R=l.parse(r).ext===".md",C=oe({accept:a.header("accept"),signatureAgent:a.header("signature-agent"),signature:a.header("signature"),signatureInput:a.header("signature-input"),userAgent:a.header("user-agent")}),m=j(r),o=(a.method==="GET"||a.method==="HEAD")&&!R?e.getRouteBySlug(m,{followRedirect:!1})||N(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(r===t.slug||r.startsWith(t.slug+"/"))):void 0,E=e.getRedirect(m);if(E){const t=K({redirect:E,reqUrlSearch:i.search});return se.sendRedirectMessage([{object:"redirect",from:m,templateId:t.type.toString()}]),n.newResponse(null,t.type,{Location:t.location})}const f=W.isProductionEnv?301:302;if(o?.metadata?.type==="openapi"){const t=re(i.pathname);if(t)return A.info("Legacy OpenAPI docs redirect from "+i.pathname),n.newResponse(null,f,{Location:encodeURI(t)});if(i.pathname.match(/[A-Z]/))return A.warn("Redirect to lowercase route to avoid 404 error"),n.newResponse(null,f,{Location:encodeURI(i.pathname.toLowerCase())})}if(r.endsWith("/")&&r!=="/"){const t=V(new URL(m||"/",n.req.url).pathname);return n.newResponse(null,f,{Location:encodeURI(Y((t==="/"?"/":k(t))+i.search))})}const u=o&&C?J(o.slug):void 0,w=u?await v(l.resolve(e.outdir,S(u))):!1,{isAuthenticated:d,teams:g,claims:{email:p}}=n.get("auth");if(o&&!U(o,{isAuthenticated:d,email:p,teams:g},e.config.access?.rbac,e.config.access?.requiresLogin))return d?M(n,e,{slug:o.slug,[T]:o[T],[_]:o[_]},403):b(n,e,o.slug);if(o&&(!C||!w)){const t=await D(o),c=await x(o,n,t,e),{html:B,statusCode:z}=await Q(o,c,n,e,ie);return n.html(B,z,{"Cache-Control":I})}const L=u&&w?u:r,F=S(L),s=l.resolve(e.outdir,F);if(!Z(s,e.outdir))return q(n);if(R){const t=r==="index.html.md"?"/":r.replace(/\.md$/,""),c=e.getRouteBySlug(t,{followRedirect:!1});if(c&&!U(c,{isAuthenticated:d,email:p,teams:g},e.config.access?.rbac,e.config.access?.requiresLogin))return b(n,e,r)}const P=e.getGlobalConfig("access");if(!ee(L,P?.rbac||{},P?.requiresLogin||!1,e.getGlobalConfig("directoryPaths"),{isAuthenticated:d,email:p,teams:g}))return q(n);const y=ne[l.extname(s)]||"text/plain",h=s.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||s.match(/runtime\/chunks\/.*/)?$:te[y],H=h?{"Cache-Control":`public, max-age=${h}, immutable`,Expires:new Date(Date.now()+h*1e3).toUTCString()}:{"Cache-Control":I};if(await v(s)){const t=a.query("download")!=null,c=await O(s);return n.newResponse(c,200,{"Content-Type":ae(y),"Access-Control-Allow-Origin":"*",...H,...t&&{"Content-Disposition":`attachment; filename="${l.basename(s)}"`}})}else return M(n,e,{slug:m},404)}}export{De as dynamicRouteHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{FEEDBACK_API_URL as _}from"../../constants/common.js";import{MAX_CONTEXT_LENGTH as g,MAX_EMAIL_LENGTH as C,MAX_LANG_LENGTH as
|
|
1
|
+
import{FEEDBACK_API_URL as _}from"../../constants/common.js";import{MAX_CONTEXT_LENGTH as g,MAX_EMAIL_LENGTH as C,MAX_LANG_LENGTH as N,MAX_PATH_LENGTH as j,MAX_REASONS_COUNT as E}from"../../constants/feedback.js";import{mapObject as S}from"../../../utils/object/map-object.js";import{getClientIp as T}from"../utils/get-client-ip.js";import{canAccessResource as q}from"../../utils/rbac.js";function a(e,n){if(e!=null)return String(e).replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g,"").trim().slice(0,n)||void 0}function w(e){if(!e)return e;const n=["userAgent","firstName","lastName","auth_time","platform","id","email","ipAddress"];return S(e,(t,r)=>n.includes(r)?t:"*****")}function I({component:e,path:n,location:t,lang:r,score:u,max:i,reasons:s,comment:m,metadata:o,email:l}){const c=Array.isArray(s)?s.map(d=>a(String(d),g)).filter(d=>!!d).slice(0,E):void 0;return{feedbackComponent:e.toUpperCase(),path:a(n,j),location:a(t,g),lang:a(r,N),score:typeof u=="number"?u:void 0,maxScore:typeof i=="number"?i:void 0,reasons:c?.length?c:void 0,comment:a(m,g),email:a(l,C),metadata:w(o)}}async function L(e,n){return(await fetch(_,{method:"POST",body:JSON.stringify(I(e)),headers:n})).json()}function G(e){return async n=>{const t=n.get("logger"),r=await n.req.json(),u=n.req.header("user-agent"),i=T(n.req.raw),s=n.req.header("Sec-Ch-Ua-Platform"),m={...r.metadata,userAgent:u,ipAddress:i,platform:s?s.replace(/"/g,""):"unknown"};t.info(`Feedback IP diagnostics ${O(R(n,i??void 0))}`);const o=[];(!r.path||r.path==="")&&o.push("`path` is required");const l=["sentiment","rating","comment","problem","mood","scale"];if(l.includes(r.component)||o.push(`\`component\` field should be one of ${l.join(", ")}.`),o.length)return n.json({errors:o},400);const{claims:c,isAuthenticated:d,teams:A}=n.get("auth"),k={isAuthenticated:d,email:c?.email,teams:A};if(Object.keys(e.config.access?.rbac||{}).length>0){const f=r.path,F=new URL(f).pathname,b=e.getRouteBySlug(F);if(!b)return n.json({errors:["Resource not found"]},404);if(!q(b,k,e.config.access?.rbac,e.config.access?.requiresLogin))return n.json({errors:["Forbidden: no permission to send feedback for resource"]},403)}const y={"Content-Type":"application/json"},h=c?.email||r?.email||m?.email;try{const f=await L({...r,email:h,metadata:{email:h,...m}},y);return n.json({message:"Thanks for your feedback",...f},200,{})}catch(f){return n.json({errors:["Failed to send feedback",f.message]},500)}}}function R(e,n){return{extractedIpAddress:n,xForwardedFor:p(e.req.header("x-forwarded-for")),xRealIp:p(e.req.header("x-real-ip")),trueClientIp:p(e.req.header("true-client-ip")),cfConnectingIp:p(e.req.header("cf-connecting-ip"))}}function O(e){return JSON.stringify(e,(n,t)=>t===void 0?null:t)}function p(e){if(e)return e.slice(0,256)}export{G as feedbackHandler,w as normalizeFeedbackMetadata};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{serveStatic as C}from"hono/serve-static";import{withPathPrefix as e,withoutPathPrefix as H}from"@redocly/theme/core/utils";import{ServerRoutes as i}from"../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as c}from"../../constants/common.js";import{envConfig as L}from"../../config/env-config.js";import{authMiddleware as S}from"../middleware/authMiddleware.js";import{ensureSearchData as g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as P}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as I}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as D,oidcCallbackHandler as h,logoutHandler as O,postLogoutHandler as M,idpLoginHandler as N,redoclyLoginCallbackHandler as v,samlCallbackHandler as B,redoclyTokenLoginHandler as w,inviteHandler as U}from"./auth.js";import{appDataHandler as G}from"./app-data.js";import{searchFacetsHandler as F,searchHandler as y}from"./search.js";import{dynamicRouteHandler as K}from"./dynamic-route.js";import{pageDataHandler as Y,sharedPageDataHandler as k}from"./page-data.js";import{pathPrefixRedirectHandler as b}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as _,resolvePathHandler as E,resolvePathsHandler as V,resolveSlugHandler as T}from"./resolve-route.js";import{feedbackHandler as x}from"./feedback.js";import{loggerMiddleware as $}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as z}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as Z}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as X}from"./otel/otel.js";import{healthCheckHandler as q}from"./health.js";import{askAiHandler as W}from"./ask-ai.js";import{semanticSearchHandler as j}from"./semantic-search.js";import{replayOauth2RedirectCallbackHandler as J}from"./replay-oauth2-redirect.js";import{corsProxyHandler as r}from"./cors-proxy.js";import{mcpOAuthProtectedResourceHandler as Q,mcpOAuthAuthorizationServerHandler as u,mcpDynamicClientRegistrationHandler as aa,mcpAuthorizationHandler as ea,mcpTokenPortalHandler as ia,mcpCallbackHandler as f}from"./mcp-oauth.js";import{corsMiddleware as d}from"../middleware/corsMiddleware.js";import{installApiRoutes as la}from"./api-routes/api-routes.js";import{cookieMiddleware as ta}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ma}from"../routes/static-content.js";import{infoHandler as
|
|
1
|
+
import{serveStatic as C}from"hono/serve-static";import{withPathPrefix as e,withoutPathPrefix as H}from"@redocly/theme/core/utils";import{ServerRoutes as i}from"../../../constants/common.js";import{PUBLIC_STATIC_FOLDER as c}from"../../constants/common.js";import{envConfig as L}from"../../config/env-config.js";import{authMiddleware as S}from"../middleware/authMiddleware.js";import{ensureSearchData as g}from"../middleware/ensureSearchData.js";import{dynamicMiddleware as P}from"../middleware/dynamic-middleware/dynamic-middleware.js";import{installRoutes as I}from"../../plugins/dev-onboarding/api/routes/index.js";import{authorizeHandler as D,oidcCallbackHandler as h,logoutHandler as O,postLogoutHandler as M,idpLoginHandler as N,redoclyLoginCallbackHandler as v,samlCallbackHandler as B,redoclyTokenLoginHandler as w,inviteHandler as U}from"./auth.js";import{appDataHandler as G}from"./app-data.js";import{searchFacetsHandler as F,searchHandler as y}from"./search.js";import{dynamicRouteHandler as K}from"./dynamic-route.js";import{pageDataHandler as Y,sharedPageDataHandler as k}from"./page-data.js";import{pathPrefixRedirectHandler as b}from"./path-prefix-redirect.js";import{getRoutesByLineHandler as _,resolvePathHandler as E,resolvePathsHandler as V,resolveSlugHandler as T}from"./resolve-route.js";import{feedbackHandler as x}from"./feedback.js";import{loggerMiddleware as $}from"../middleware/loggerMiddleware.js";import{responseHeadersMiddleware as z}from"../middleware/responseHeadersMiddleware.js";import{idleTimeoutMiddleware as Z}from"../middleware/idleTimeoutMiddleware.js";import{otelTracesHandler as X}from"./otel/otel.js";import{healthCheckHandler as q}from"./health.js";import{askAiHandler as W}from"./ask-ai.js";import{semanticSearchHandler as j}from"./semantic-search.js";import{replayOauth2RedirectCallbackHandler as J}from"./replay-oauth2-redirect.js";import{corsProxyHandler as r}from"./cors-proxy.js";import{mcpOAuthProtectedResourceHandler as Q,mcpOAuthAuthorizationServerHandler as u,mcpDynamicClientRegistrationHandler as aa,mcpAuthorizationHandler as ea,mcpTokenPortalHandler as ia,mcpCallbackHandler as f}from"./mcp-oauth.js";import{corsMiddleware as d}from"../middleware/corsMiddleware.js";import{installApiRoutes as la}from"./api-routes/api-routes.js";import{cookieMiddleware as ta}from"../middleware/cookieMiddleware.js";import{staticContentHandler as ma}from"../routes/static-content.js";import{infoHandler as R}from"./info.js";import{catalogHandler as na}from"./catalog/catalog.js";import{catalogRelationsHandler as da}from"./catalog/catalog-relations.js";import{bffCatalogHandler as oa}from"./catalog/bff-catalog.js";import{bffCatalogRevisionsHandler as pa}from"./catalog/bff-catalog-revisions.js";import{bffCatalogRelatedEntitiesHandler as Aa}from"./catalog/bff-catalog-related-entities.js";import{catalogAuthMiddleware as t}from"../middleware/catalogAuthMiddleware.js";import{telemetryMiddleware as Oa}from"../middleware/telemetry-middleware.js";import{errorHandler as _a}from"./error.js";function ae(a,l,m){const{resolveRouteData:o,readStaticAsset:p}=m;a.use("*",Z()),a.use("*",ta()),a.use("*",P(l)),a.use("*",S(l)),a.use("*",$()),a.use("*",z(l)),a.use("*",Oa()),a.use(e("*"),C({root:`./${c}`,getContent:(n,s)=>ma(n,s,l,p),rewriteRequestPath:n=>H(n)})),a.use(e(i.FEEDBACK),d({allowMethods:["POST"]})),a.use(e(i.ASK_AI),d({allowMethods:["POST"]})),a.use(e(i.SEMANTIC_SEARCH),d({allowMethods:["POST"]})),a.use("*",Ea(l));const A=g(l);a.use(e(i.INFO),R()),L.NEW_CATALOG_ENABLED&&(a.use(e(i.CATALOG_ENTITIES),t({serverOutDir:l.serverOutDir}),na(l)),a.use(e(i.CATALOG_ENTITIES_RELATIONS),t({serverOutDir:l.serverOutDir}),da(l)),a.get(e(i.BFF_CATALOG_ENTITIES),t({serverOutDir:l.serverOutDir,protectReadMethods:!1}),oa(l)),a.get(e(i.BFF_CATALOG_RELATED_ENTITIES),t({serverOutDir:l.serverOutDir,protectReadMethods:!1}),Aa(l)),a.get(e(i.BFF_CATALOG_REVISIONS),t({serverOutDir:l.serverOutDir,protectReadMethods:!1}),pa(l))),a.get(e(i.SHARED_PAGE_DATA),k(l)),a.get(e(i.PAGE_DATA),Y(l,o)),a.get(e(i.APP_DATA),G(l)),a.post(e(i.SEARCH),A,y(l)),a.post(e(i.SEARCH_FACETS),A,F(l)),a.post(e(i.AUTHORIZATION),D),a.post(e(i.LOGOUT),O(l)),a.get(e(i.LOGOUT),O(l)),a.get(e(i.POST_LOGOUT),M(l)),a.get(e(i.OIDC_CALLBACK),h(l)),a.get(e(i.REDOCLY_TOKEN_LOGIN),w(l)),a.get(e(i.REDOCLY_LOGIN_CALLBACK),v()),a.get(e(i.IDP_LOGIN),N(l)),a.post(e(i.SAML_CALLBACK),B(l)),a.get(e(i.INVITE),U(l)),a.get(e(i.HEALTH),q),a.get(`${i.MCP_OAUTH_PROTECTED_RESOURCE}${e("/mcp")}`,Q()),a.get(i.MCP_OAUTH_AUTHORIZATION_SERVER,u()),a.post(e(i.MCP_DYNAMIC_CLIENT_REGISTRATION),aa()),a.get(e(i.MCP_AUTHORIZATION),ea()),a.post(e(i.MCP_TOKEN_PORTAL),ia()),a.get(e(i.MCP_CALLBACK),f()),a.get(e(`${i.MCP_CALLBACK}/*`),f()),I(a,l),a.all(e(i.CORS_PROXY),r(l)),a.all(e(`${i.CORS_PROXY}/*`),r(l)),la(a,l),a.post(e(i.FEEDBACK),x(l)),a.post(e(i.RESOLVE_ROUTE_BY_PATH),E(l)),a.post(e(i.RESOLVE_ROUTES_BY_PATHS),V(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),T(l)),a.post(e(i.ASK_AI),W(l)),a.post(e(i.SEMANTIC_SEARCH),j(l)),a.get(e(i.GET_ROUTES_BY_LINE),_(l)),a.post(e(i.OTEL_TRACES),X),a.get(e(i.REPLAY_OAUTH2_CALLBACK),J),a.all(e("/*"),K(l,o,p)),a.get("*",b),a.onError(_a)}function Ea(a){return async(l,m)=>{await a.waitForPluginsLifecycle(),await m()}}function ee(a,l){a.get(e(i.INFO),R()),a.post(e(i.RESOLVE_ROUTE_BY_PATH),E(l)),a.post(e(i.RESOLVE_ROUTE_BY_SLUG),T(l)),a.get(e(i.GET_ROUTES_BY_LINE),_(l))}export{ee as installDevRoutes,ae as installProdRoutes,Ea as waitForPluginsLifecycle};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getCookie as
|
|
1
|
+
import{getCookie as f}from"hono/cookie";import{ulid as S}from"ulid";import{AUTH_URL as k,JWT_SECRET_KEY as y}from"../../constants/common.js";import{ServerRoutes as p}from"../../../constants/common.js";import{withPathPrefix as l}from"@redocly/theme/core/utils";import{telemetry as _}from"../../telemetry/index.js";import{envConfig as C}from"../../config/env-config.js";import{createMcpAuthorizationCode as w,verifyMcpAuthorizationCode as A,createMcpSessionResource as u}from"../auth.js";import*as m from"../jwt/jwt.js";import{AlgorithmTypes as T}from"../jwt/types.js";import{getRequestOrigin as M}from"../utils/get-request-origin.js";const n=(e,r,o=200,a)=>e.json(r,o,{"Content-Type":"application/json",...a??{}});async function I(e){const r=Math.floor(Date.now()/1e3);return m.sign({type:"mcp_context",...e,iat:r,exp:r+600},y,T.HS256)}async function P(e){await m.verify(e,y,T.HS256);const{payload:r}=m.decode(e);if(r.type!=="mcp_context")throw new Error("Invalid context token type");return r}function q(){return async e=>{if(e.req.method!=="GET")return n(e,{error:"Method not allowed"},405,{Allow:"GET"});const r=M(e);return n(e,{resource:`${r}${l("/mcp")}`,authorization_servers:[r],bearer_methods_supported:["header"],resource_documentation:`${r}${p.MCP_OAUTH_AUTHORIZATION_SERVER}`,scopes_supported:["openid","profile","email","offline_access"],bearer_token_types_supported:["Bearer"]})}}function b(){return async e=>{const r=M(e);return n(e,{issuer:k||"",authorization_endpoint:`${r}${l(p.MCP_AUTHORIZATION)}`,token_endpoint:`${r}${l(p.MCP_TOKEN_PORTAL)}`,jwks_uri:`${k||""}/.well-known/jwks.json`,registration_endpoint:`${r}${l(p.MCP_DYNAMIC_CLIENT_REGISTRATION)}`,scopes_supported:["openid","profile","email","offline_access"],response_types_supported:["code"],grant_types_supported:["authorization_code","refresh_token","client_credentials"],subject_types_supported:["public"],id_token_signing_alg_values_supported:["RS256"],code_challenge_methods_supported:["S256"]})}}function N(){return async e=>{if(e.req.method!=="POST")return n(e,{error:"Method not allowed"},405);try{return n(e,{client_id:C.OAUTH_CLIENT_ID||"",client_name:"MCP Client",redirect_uris:[],grant_types:["authorization_code","refresh_token"],response_types:["code"],scope:"openid offline email",subject_type:"public",token_endpoint_auth_method:"none",created_at:new Date().toISOString(),updated_at:new Date().toISOString()},201)}catch(r){return n(e,{error:"invalid_request",error_description:r?.message||"Unable to register client"},500)}}}function j(){return async e=>{const r=new URL(e.req.url),{searchParams:o}=r,a=o.get("redirect_uri"),t=S();_.sendMcpAuthorizationStartedMessage([{...u(t),redirect_uri:a||null}]);const i=M(e),c={isMcpFlow:!0,originalRedirectUri:a,mcpClientId:o.get("client_id"),mcpState:o.get("state"),mcpSessionId:t,timestamp:Date.now()};try{const s=await I(c),d=new URL(l(p.IDP_LOGIN),i);return d.searchParams.set("redirectTo",`${p.MCP_CALLBACK}/${s}`),d.searchParams.set("idpId","oidc"),e.redirect(d.toString())}catch(s){const d=s instanceof Error?s.message:String(s),h=s instanceof Error?s.stack:String(s);_.sendMcpAuthorizationFailedMessage([{...u(t),error:d,error_details:h}]);const g=new URL(l(`${k}/oauth2/auth`));return g.search=o.toString(),e.redirect(g.toString())}}}function F(){return async e=>{if(e.req.method!=="POST")return n(e,{error:"Method not allowed"},405);try{const r=await e.req.formData(),o=r.get("grant_type"),a=r.get("code"),t=r.get("redirect_uri")||void 0;if(o!=="authorization_code"||!a)return n(e,{error:"invalid_request",error_description:"Invalid grant type or missing authorization code"},400);try{const i=await A(a);if(t&&t!==i.redirect_uri)return n(e,{error:"invalid_grant",error_description:"redirect_uri mismatch"},400);if(C.OAUTH_CLIENT_ID&&i.client_id&&i.client_id!==C.OAUTH_CLIENT_ID)return n(e,{error:"invalid_client",error_description:"Client mismatch"},400);const c=i.id_token;if(typeof c!="string"||c.length===0)return n(e,{error:"invalid_grant",error_description:"Missing id_token in authorization code"},400);let s=c;if(i.idp_access_token){const{payload:h,header:{kid:g}}=m.decode(c);s=await m.sign({...h,idp_access_token:i.idp_access_token},y,T.HS256,g)}return n(e,{access_token:s,token_type:"Bearer",expires_in:3600,scope:"openid profile email",id_token:c},200,{"Cache-Control":"no-store",Pragma:"no-cache"})}catch{return n(e,{error:"invalid_grant",error_description:"Invalid authorization code"},400)}}catch(r){const o=r instanceof Error?r.message:String(r);return n(e,{error:"server_error",error_description:"Failed to process token request",error_details:o},500)}}}function B(){return async e=>{const r=new URL(e.req.url);let o=r.searchParams.get("context");if(!o&&r.pathname.startsWith(l(`${p.MCP_CALLBACK}/`))){const t=r.pathname.split("/");o=t[t.length-1]}if(!o)return _.sendMcpAuthorizationFailedMessage([{...u(null),error:"Missing context parameter",error_details:null}]),e.text("Missing context parameter",400);let a=null;try{const t=await P(o);if(a=t.mcpSessionId||null,!t.isMcpFlow||!t.originalRedirectUri)throw new Error("Invalid MCP context");const i=f(e,"idp_id_token")||f(e,"authorization"),c=f(e,"idp_access_token"),s=await w({idToken:i||"",idpAccessToken:c||void 0,clientId:t.mcpClientId||"",redirectUri:t.originalRedirectUri,ttlSec:600}),d=new URL(t.originalRedirectUri);return d.searchParams.set("code",s),t.mcpState&&d.searchParams.set("state",t.mcpState),_.sendMcpAuthorizationCompletedMessage([{...u(a),redirect_uri:t.originalRedirectUri||null}]),e.redirect(d.toString())}catch(t){const i=t instanceof Error?t.message:String(t),c=t instanceof Error?t.stack:String(t);return _.sendMcpAuthorizationFailedMessage([{...u(a),error:i,error_details:c}]),e.text(`Invalid MCP callback: ${i}`,400)}}}export{I as createMcpContextToken,j as mcpAuthorizationHandler,B as mcpCallbackHandler,N as mcpDynamicClientRegistrationHandler,b as mcpOAuthAuthorizationServerHandler,q as mcpOAuthProtectedResourceHandler,F as mcpTokenPortalHandler,P as verifyAndParseMcpContextToken};
|
|
@@ -1,19 +1,5 @@
|
|
|
1
|
+
import { AsyncApiRealmAPI } from '@redocly/realm-asyncapi-sdk';
|
|
1
2
|
import type { Context } from 'hono';
|
|
2
|
-
import type { Attribute, Span } from './otlp.js';
|
|
3
3
|
export declare function otelTracesHandler(ctx: Context): Promise<Response>;
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function toSource(userId: string | undefined, sessionId: string): Source;
|
|
6
|
-
type ClientContext = {
|
|
7
|
-
userId: string | undefined;
|
|
8
|
-
clientIp: string | undefined;
|
|
9
|
-
userAgent: string | undefined;
|
|
10
|
-
acceptLanguage: string | undefined;
|
|
11
|
-
locale: string | undefined;
|
|
12
|
-
};
|
|
13
|
-
type Source = {
|
|
14
|
-
id: string;
|
|
15
|
-
object: 'user' | 'anonymous';
|
|
16
|
-
uri: string;
|
|
17
|
-
};
|
|
18
|
-
export {};
|
|
4
|
+
export declare function toActor(userId: string | undefined, sessionId: string): AsyncApiRealmAPI.cloudEvents.CloudEventActor;
|
|
19
5
|
//# sourceMappingURL=otel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{envConfig as
|
|
1
|
+
import{AsyncApiRealmAPI as T}from"@redocly/realm-asyncapi-sdk";import{envConfig as o}from"../../../config/env-config.js";import{getClientIp as R}from"../../utils/get-client-ip.js";import{getAttributesStringValue as v,mergeAttributes as S}from"./otlp.js";const C=o.OTEL_TRACES_URL||"https://otel.cloud.redocly.com/v1/traces";class O extends T.OtelClient{initTracer(){}}let a=null;function h(){return a||(a=new O,a.init({collectorTraceUrl:void 0,serviceName:"realm-ui",serviceVersion:"1.0",isProd:o.isProductionEnv,version:"1.0",tracerName:"attribute-processor"})),a}async function D(e){const n=await e.req.json();return n.resourceSpans?.length&&(w(n,P(e)),await fetch(C,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})),e.newResponse(null,200)}function w(e,n){for(const r of e.resourceSpans){const c=r.resource.attributes.find(i=>i.key==="session_id");if(!c)continue;const d=v(c);if(!d)continue;const l=j(n.userId,d),A=new Date,_={organizationId:o.ORGANIZATION_ID||"",organizationSlug:o.ORGANIZATION_SLUG||"",projectId:o.PROJECT_ID||"",projectSlug:o.PROJECT_SLUG||"",env:o.REDOCLY_ENV||"",source:"urn:redocly:realm:ui",actor:{id:l.id,object:l.object,uri:l.uri},clientIp:n.clientIp,userAgent:n.userAgent,sessionId:d},s=(i,t)=>{const u=i.attributes.find(p=>p.key===t);return u?v(u):""};for(const i of r.scopeSpans)for(const t of i.spans){if(!t.name.startsWith("event.")||t.name==="event.undefined")continue;const u=s(t,"cloudevents.event_spec_version"),p=s(t,"cloudevents.event_object"),g=s(t,"cloudevents.event_data_content_type"),I=s(t,"cloudevents.event_origin"),m=s(t,"cloudevents.event_time"),f=m?new Date(m):A,b={..._,id:s(t,"cloudevents.event_id"),specversion:u,type:t.name.slice(6),object:p,datacontenttype:g,time:f,origin:I},y=h().processAttributes(b,f);S(t,y,{overwrite:!0})}}}function P(e){const n=e.get("auth")?.claims?.id||e.get("auth")?.claims?.sub,r=R(e.req.raw)||e.req.raw.context?.remoteAddr?.hostname,c=e.req.raw.headers.get("user-agent");return{userId:n,clientIp:r??void 0,userAgent:c??void 0}}function j(e,n){if(e)return{id:e,object:"user",uri:`${o.MAIN_API_URL}/users/${e}`};const r=n.replace("ses_","ann_");return{id:r,object:"anonymous",uri:`${o.MAIN_API_URL}/anonymous/${r}`}}export{D as otelTracesHandler,j as toActor};
|
|
@@ -33,6 +33,9 @@ export type IntAttribute = {
|
|
|
33
33
|
export type OptionalAttribute = Attribute | undefined;
|
|
34
34
|
export type EventAttribute = Map<string, Attribute>;
|
|
35
35
|
export declare function toAttribute(key: string, value: number | string | undefined | null): OptionalAttribute;
|
|
36
|
-
export declare function
|
|
36
|
+
export declare function mergeAttributes(span: Span, attrs: Record<string, string | number | null | undefined>, { overwrite }?: {
|
|
37
|
+
overwrite?: boolean;
|
|
38
|
+
}): void;
|
|
39
|
+
export declare function getAttributesStringValue(attr: Attribute): string;
|
|
37
40
|
export declare function getAttributesIntValue(attr?: Attribute): number | undefined;
|
|
38
41
|
//# sourceMappingURL=otlp.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function f(e,n){if(n!=null)return typeof n=="number"?{key:e,value:{intValue:n}}:{key:e,value:{stringValue:n}}}function l(e,n,{overwrite:o=!1}={}){for(const[u,i]of Object.entries(n)){const r=e.attributes.findIndex(t=>t.key===u);if(r!==-1){if(!o)continue;const t=f(u,i);t&&(e.attributes[r]=t)}else{const t=f(u,i);t&&e.attributes.push(t)}}}function s(e){return"stringValue"in e.value?e.value.stringValue:""}function a(e){if(e?.value&&typeof e.value=="object"&&"intValue"in e.value)return e.value.intValue}export{a as getAttributesIntValue,s as getAttributesStringValue,l as mergeAttributes,f as toAttribute};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import s from"path";import{REDOCLY_ROUTE_RBAC as C}from"@redocly/config";import{PUBLIC_STATIC_FOLDER as r}from"../../constants/common.js";import{isPathInFolder as g}from"../../../utils/path/is-path-in-folder.js";import{fileExistsAsync as
|
|
1
|
+
import s from"path";import{REDOCLY_ROUTE_RBAC as C}from"@redocly/config";import{PUBLIC_STATIC_FOLDER as r}from"../../constants/common.js";import{isPathInFolder as g}from"../../../utils/path/is-path-in-folder.js";import{fileExistsAsync as T}from"../../utils/index.js";import{handleUnauthorizedAsset as h}from"../utils.js";import{MIME_TYPES as w}from"../mime-types.js";import{getContentTypeHeaderValue as y}from"../utils/content-type.js";import{canAccessResource as E}from"../../utils/rbac.js";const U=async(e,o,n,a)=>{const c=o.req,{isAuthenticated:m,teams:l,claims:{email:u}}=o.get("auth"),i=s.join(r,r);e.startsWith(i)&&(e=e.replace(i,r));const t=s.resolve(n.outdir,e);if(!g(t,n.outdir))return null;if(await T(t)){const p={[C]:{slug:e,fsPath:t},slug:e};if(!E(p,{isAuthenticated:m,email:u,teams:l},n.config.access?.rbac,n.config.access?.requiresLogin))return h(o);const f=c.query("download")!=null,d=w[s.extname(t)]||"text/plain",A=await a(t);return o.newResponse(A,200,{"Content-Type":y(d),"Access-Control-Allow-Origin":"*",...f&&{"Content-Disposition":`attachment; filename="${s.basename(t)}"`}})}else return null};export{U as staticContentHandler};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function r(t){return t.startsWith("text/")?`${t}; charset=utf-8`:t}export{r as getContentTypeHeaderValue};
|