@redocly/revel 0.138.0-next.7 → 0.138.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 +288 -0
- package/dist/api-schemas/mcp-fetch-count.d.ts +24 -0
- package/dist/api-schemas/mcp-fetch-count.js +1 -0
- package/dist/bin.js +0 -0
- package/dist/cli/build/analytics/collect-analytics.js +1 -1
- package/dist/cli/build/analytics/collectors/get-processed-config-stats-usage.js +1 -1
- package/dist/cli/build/index.js +1 -1
- package/dist/cli/develop.js +1 -1
- package/dist/cli/eject/ejectTheme.js +1 -1
- package/dist/cli/translations/collect-config-translations.js +1 -1
- package/dist/client/App.js +1 -1
- package/dist/client/app/ReviewComments/ReviewComments.js +2 -2
- package/dist/client/app/l10n/hooks/useTranslationKeys.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/openapi-example.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/openapi-response-sample.js +1 -1
- package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
- package/dist/client/app/markdoc/hooks/use-store.d.ts +2 -3
- package/dist/client/app/pages/Invite/Invite.js +1 -1
- package/dist/client/app/search/useSearch.js +1 -1
- package/dist/client/app/utils/loadAndNavigate.js +1 -1
- package/dist/client/polyfills.js +1 -1
- package/dist/client/runtime/loader.js +1 -1
- package/dist/client/utils/catalog/parse-filter-query.js +1 -1
- package/dist/compiled/svgo/svgo-node.js +39 -39
- package/dist/constants/api.d.ts +1 -0
- package/dist/constants/api.js +1 -1
- package/dist/constants/common.d.ts +6 -0
- package/dist/constants/common.js +1 -1
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/markdoc/helpers/get-inner-text.js +2 -2
- package/dist/markdoc/helpers/guards/is-prompt-node.d.ts +13 -0
- package/dist/markdoc/helpers/guards/is-prompt-node.js +1 -0
- package/dist/server/config/env-config.d.ts +0 -4
- package/dist/server/config/env-schema.d.ts +0 -10
- package/dist/server/config/env-schemas/feature-flags.d.ts +0 -8
- package/dist/server/config/env-schemas/feature-flags.js +1 -1
- package/dist/server/constants/entitlements.js +1 -1
- package/dist/server/entitlements/entitlements-provider.js +1 -1
- package/dist/server/esbuild/esbuild.js +3 -3
- package/dist/server/esbuild/plugins/on-rebuild.js +1 -1
- package/dist/server/esbuild/plugins/styled-components-ssr.js +1 -1
- package/dist/server/esbuild/plugins/yaml-loader.js +1 -1
- package/dist/server/fs/content-fs.js +1 -1
- package/dist/server/fs/utils/is-l10n-root-file.d.ts +3 -0
- package/dist/server/fs/utils/is-l10n-root-file.js +1 -0
- package/dist/server/plugins/analytics/amplitude/index.js +1 -1
- package/dist/server/plugins/analytics/heap/browser-hooks.js +1 -1
- package/dist/server/plugins/api-docs/index.js +1 -1
- package/dist/server/plugins/api-docs/loader.js +3 -3
- package/dist/server/plugins/api-docs/spec-download.api.js +1 -1
- package/dist/server/plugins/api-docs/utils/apply-nav-item-to-root.js +1 -1
- package/dist/server/plugins/api-docs/utils/decorators.d.ts +11 -0
- package/dist/server/plugins/api-docs/utils/decorators.js +1 -1
- package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.js +2 -2
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/utils/extract-parts-from-channels-message-ref.js +1 -1
- package/dist/server/plugins/config-parser/format-custom-tags.js +1 -1
- package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
- package/dist/server/plugins/config-parser/loaders/versions-config-loader.js +1 -1
- package/dist/server/plugins/config-parser/resolve-mutual-exclusion.js +1 -1
- package/dist/server/plugins/config-parser/safe-parse.js +1 -1
- package/dist/server/plugins/default-theme/resolve-logo.js +1 -1
- package/dist/server/plugins/dev-onboarding/api/adapters/apigee/adapter.js +2 -2
- package/dist/server/plugins/dev-onboarding/api/adapters/gravitee/client.js +2 -2
- package/dist/server/plugins/dev-onboarding/api/combine.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/ApiKeyOverview.js +3 -3
- package/dist/server/plugins/dev-onboarding/template/components/AppOverview.js +1 -1
- package/dist/server/plugins/dev-onboarding/template/components/useSortableData.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/code-walkthrough/file-chunk-parser.d.ts +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/index.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-svg-content.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-tag-raw-content.d.ts +4 -0
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-tag-raw-content.js +2 -0
- package/dist/server/plugins/markdown/compiler.js +1 -1
- package/dist/server/plugins/markdown/create-source-lines-reader.d.ts +7 -0
- package/dist/server/plugins/markdown/create-source-lines-reader.js +1 -0
- package/dist/server/plugins/markdown/html/normalize-html-headings.d.ts +9 -0
- package/dist/server/plugins/markdown/html/normalize-html-headings.js +1 -0
- package/dist/server/plugins/markdown/markdoc/markdoc-options.js +1 -1
- package/dist/server/plugins/markdown/markdoc/plugins/utils.d.ts +1 -1
- package/dist/server/plugins/markdown/markdoc/plugins/utils.js +1 -1
- package/dist/server/plugins/markdown/markdown-static-data-loader.js +1 -1
- package/dist/server/plugins/markdown/search/get-ai-search-documents.js +2 -2
- package/dist/server/plugins/markdown/search/search-resolver.js +1 -1
- package/dist/server/plugins/markdown/search/to-markdown.js +13 -13
- package/dist/server/plugins/markdown/search/walk-sections.d.ts +3 -1
- package/dist/server/plugins/markdown/search/walk-sections.js +3 -3
- package/dist/server/plugins/markdown/utils/sanitize-malformed-md-content.js +2 -2
- package/dist/server/plugins/mcp/audit/audit-log.d.ts +1 -1
- package/dist/server/plugins/mcp/audit/audit-log.js +1 -1
- package/dist/server/plugins/mcp/audit/code-credentials.d.ts +9 -0
- package/dist/server/plugins/mcp/audit/code-credentials.js +2 -0
- package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +5 -5
- package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +3 -1
- package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +2 -1
- package/dist/server/plugins/mcp/codemode/capabilities/utils.js +3 -3
- package/dist/server/plugins/mcp/codemode/code-audit.d.ts +4 -3
- package/dist/server/plugins/mcp/codemode/code-execution-audit.js +1 -1
- package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/utils.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/whoami.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.d.ts +12 -3
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.d.ts +2 -2
- package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/allowed-http-methods.d.ts +11 -0
- package/dist/server/plugins/mcp/gateway-mcp/allowed-http-methods.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/api-call-operations.d.ts +32 -0
- package/dist/server/plugins/mcp/gateway-mcp/api-call-operations.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/callable-apis.d.ts +7 -4
- package/dist/server/plugins/mcp/gateway-mcp/callable-apis.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/caller-api-calls.d.ts +9 -0
- package/dist/server/plugins/mcp/gateway-mcp/caller-api-calls.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/credential-validation.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -5
- package/dist/server/plugins/mcp/gateway-mcp/eligibility.d.ts +8 -4
- package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.d.ts +2 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.d.ts +11 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/redact.d.ts +11 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/redact.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-count-client.d.ts +4 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-count-client.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-count-secret.d.ts +4 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-count-secret.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-count.d.ts +11 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-count.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-counter-repository.d.ts +13 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-counter-repository.js +13 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/{limits.d.ts → fetch-limiter/fetch-limits.d.ts} +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/fetch-limiter/fetch-limits.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/{apply-edge-rate-limit.d.ts → request-limiter/apply-edge-rate-limit.d.ts} +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/request-limiter/apply-edge-rate-limit.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/{edge-limiter.d.ts → request-limiter/edge-limiter.d.ts} +3 -3
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/request-limiter/edge-limiter.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/request-limiter/rate-limit-telemetry.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/request-limiter/request-limits.d.ts +6 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/request-limiter/request-limits.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/utils/ip-key.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/{window-counter.d.ts → utils/window-counter.d.ts} +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/utils/window-counter.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/route-pattern.d.ts +18 -0
- package/dist/server/plugins/mcp/gateway-mcp/route-pattern.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.d.ts +9 -3
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/subject.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.d.ts +2 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +2 -2
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +0 -2
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.js +1 -1
- package/dist/server/plugins/mcp/handlers/credentials-page/constants.d.ts +7 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/constants.js +1 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-contract.d.ts +5 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-contract.js +1 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-page.d.ts +14 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-page.js +62 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/layout.d.ts +17 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/layout.js +11 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/outcome-pages.d.ts +10 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/outcome-pages.js +11 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/site-branding.d.ts +10 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/site-branding.js +1 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/styles.d.ts +4 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/styles.js +186 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/types.d.ts +32 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/types.js +0 -0
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.d.ts +0 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -1
- package/dist/server/plugins/mcp/index.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 +16 -1
- package/dist/server/plugins/mcp/utils/mode.d.ts +4 -1
- package/dist/server/plugins/mcp/utils/mode.js +1 -1
- package/dist/server/plugins/mcp/utils/xmcp-utils.d.ts +3 -5
- package/dist/server/plugins/mcp/utils/xmcp-utils.js +1 -1
- package/dist/server/plugins/nav-utils.js +1 -1
- package/dist/server/plugins/scorecard-classic/loaders/scorecard.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/components.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/useData.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/views.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/index.js +2 -2
- package/dist/server/plugins/sidebars/index.js +2 -2
- package/dist/server/plugins/sidebars/tabs.js +1 -1
- package/dist/server/plugins/sidebars/utils.js +1 -1
- package/dist/server/providers/database/client.d.ts +5 -0
- package/dist/server/providers/database/client.js +1 -1
- package/dist/server/providers/database/copy-migrations.js +1 -1
- package/dist/server/providers/database/database-connections-manager.js +1 -1
- package/dist/server/providers/database/has-project-database.d.ts +3 -0
- package/dist/server/providers/database/has-project-database.js +1 -0
- package/dist/server/store.d.ts +2 -0
- package/dist/server/store.js +1 -1
- package/dist/server/tools/notifiers/formatter.js +1 -1
- package/dist/server/tools/notifiers/helpers/privacy/mask-email.js +1 -1
- package/dist/server/tools/notifiers/logger.js +1 -1
- package/dist/server/types/plugins/markdown.d.ts +2 -0
- package/dist/server/types/web-server.d.ts +1 -0
- package/dist/server/utils/codeframes/codeframes.js +2 -2
- package/dist/server/utils/entitlements/read-entitlement-number.d.ts +3 -0
- package/dist/server/utils/entitlements/read-entitlement-number.js +1 -0
- package/dist/server/utils/fs.js +1 -1
- package/dist/server/utils/is-api-download-link.d.ts +1 -0
- package/dist/server/utils/is-api-download-link.js +1 -1
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/utils/redact-url.d.ts +3 -2
- package/dist/server/utils/redact-url.js +1 -1
- package/dist/server/utils/sandbox-context.d.ts +7 -4
- package/dist/server/utils/sandbox-context.js +1 -1
- package/dist/server/web-server/auth.d.ts +0 -1
- package/dist/server/web-server/auth.js +4 -4
- package/dist/server/web-server/dev-server.js +1 -1
- package/dist/server/web-server/http.d.ts +2 -1
- package/dist/server/web-server/http.js +2 -2
- package/dist/server/web-server/jwt/token-types.d.ts +1 -0
- package/dist/server/web-server/jwt/token-types.js +1 -1
- package/dist/server/web-server/middleware/catalogAuthMiddleware.js +1 -1
- package/dist/server/web-server/middleware/dynamic-middleware/hono-compose.js +1 -1
- package/dist/server/web-server/middleware/responseHeadersMiddleware.js +1 -1
- package/dist/server/web-server/routes/auth.d.ts +1 -1
- package/dist/server/web-server/routes/auth.js +1 -1
- package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.d.ts +1756 -1756
- package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.d.ts +295 -295
- package/dist/server/web-server/routes/cors-proxy.js +2 -2
- package/dist/server/web-server/routes/index.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-consent-page.d.ts +24 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-consent-page.js +35 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-fetch-count.d.ts +8 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-fetch-count.js +1 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth-store.d.ts +15 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth-store.js +1 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.d.ts +3 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
- package/dist/server/web-server/routes/resolve-route.js +1 -1
- package/dist/server/workers/worker-pool.js +1 -1
- package/dist/types/entitlements.d.ts +2 -0
- package/dist/utils/time/debounce.js +1 -1
- package/package.json +10 -11
- package/dist/client/app/utils/withLoadProgress.d.ts +0 -2
- package/dist/client/app/utils/withLoadProgress.js +0 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.js +0 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/edge-limiter.js +0 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/ip-key.js +0 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/limits.js +0 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.js +0 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/window-counter.js +0 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-page.d.ts +0 -12
- package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +0 -225
- /package/dist/server/plugins/mcp/gateway-mcp/rate-limit/{rate-limit-telemetry.d.ts → request-limiter/rate-limit-telemetry.d.ts} +0 -0
- /package/dist/server/plugins/mcp/gateway-mcp/rate-limit/{ip-key.d.ts → utils/ip-key.d.ts} +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RedoclyConfig } from '@redocly/config';
|
|
2
|
+
import type { GlobalData } from '../../../../../types/index.js';
|
|
3
|
+
import type { SiteBranding } from './types.js';
|
|
4
|
+
/** `logo` is the resolved theme logo from global data, whose paths point at served assets. */
|
|
5
|
+
export declare function resolveSiteBranding({ seo, logo, colorMode, }: {
|
|
6
|
+
seo?: RedoclyConfig['seo'];
|
|
7
|
+
logo?: GlobalData['logo'];
|
|
8
|
+
colorMode?: RedoclyConfig['colorMode'];
|
|
9
|
+
}): SiteBranding;
|
|
10
|
+
//# sourceMappingURL=site-branding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{parseSrcSet as h}from"../../../../utils/attribute-parser.js";function o({seo:t,logo:e,colorMode:d}){const n=t?.title||t?.projectTitle||e?.altText||void 0,i=e?.srcSet?h(e.srcSet):new Map,r=s(i.get("light")??e?.image),a=s(i.get("dark")),c=f(d);return{...n?{name:n}:{},...r?{logo:{light:r,...a?{dark:a}:{}}}:{},...c?{colorScheme:c}:{}}}function f(t){if(t?.hide)return"light";if(t?.ignoreDetection)return t.modes?.[0]==="dark"?"dark":"light"}function s(t){return t?.startsWith("/")&&!t.startsWith("//")?t:void 0}export{o as resolveSiteBranding};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
const e=`
|
|
2
|
+
--font-family-base:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
|
3
|
+
--page-bg:#f7f7f9;
|
|
4
|
+
--page-dot:#e3e4ea;
|
|
5
|
+
--bg-color:#ffffff;
|
|
6
|
+
--border-color-primary:#dcdde5;
|
|
7
|
+
--panel-bg:#f3f3f6;
|
|
8
|
+
--layer-color:#fbfbfc;
|
|
9
|
+
--input-border-color:#dcdde5;
|
|
10
|
+
--border-color-secondary:#ededf2;
|
|
11
|
+
--stored-bg:#ededf2;
|
|
12
|
+
--text-color-primary:#1a1c21;
|
|
13
|
+
--text-color-secondary:#3b3c45;
|
|
14
|
+
--text-color-description:#555761;
|
|
15
|
+
--placeholder:#9b9ca8;
|
|
16
|
+
--input-bg-color:#ffffff;
|
|
17
|
+
--primary-bg:#1a1c21;
|
|
18
|
+
--primary-hover:#3b3c45;
|
|
19
|
+
--primary-text:#ffffff;
|
|
20
|
+
--focus:#4561db;
|
|
21
|
+
--code-bg:#ededf2;
|
|
22
|
+
--code-text:#2a2b33;
|
|
23
|
+
--tag-bg:#ededf2;
|
|
24
|
+
--tag-text:#3b3c45;
|
|
25
|
+
--tag-stored-bg:#f0f4ff;
|
|
26
|
+
--tag-stored-text:#4561db;
|
|
27
|
+
--danger:#c8174f;
|
|
28
|
+
--danger-bg:#fff1f5;
|
|
29
|
+
--danger-border:#f7a8c0;
|
|
30
|
+
--success:#1f9d55;
|
|
31
|
+
--success-glow:rgba(31,157,85,.18);
|
|
32
|
+
--warning:#e08a00;
|
|
33
|
+
--warning-glow:rgba(224,138,0,.18);
|
|
34
|
+
--warning-bg:#fff8eb;
|
|
35
|
+
--warning-border:#f5c97a;
|
|
36
|
+
--danger-icon:#f9316d;
|
|
37
|
+
--danger-glow:rgba(249,49,109,.18);
|
|
38
|
+
--neutral-glow:rgba(85,87,97,.14);
|
|
39
|
+
`,o=`
|
|
40
|
+
--page-bg:#1a1b20;
|
|
41
|
+
--page-dot:#2c2e36;
|
|
42
|
+
--bg-color:#22242b;
|
|
43
|
+
--border-color-primary:#555761;
|
|
44
|
+
--panel-bg:#2a2b33;
|
|
45
|
+
--layer-color:#2a2b33;
|
|
46
|
+
--input-border-color:#3b3c45;
|
|
47
|
+
--border-color-secondary:#3b3c45;
|
|
48
|
+
--stored-bg:#32343e;
|
|
49
|
+
--text-color-primary:#fbfbfc;
|
|
50
|
+
--text-color-secondary:#c4c6d1;
|
|
51
|
+
--text-color-description:#9b9ca8;
|
|
52
|
+
--placeholder:#6e6f7a;
|
|
53
|
+
--input-bg-color:#22242b;
|
|
54
|
+
--primary-bg:#fbfbfc;
|
|
55
|
+
--primary-hover:#dcdde5;
|
|
56
|
+
--primary-text:#1a1c21;
|
|
57
|
+
--focus:#8fa6ff;
|
|
58
|
+
--code-bg:#3b3c45;
|
|
59
|
+
--code-text:#c4c6d1;
|
|
60
|
+
--tag-bg:#3b3c45;
|
|
61
|
+
--tag-text:#c4c6d1;
|
|
62
|
+
--tag-stored-bg:#1f2a4d;
|
|
63
|
+
--tag-stored-text:#8fa6ff;
|
|
64
|
+
--danger:#ff6b95;
|
|
65
|
+
--danger-bg:#3a1822;
|
|
66
|
+
--danger-border:#7a2b44;
|
|
67
|
+
--success:#3ccf74;
|
|
68
|
+
--success-glow:rgba(60,207,116,.2);
|
|
69
|
+
--warning:#f5a524;
|
|
70
|
+
--warning-glow:rgba(245,165,36,.2);
|
|
71
|
+
--warning-bg:#33260f;
|
|
72
|
+
--warning-border:#7a5a1e;
|
|
73
|
+
--danger-icon:#ff6b95;
|
|
74
|
+
--danger-glow:rgba(255,107,149,.2);
|
|
75
|
+
--neutral-glow:rgba(155,156,168,.16);
|
|
76
|
+
`,r=`
|
|
77
|
+
*{box-sizing:border-box}
|
|
78
|
+
body{margin:0;min-height:100vh;padding:48px 24px;font-family:var(--font-family-base);font-size:14px;line-height:22px;color:var(--text-color-primary);background-color:var(--page-bg);background-image:radial-gradient(var(--page-dot) 1px,transparent 1px);background-size:16px 16px}
|
|
79
|
+
.page{display:grid;grid-template-columns:minmax(0,692px) minmax(0,348px);gap:16px;justify-content:center;min-height:calc(100vh - 96px);margin:0 auto}
|
|
80
|
+
.page.narrow{grid-template-columns:minmax(0,864px)}
|
|
81
|
+
.card{display:flex;flex-direction:column;background:var(--bg-color);border:1px solid var(--border-color-primary);border-radius:24px;padding:40px 48px 24px}
|
|
82
|
+
.panel{display:flex;flex-direction:column;gap:16px;background:var(--panel-bg);border:1px solid var(--border-color-primary);border-radius:24px;padding:32px 24px 24px}
|
|
83
|
+
.site{display:flex;align-items:center;justify-content:space-between;gap:16px;padding-bottom:24px;margin-bottom:24px;border-bottom:1px solid var(--border-color-secondary)}
|
|
84
|
+
.site-name{font-size:18px;line-height:24px;font-weight:600;overflow-wrap:anywhere}
|
|
85
|
+
.site-host{font-size:16px;line-height:24px;color:var(--text-color-secondary);overflow-wrap:anywhere;text-align:right}
|
|
86
|
+
.site-logo{display:block;max-height:32px;max-width:200px;width:auto}
|
|
87
|
+
h1{margin:0;font-size:20px;line-height:28px;font-weight:600}
|
|
88
|
+
h2{margin:0;font-size:16px;line-height:24px;font-weight:600}
|
|
89
|
+
p{margin:0}
|
|
90
|
+
.lede{margin-top:12px}
|
|
91
|
+
.muted{color:var(--text-color-description)}
|
|
92
|
+
.small{font-size:12px;line-height:20px}
|
|
93
|
+
.strong{font-weight:600}
|
|
94
|
+
code{font:inherit;background:var(--code-bg);color:var(--code-text);padding:1px 8px;border-radius:6px;overflow-wrap:anywhere}
|
|
95
|
+
.banner{display:flex;gap:8px;align-items:flex-start;margin-top:24px;padding:12px 16px;border:1px solid var(--danger-border);border-radius:8px;background:var(--danger-bg);color:var(--text-color-primary)}
|
|
96
|
+
.banner svg{flex:none;margin-top:3px;color:var(--danger)}
|
|
97
|
+
.banner.warning{border-color:var(--warning-border);background:var(--warning-bg)}
|
|
98
|
+
.banner.warning svg{color:var(--warning)}
|
|
99
|
+
form.credentials{display:flex;flex-direction:column;flex:1}
|
|
100
|
+
.schemes{display:flex;flex-direction:column;gap:12px;margin-top:24px}
|
|
101
|
+
.scheme{background:var(--layer-color);border:1px solid var(--border-color-secondary);border-radius:16px;padding:24px 32px 24px 24px}
|
|
102
|
+
.info-card{margin-top:24px;padding:8px 24px;background:var(--layer-color);border:1px solid var(--border-color-secondary);border-radius:16px}
|
|
103
|
+
.info-card section{display:flex;flex-direction:column;gap:2px;padding:16px 0}
|
|
104
|
+
.info-card section+section{border-top:1px solid var(--border-color-secondary)}
|
|
105
|
+
.info-card h2{font-size:14px;line-height:22px;font-weight:500;color:var(--text-color-secondary)}
|
|
106
|
+
.scheme-body{display:flex;flex-direction:column;gap:16px}
|
|
107
|
+
details.scheme>.scheme-body{margin-top:16px;padding-left:24px}
|
|
108
|
+
details.scheme>summary{display:grid;grid-template-columns:16px minmax(0,1fr) auto;column-gap:8px;row-gap:4px;cursor:pointer;list-style:none}
|
|
109
|
+
details.scheme>summary::-webkit-details-marker{display:none}
|
|
110
|
+
details.scheme>summary::before,details.operations>summary::before{content:"";flex:none;width:6px;height:6px;margin:8px 0 0 4px;border-right:1.5px solid var(--text-color-secondary);border-bottom:1.5px solid var(--text-color-secondary);transform:rotate(-45deg);transition:transform .15s}
|
|
111
|
+
details[open]>summary::before{transform:rotate(45deg);margin-top:6px}
|
|
112
|
+
details.scheme>summary:focus-visible{outline:2px solid var(--focus);outline-offset:4px;border-radius:4px}
|
|
113
|
+
.summary-title{grid-column:2;font-size:16px;line-height:24px;font-weight:600;overflow-wrap:anywhere}
|
|
114
|
+
.summary-tag{grid-column:3;grid-row:1}
|
|
115
|
+
.summary-line{grid-column:2/4}
|
|
116
|
+
.scheme-head{display:flex;flex-direction:column;gap:4px}
|
|
117
|
+
.tag{display:inline-block;padding:1px 8px;border-radius:4px;font-size:14px;line-height:22px;background:var(--tag-bg);color:var(--tag-text);white-space:nowrap}
|
|
118
|
+
.tag.stored{background:var(--tag-stored-bg);color:var(--tag-stored-text)}
|
|
119
|
+
.tags{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px}
|
|
120
|
+
.stored-box{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-radius:8px;background:var(--stored-bg)}
|
|
121
|
+
.field{display:flex;flex-direction:column;gap:4px;min-width:0}
|
|
122
|
+
.field-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
|
|
123
|
+
label{font-weight:500;color:var(--text-color-secondary)}
|
|
124
|
+
input[type=text],input[type=password]{width:100%;height:34px;padding:0 12px;font-family:var(--font-family-base);font-size:14px;color:var(--text-color-primary);background:var(--input-bg-color);border:1px solid var(--input-border-color);border-radius:8px}
|
|
125
|
+
input::placeholder{color:var(--placeholder)}
|
|
126
|
+
input:focus{outline:2px solid transparent;border-color:var(--focus);box-shadow:0 0 0 1px var(--focus)}
|
|
127
|
+
input[aria-invalid=true]{border-color:var(--danger)}
|
|
128
|
+
input[aria-invalid=true]:focus{box-shadow:0 0 0 3px var(--danger-border)}
|
|
129
|
+
.divider{border:0;border-top:1px solid var(--border-color-secondary);margin:0}
|
|
130
|
+
details.operations>summary{display:flex;gap:8px;cursor:pointer;list-style:none;width:max-content;max-width:100%}
|
|
131
|
+
details.operations>summary::-webkit-details-marker{display:none}
|
|
132
|
+
details.operations>summary:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:4px}
|
|
133
|
+
details.operations ul{margin:8px 0 0;padding-left:20px;display:flex;flex-direction:column;gap:4px}
|
|
134
|
+
.actions{margin-top:auto;padding-top:40px}
|
|
135
|
+
.actions-row{display:flex;align-items:center;gap:16px;padding-top:24px;border-top:1px solid var(--border-color-secondary)}
|
|
136
|
+
.actions-row .primary{flex:1}
|
|
137
|
+
button{font-family:var(--font-family-base);font-size:16px;line-height:24px;font-weight:400;cursor:pointer;border-radius:12px}
|
|
138
|
+
button:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
|
|
139
|
+
.primary{height:40px;padding:0 20px;border:0;background:var(--primary-bg);color:var(--primary-text)}
|
|
140
|
+
.primary:hover{background:var(--primary-hover)}
|
|
141
|
+
.secondary{height:40px;padding:0 20px;border:0;box-shadow:inset 0 0 0 1px var(--border-color-primary);background:var(--bg-color);color:var(--text-color-primary)}
|
|
142
|
+
.actions-row .secondary{flex:1}
|
|
143
|
+
.secondary:hover{background:var(--panel-bg)}
|
|
144
|
+
.text-danger{padding:0 20px;height:40px;border:0;background:none;color:var(--danger)}
|
|
145
|
+
.text-danger.small{height:auto;padding:0 8px;font-size:14px;line-height:22px}
|
|
146
|
+
.text-danger:hover{text-decoration:underline}
|
|
147
|
+
.link-button{padding:0;border:0;background:none;color:var(--text-color-secondary);font-size:12px;line-height:20px;text-decoration:underline;text-underline-offset:2px}
|
|
148
|
+
.decline{margin-top:12px;text-align:center;color:var(--text-color-secondary)}
|
|
149
|
+
.panel h2{display:flex;align-items:center;gap:12px;font-weight:500}
|
|
150
|
+
.panel-steps{display:flex;flex-direction:column;gap:16px}
|
|
151
|
+
.panel-steps-toggle{display:none}
|
|
152
|
+
.panel-steps-toggle>summary{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer;list-style:none}
|
|
153
|
+
.panel-steps-toggle>summary::-webkit-details-marker{display:none}
|
|
154
|
+
.panel-steps-toggle>summary::after{content:"";flex:none;width:7px;height:7px;margin:0 4px 4px 0;border-right:1.5px solid var(--text-color-secondary);border-bottom:1.5px solid var(--text-color-secondary);transform:rotate(45deg);transition:transform .15s}
|
|
155
|
+
.panel-steps-toggle[open]>summary::after{transform:rotate(-135deg);margin:4px 4px 0 0}
|
|
156
|
+
.panel-steps-toggle>summary:focus-visible{outline:2px solid var(--focus);outline-offset:4px;border-radius:4px}
|
|
157
|
+
.panel-steps-toggle>.steps{margin-top:16px}
|
|
158
|
+
.steps{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:16px;counter-reset:step}
|
|
159
|
+
.steps li{display:grid;grid-template-columns:20px minmax(0,1fr);gap:12px;counter-increment:step;font-size:16px;line-height:24px}
|
|
160
|
+
.steps li::before{content:counter(step);display:flex;align-items:center;justify-content:center;height:20px;margin-top:2px;border-radius:5px;background:var(--bg-color);font-size:14px;line-height:16px}
|
|
161
|
+
.link-facts{display:flex;flex-direction:column;gap:8px;margin-top:auto;padding-top:32px;border-top:1px solid var(--border-color-primary);color:var(--text-color-secondary)}
|
|
162
|
+
.pill{display:inline-flex;align-items:center;gap:8px;width:max-content;max-width:100%;padding:1px 8px;border-radius:999px;background:var(--bg-color);font-size:12px;line-height:20px}
|
|
163
|
+
.pill::before{content:"";flex:none;width:6px;height:6px;border-radius:50%;background:var(--success)}
|
|
164
|
+
.outcome{display:flex;flex-direction:column;align-items:center;text-align:center;gap:24px;padding:56px 0}
|
|
165
|
+
.status-icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;color:#ffffff}
|
|
166
|
+
.status-icon.success{background:var(--success);box-shadow:0 0 16px 10px var(--success-glow)}
|
|
167
|
+
.status-icon.warning{background:var(--warning);box-shadow:0 0 16px 10px var(--warning-glow)}
|
|
168
|
+
.status-icon.danger{background:var(--danger-icon);box-shadow:0 0 16px 10px var(--danger-glow)}
|
|
169
|
+
.status-icon.neutral{background:var(--text-color-description);box-shadow:0 0 16px 10px var(--neutral-glow)}
|
|
170
|
+
.message{display:flex;flex-direction:column;gap:8px;width:100%;max-width:640px;padding:24px 32px;border:1px solid var(--border-color-secondary);border-radius:12px;background:var(--layer-color)}
|
|
171
|
+
@media (max-width:960px){
|
|
172
|
+
body{padding:16px}
|
|
173
|
+
.page{grid-template-columns:minmax(0,1fr);min-height:0}
|
|
174
|
+
.card{padding:24px}
|
|
175
|
+
.site{flex-direction:column;align-items:flex-start;gap:0}
|
|
176
|
+
.site-host{text-align:left}
|
|
177
|
+
.panel-steps{display:none}
|
|
178
|
+
.panel-steps-toggle{display:block}
|
|
179
|
+
.link-facts{padding-top:16px}
|
|
180
|
+
.scheme{padding:16px}
|
|
181
|
+
.info-card{padding:4px 16px}
|
|
182
|
+
.field-row{grid-template-columns:minmax(0,1fr)}
|
|
183
|
+
.outcome{padding:32px 0}
|
|
184
|
+
.message{padding:16px}
|
|
185
|
+
}
|
|
186
|
+
`;function t(a){switch(a){case"light":return`:root{color-scheme:light;${e}}${r}`;case"dark":return`:root{color-scheme:dark;${e}${o}}${r}`;default:return`:root{color-scheme:light dark;${e}}@media (prefers-color-scheme:dark){:root{${o}}}${r}`}}export{t as pageStyles};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type SiteBranding = {
|
|
2
|
+
name?: string;
|
|
3
|
+
logo?: {
|
|
4
|
+
light: string;
|
|
5
|
+
dark?: string;
|
|
6
|
+
};
|
|
7
|
+
/** Set when the portal always shows one color mode. */
|
|
8
|
+
colorScheme?: PageColorScheme;
|
|
9
|
+
};
|
|
10
|
+
export type PageColorScheme = 'light' | 'dark';
|
|
11
|
+
export type PageSite = SiteBranding & {
|
|
12
|
+
host: string;
|
|
13
|
+
};
|
|
14
|
+
/** One page, before the shared document shell wraps it. */
|
|
15
|
+
export type PageContent = {
|
|
16
|
+
title: string;
|
|
17
|
+
body: string;
|
|
18
|
+
};
|
|
19
|
+
export type SchemeField = 'secret' | 'client_id' | 'client_secret';
|
|
20
|
+
/** A rejected submission. `schemeIndex` and `field` name the input to mark, when there is one. */
|
|
21
|
+
export type FormError = {
|
|
22
|
+
message: string;
|
|
23
|
+
schemeIndex?: number;
|
|
24
|
+
field?: SchemeField;
|
|
25
|
+
};
|
|
26
|
+
/** What one submission changed, and the schemes that hold a credential after it. */
|
|
27
|
+
export type CredentialsOutcome = {
|
|
28
|
+
action: 'saved' | 'removed';
|
|
29
|
+
schemes: readonly string[];
|
|
30
|
+
stored: readonly string[];
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=types.d.ts.map
|
|
File without changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{logger as A}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as N}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as M,getInternalOrigin as v}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as L,DEFAULT_ANONYMOUS_VISITOR_TEAM as B,RbacFeatures as H}from"../../../../constants/common.js";import{isObject as j}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as V}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as $}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as G}from"@modelcontextprotocol/server";import{createDocsMcpServer as J}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as K,filterGraphqlDescriptionsByRbac as Y}from"../utils.js";import{userSubject as z}from"../gateway-mcp/subject.js";import{ipRateLimitKey as W}from"../gateway-mcp/rate-limit/utils/ip-key.js";import{McpClientInputError as X,createMethodNotAllowedError as Q,withErrorHandling as Z}from"./errors.js";import{constructForbiddenResponse as q,constructInvalidTokenResponse as x,constructUnauthorizedResponse as ee,handleMcpAuth as re}from"../auth/auth-handlers.js";import{isAssistantAnonymousToken as oe}from"../auth/assistant-anonymous-token.js";import{shouldHandleMcpAuth as se}from"../../../utils/rbac/should-handle-mcp-auth.js";import{extractTokenFromAuthHeader as ne}from"../utils/jwt.js";import{resolveMcpClient as ie}from"../utils/mcp-client.js";import{randomUUID as te}from"../../../utils/crypto/random-uuid.js";import{getPublicMcpEndpointStatus as ce}from"../utils/public-endpoint.js";import{narrowMcpConfigForCaller as ae}from"../gateway-mcp/caller-api-calls.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as pe,SSE_KEEPALIVE_INTERVAL_MS as de}from"../constants.js";import{withPathPrefix as me}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as fe}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as le}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as ue}from"../../../constants/rbac.js";const E="X-Redocly-AI-Metadata";function ge(r){if(r)try{const e=JSON.parse(r);if(j(e))return e;A.warn(`Ignoring ${E} header: not a JSON object.`)}catch{A.warn(`Ignoring ${E} header: invalid JSON.`)}}function I(){return{...ue,email:"",idpAccessToken:void 0,idpId:void 0}}const he=async(r,e,i)=>{const t=!!e?.config?.access?.requiresLogin,c=e?.config?.access?.rbac||{},l=i?.props?.config?.mcpMode??"tools",y=i?.props?.config?.gatewayFetchBudgetPerExec??L.budgetPerExec,C=i?.props?.config?.searchIgnoredRoutes??[],s=i,U=!!s?.props?.config?.isPublicEndpoint;let u;const T=r.headers.get("Authorization");if(U)e.user=I();else if(se(t,c)){const{isAuthenticated:n,isTokenValid:p,isFirstPartyAnonymous:g,currentUser:d,accessToken:h}=await re(r,e);if(g)e.user=I();else if(n)d&&(e.user=d),u=h;else{const a=M(r),m=ce(e.config)==="served"?`${a}${me(fe)}`:void 0;return p===!1?x(a,m):ee(a,m)}}else if(T){const n=ne(T)??void 0;u=(n?await oe(n):!1)?void 0:n}const w={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[B],claims:e.user?.claims??{}};return le(H.MCP,w,c,t)?await Z(async()=>{const n=i?.props?.config?.elicitationEnabled??!1;if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP client (VS Code, Cursor, Claude Code, etc.) using this URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return Q();const p=s?.props?.config?.apiDescriptionsMap||{},g=s?.props?.config?.graphqlDescriptions||[],d=s?.props?.config?.mcpDocsServerName||pe,{config:{mcp:h={}}}=e,a=K(p,e.user,c,t),m=Y(g,e.user,c,t),R=e.config.products?Object.values(e.config.products).map(o=>o?.name):[],D=h.docs?.name||d,f=ge(r.headers.get(E)),P=s?.props?.tools||[],_=s?.props?.skillsBaseUrl||M(r),O=V(s?.props?.skills||[],e.user,c,t).map(o=>({slug:o.slug,name:o.name,description:o.description,content:o.content,uri:$(_,o.slug)})),S=await Ae(r),b=s?.props?.fetchCountSecret,k={name:D,tools:P,skills:O,context:{...e,config:{...e.config,mcp:ae(e.config.mcp,f)},accessToken:u,outdir:e.outdir||"",baseUrl:e.baseUrl||M(r),internalBaseUrl:v(r),apiDescriptionsMap:a,graphqlDescriptions:m,products:R,metadata:f,mcpMode:l,elicitationEnabled:n,gatewayFetchBudgetPerExec:y,fetchCountRequest:l==="code"&&b?{caller:{subject:z(e.user),ip:W(r)},secret:b}:void 0,searchIgnoredRoutes:C,clientIp:N(r),...ie(r),requestId:te(),messageId:typeof f?.messageId=="string"?f.messageId:void 0}},F=await J({...k,getKv:e.getKv});return await G(async()=>F,{keepAliveMs:de,onerror:o=>A.warn(`MCP handler: ${o.message}`)}).fetch(r,S!==void 0?{parsedBody:S}:void 0)},l):q()};async function Ae(r){try{return await r.json()}catch(e){throw new X(e instanceof Error?e.message:String(e),{cause:e})}}var Ke=he;export{Ke as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withPathPrefix as g}from"@redocly/theme/core/utils";import{importApiRoutesHandler as
|
|
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 G(a,t,e){const n=t.req.raw;if(a.requestHandlerId===_&&n.method==="GET"&&R(n.headers.get("accept"))&&e.globalData.mcpData?.docs?.enabled)return T(t,e,{slug:a.slug},405,w);const r=t.get("auth"),o=await C(n,e);if(o)return o;const s=await e.resolveRouteStaticData(a)||{},m=g(a.slug),{requestHandlers:c}=await h(e.serverOutDir),p=c[a.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}),i=await d(t.req.raw,f,{...s,props:{...s.props,routeSlug:m,outdir:e.outdir,fetchCountSecret:O(),skills:e.config.skills?.hide===!0?[]:e.getSkills(),skillsBaseUrl:S(e,t)}});return i instanceof Response?i:typeof i=="string"?new Response(i,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}})}export{G as handleMcpRequest};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ApiRoutesHandler } from '@redocly/config';
|
|
2
|
-
export declare function setCredentialsFetchImpl(impl: typeof fetch): void;
|
|
3
2
|
declare const mcpCredentialsHandler: ApiRoutesHandler;
|
|
4
3
|
export default mcpCredentialsHandler;
|
|
5
4
|
//# sourceMappingURL=mcp-credentials-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{secretStore as
|
|
1
|
+
import{secretStore as d}from"../gateway-mcp/secret-store.js";import{rejectCredential as _}from"../gateway-mcp/credential-validation.js";import{buildAllowedHostMatchers as C}from"../gateway-mcp/fetch/allowed-hosts.js";import{assertUrlAllowed as A}from"../gateway-mcp/fetch/ssrf-guard.js";import{readCappedBody as T,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 N}from"./credentials-page/form-page.js";import{htmlDocument as O}from"./credentials-page/layout.js";import{declinedPage as R,expiredPage as I,outcomePage as j}from"./credentials-page/outcome-pages.js";const D={"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'"},$=3e4,F=64*1024,M=/^bearer\s+/i,U=/^\d+$/,B=async(e,t,o)=>{const n=await t.getKv(),r=L(e,t.baseUrl,o);if(e.method==="GET"){const i=new URL(e.url).searchParams.get("token")??"",c=await d.peekElicitation(n,i);return c?S({kv:n,site:r,token:i,target:c},{},200):p(r)}if(e.method==="POST"){const i=await e.formData(),c=u(i,"token"),a=await d.peekElicitation(n,c);if(!a)return p(r);const s={kv:n,site:r,token:c,target:a,form:i};switch(u(i,"action")){case k.remove:return b(s,z(a,u(i,"scheme")));case k.removeAll:return b(s,w(a));case k.decline:return K(s);default:return H(s)}}return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, POST"}})};async function H(e){const{target:t,form:o}=e,n=w(t),r=n.map((s,l)=>u(o,f("client_id",l)).trim()),i=s=>S(e,{error:s,clientIds:r},400),c=X(n,o);if("error"in c)return i(c.error);if(c.writes.length===0)return i(G(n));const a=[];for(const s of c.writes){if(s.kind!=="exchange"){a.push(s);continue}const l=await J(s.auth,s.clientId,s.clientSecret);if(!l.ok)return x.warn(`gateway oauth2 client_credentials exchange failed for ${t.api}: ${l.reason}`),i(E(n,s.schemeIndex,"client_id","We could not exchange those client credentials for a token. Check the client ID and secret, then try again."));a.push({kind:"set",scheme:s.scheme,secret:l.secret})}return v(e,a)}function X(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:E(e,n,"secret",s)};o.push({kind:"set",scheme:r.name,secret:W(r.auth,i)});continue}if(r.auth.kind!=="oauth2ClientCredentials")continue;const c=u(t,f("client_id",n)).trim(),a=u(t,f("client_secret",n)).trim();if(c&&a)o.push({kind:"exchange",scheme:r.name,schemeIndex:n,auth:r.auth,clientId:c,clientSecret:a});else if(c||a)return{error:E(e,n,c?"client_secret":"client_id","Enter both the client ID and the client secret, or leave both blank.")}}return{writes:o}}function G(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 E(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(c=>r[c.name]).map(c=>({kind:"remove",scheme:c.name}));return i.length===0?S(e,{error:{message:"No credential is stored there, so there is nothing to remove."}},400):v(e,i)}function z(e,t){const o=U.test(t)?w(e)[Number(t)]:void 0;return o?[o]:[]}async function K({kv:e,site:t,token:o}){return await d.consumeElicitation(e,o)?h(t,R(),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 a of n)a.kind==="remove"?await d.deleteSecret(e,r.subject,r.api,a.scheme):await d.setSecret(e,r.subject,r.api,a.scheme,a.secret);const i=await d.getStoredSchemes(e,r.subject,r.api),c={action:n.some(a=>a.kind==="set")?"saved":"removed",schemes:n.map(a=>a.scheme),stored:Object.keys(i).sort()};return h(t,j(r,c),200)}async function S({kv:e,site:t,token:o,target:n},r,i){const c=await d.getStoredSchemes(e,n.subject,n.api);return h(t,N({site:t,target:n,token:o,stored:c,...r}),i)}function L(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 J(e,t,o){try{const n=C([{url:e.tokenUrl}]),r=A(e.tokenUrl,n),i=new AbortController,c=setTimeout(()=>i.abort(),$);let a;try{a=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(c)}if(!a.ok)return m(`token endpoint returned ${a.status}`);let s;try{s=await T(a,F)}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 y=typeof l=="object"&&l!==null&&"access_token"in l?l.access_token:void 0,g=typeof y=="string"?y.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(O(t,e.colorScheme),{status:o,headers:D})}function p(e){return h(e,I(),404)}function W(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:Y(t)}:{header:"Authorization",value:t}}function Y(e){return`Bearer ${e.replace(M,"")}`}var ie=B;export{ie as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fileURLToPath as U}from"node:url";import{dirname as $,join as
|
|
1
|
+
import{fileURLToPath as U}from"node:url";import{dirname as $,join as D}from"node:path";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as M}from"@redocly/theme/core/constants/mcp";import{logger as p}from"../../tools/notifiers/logger.js";import{reporter as F}from"../../tools/notifiers/reporter.js";import{isDefined as B}from"../../../utils/guards/is-defined.js";import{MCP_CREDENTIALS_HANDLER_ID as A,MCP_CREDENTIALS_ROUTE as V,MCP_DOCS_SERVER_HANDLER_ID as T,MCP_NOT_ALLOWED_TEMPLATE_ID as x}from"../../constants/mcp.js";import{bundledOpenApiDocumentsToMcpOpenApi as J,bundledGraphqlDocumentsToMcpOpenApi as W,buildGraphqlDescriptions as X,collectIgnoredRoutes as z,filterIgnoredApiDescriptions as P,getCleanedUpApiDescriptions as K,isMcpInRedirects as Q}from"./utils.js";import{getMcpMode as R,isMcpElicitationEnabled as Y,isMcpGatewayEnabled as Z}from"./utils/mode.js";import{getPublicMcpEndpointStatus as _}from"./utils/public-endpoint.js";import{findGatedToolNames as ee}from"./utils/find-gated-tool-names.js";import{getDefaultToolSchemas as oe}from"./docs-mcp/tool-schemas.js";import{EXECUTE_TOOL_SCHEMA as te}from"./codemode/tools/execute-schema.js";import{isGatewayCapabilityEnabled as ie,isGatewayEligible as re}from"./gateway-mcp/eligibility.js";import{resolveGatewayFetchLimits as se}from"./gateway-mcp/rate-limit/fetch-limiter/fetch-limits.js";import{resetCustomMcpTools as ne,scanCustomMcpTools as ae}from"./custom-tools/scan-custom-tools.js";import{resolveSiteBranding as ce}from"./handlers/credentials-page/site-branding.js";import{telemetryTraceStep as pe}from"../../../cli/telemetry/helpers/trace-step.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as S}from"./constants.js";const b=$(U(import.meta.url));async function de(){let i;const m={registeredToolNames:[],warnedNoOutputSchemaTools:new Set};let u=0,f=!1;return{id:"mcp",async processContent(e,a){await pe("com.redocly.build.plugin.mcp",async s=>{const t=await a.getConfig(),{mcp:r,redirects:g}=t;if(s?.setAttribute("config",JSON.stringify(r||{})),s?.setAttribute("mcpMode",R()),s?.setAttribute("mcpGateway",String(Z())),r?.hide||r?.docs?.hide){ne(e,m);return}Q(g)&&await F.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),e.createTemplate(x,"@redocly/theme/layouts/McpNotAllowed");const l=!!t?.access?.requiresLogin,C=t?.access?.rbac||{},d=R(),c=Y(),{budgetPerExec:h}=se();if(!i){p.info("Configuring MCP servers...");const w=J(await e.loadApiDocuments(a)),O=W(await e.loadApiDocuments(a)),v=r?.docs?.ignore||[],L=K(P(w,v)),q=ie(r),E=new Map;for(const o of L){const H=o.definition.info?.title||"",j=o.definition.info?.version||"";E.set(o.relativePath,{name:H,description:typeof o.definition.info?.description=="string"?o.definition.info.description:"",version:j,servers:o.definition.servers||[],relativePath:o.relativePath,...q&&re(o.definition.info)?{fetchEligible:!0}:{}})}const y=X(P(O,v)),G=Object.values(t.products||{}).map(o=>o?.name).filter(B),I=t.l10n?.locales?.map(o=>o.code)??a.fs.localeFolders,N=oe({products:G,locales:I,requiresLogin:l,rbac:C,hasGraphqlApis:y.length>0,elicitationEnabled:c,hasCallableApis:E.values().some(o=>o.fetchEligible),feedbackHidden:t.feedback?.hide===!0});e.addMcpTools(D(b,"./docs-mcp/tools/index.js"),N),d==="code"&&e.addMcpTools(D(b,"./codemode/tools/execute.js"),[te]),i={apiDescriptionsMap:Object.fromEntries(E),graphqlDescriptions:y}}const n=await ae(e,a,m);s?.setAttribute("customToolsCount",String(n)),n!==u&&(u=n,n>0&&p.info(`Registered ${n} custom MCP tool${n===1?"":"s"} from @mcp folders`)),await le({actions:e,handlerPath:D(b,"./handlers/docs-mcp-handler.js"),apiDescriptionsMap:i.apiDescriptionsMap,graphqlDescriptions:i.graphqlDescriptions,mcpConfig:r,mcpMode:d,elicitationEnabled:c,gatewayFetchBudgetPerExec:h,publicEndpointStatus:_(t)}),f||(p.info("Registered Docs MCP Server endpoint at /mcp"),f=!0)})},async afterRoutesCreated(e,a){const s=await a.getConfig(),{mcp:t}=s,r=!t?.hide&&!t?.docs?.hide;e.markGatedMcpTools(await ee(e.getMcpTools())),e.setGlobalData({mcpData:{docs:{enabled:r,name:t?.docs?.name||S,publicEndpoint:_(s)==="served"}}})}}}var Oe=de;async function le({actions:i,handlerPath:m,apiDescriptionsMap:u,graphqlDescriptions:f,mcpConfig:e,mcpMode:a,elicitationEnabled:s,gatewayFetchBudgetPerExec:t,publicEndpointStatus:r}){i.createRequestHandler(T,m);const g=l=>async(C,d)=>{const c=z(d.getAllRoutes(),e?.docs?.ignore||[]);return c.length>0&&p.verbose(`mcp.docs.ignore: hiding ${c.length} page routes from MCP search`),{props:{config:{apiDescriptionsMap:u,graphqlDescriptions:f,mcpDocsServerName:e?.docs?.name||S,mcpMode:a,elicitationEnabled:s,gatewayFetchBudgetPerExec:t,searchIgnoredRoutes:c,...l?{isPublicEndpoint:l}:{}},serverOutDir:i.serverOutDir,tools:i.getMcpTools().map(({importPath:h,...n})=>n)}}};if(i.addApiRoute({slug:k,requestHandlerId:T,httpMethod:"all",getStaticData:g(!1)}),r==="no-protected-content"?p.info(`mcp.docs.publicEndpoint is enabled, but the project has no protected content - /mcp already serves anonymous users, skipping ${M}.`):r==="anonymous-denied"?p.info(`mcp.docs.publicEndpoint is enabled, but anonymous users are denied the MCP feature (rbac.features.mcp or requiresLogin) - skipping ${M}.`):r==="served"&&(i.addApiRoute({slug:M,requestHandlerId:T,httpMethod:"all",getStaticData:g(!0)}),p.verbose(`Registered public Docs MCP Server endpoint at ${M}`)),s){const l=D(b,"./handlers/mcp-credentials-handler.js");i.createRequestHandler(A,l),i.addApiRoute({slug:V,requestHandlerId:A,httpMethod:"all",getStaticData:async(C,d)=>{const{seo:c,colorMode:h}=d.getConfig(),{logo:n}=d.getGlobalData();return{props:{branding:ce({seo:c,logo:n,colorMode:h})}}}}),p.verbose("Registered MCP credentials endpoint at /mcp/credentials")}}export{Oe as default,de as mcpServerPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as v}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as L,MCP_TOOL_IS_AVAILABLE_KEY as k}from"../../../workers/mcp-tool-worker-pool.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as C,MANAGE_API_CREDENTIALS_TOOL_NAME as y}from"../constants.js";import{isAnonymousSessionToolAvailable as D}from"../docs-mcp/tools/core/create-anonymous-session.js";import{isManageApiCredentialsToolAvailable as N,manageApiCredentials as
|
|
1
|
+
import{logger as v}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as L,MCP_TOOL_IS_AVAILABLE_KEY as k}from"../../../workers/mcp-tool-worker-pool.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as C,MANAGE_API_CREDENTIALS_TOOL_NAME as y}from"../constants.js";import{isAnonymousSessionToolAvailable as D}from"../docs-mcp/tools/core/create-anonymous-session.js";import{isManageApiCredentialsToolAvailable as N,manageApiCredentials as w,manageApiCredentialsSchema as x}from"../codemode/tools/manage-credentials.js";import{EXECUTE_TOOL_SCHEMA as _}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as I,CODE_MODE_TOOL_NAMES as H,FETCH_TOOL_NAME as P}from"../codemode/constants.js";import{buildCodeModeInstructions as R,buildExecuteDescription as U}from"../codemode/prompts.js";import{toToolListEntries as F}from"../codemode/build-tool-list.js";import{composeExecuteAnnotations as z,getActiveCapabilities as B}from"../codemode/capabilities/index.js";import{describeToolsSchema as W,describeTools as X}from"../codemode/tools/describe-tools.js";import{availableSandboxTools as Y}from"../utils/available-sandbox-tools.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{toRegisterToolConfig as h}from"../utils/tool-registration.js";import{createMcpServer as $,createToolDispatch as j,extractSerializableContext as G}from"./mcp-server.js";function O(r,a){const o=a.schema;if(r)return o;const{sessionHandle:T,...p}=o.properties;return{...o,properties:p}}function K(r){return Object.fromEntries(r.map(a=>[a.name,a.schema]))}async function me({name:r,tools:a,context:o,skills:T=[],getKv:p}){const n=G(o),s=o.mcpMode==="code",l=s?B(o):[],b=l.some(e=>e.id===P),c=s?await Y(a.filter(e=>!H.has(e.name)),n):[],E=F(c,l),d=D(o)&&!S(C,o.metadata),g=s&&N(o)&&!S(y,o.metadata),m=$(r,s?R(b,E):void 0),u={getClientCapabilities:()=>m.server.getClientCapabilities(),getKv:p},f=j(s?{...n,sandboxToolSchemas:K(c)}:n,u),A=async e=>{try{return await L.exec(k,[{toolName:e,context:n}],{timeout:1e4})}catch(i){return v.error(`Failed to check MCP tool availability for "${e}": ${i instanceof Error?i.message:String(i)}`),!1}};if(s){const e=[{tool:{..._,description:U(b,E),schema:O(d,_),annotations:z(c,l,o.config?.mcp)},callback:f(I)},{tool:W(c,l),callback:X(c,A,l,o)}],i=a.find(t=>t.name===C);if(i&&d&&e.push({tool:i,callback:f(i.name)}),g){const t=x(o);e.push({tool:{...t,schema:O(d,t)},callback:w(n,u)})}for(const{tool:t,callback:M}of e)m.registerTool(t.name,h(t),M)}else await Promise.all(a.map(async e=>{const i=m.registerTool(e.name,h({...e,outputSchema:void 0}),f(e.name));await A(e.name)||i.disable()}));for(const e of T)m.registerResource(e.slug,e.uri,{title:e.name,description:e.description,mimeType:"text/markdown"},async()=>({contents:[{uri:e.uri,mimeType:"text/markdown",text:e.content}]}));return m}export{me as createDocsMcpServer};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{McpServer as U}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as _,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 D,stripAuthRequiredMeta as E,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{acceptedCredentialsLink as K,buildCredentialsAcceptedHint as j,buildCredentialsToolHint as F,buildUpstreamCredentialFallback as q,buildUpstreamCredentialInputRequired as v,credentialElicitationAnswer as H,dedupeElicitation as N,isStatelessRequest as P,schemeLabelOf as $,supportsUrlElicitation as B}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as y,resolveUpstreamApiAuth as G}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as V,resolveSecretSubject as W}from"../gateway-mcp/subject.js";const Y=6e4;function ue(e,t){return new U({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function le(e,t){return r=>async(n,i)=>{S.info(`MCP tool called: ${r}`);const s=e.elicitationEnabled??!1,u=P(i.mcpReq),a=s?W(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(!(!s||!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 d=async()=>{l=await c();const m={toolName:r,args:n,context:{...e,upstreamSecrets:l},extra:ee(i)};return await _.exec(O,[m],{timeout:Y})};let p=await d();const f=D(p);if(f.length>0&&s&&!o)return E(R(p,[{type:"text",text:V}]));if(f.length>0&&s&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${u?"2026-07-28":"2025"} clientElicitation=${J(t)}`);const m=await t.getKv(),h=await Q(e,f),w=f.map(C=>X(C,h)),k=Z(l),g=u?await z(e,i,w,o,m,k,h,t):await x(e,w,o,m,k,h);switch(g.kind){case"inputRequired":return g.result;case"retry":p=await d();break;case"prependText":p=R(p,[{type:"text",text:g.text},...p.content]);break;case"none":break}}return E(p)}}function R(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function J(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 Q(e,t){const r=new Map;for(const n of new Set(t.map(i=>i.api)))r.set(n,await G(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 i of Object.keys(n))t.add(b({api:r,scheme:i}));return t}function I(e,t){return e.status===401&&!t.has(b(e))}function T(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=>F(r,T(r,t))).join(`
|
|
2
2
|
|
|
3
|
-
`)}function A(e,t,r,n,
|
|
3
|
+
`)}function A(e,t,r,n,i){const[s,...u]=t,a=i.get(s.api),o=s.scheme??a?.defaultScheme??y,c=s.schemes&&s.schemes.length>1?s.schemes:void 0,l=c?void 0:T(s,i);return{subject:r,baseUrl:e.baseUrl??"",target:{api:s.api,name:s.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:s.status,...s.detail?{detail:s.detail}:{},otherApiNames:u.map(d=>d.name)}}}async function z(e,t,r,n,i,s,u,a){const o=H(t.mcpReq.inputResponses);if(o==="declined")return{kind:"none"};const c=r.filter(d=>I(d,s));if(c.length===0)return{kind:"prependText",text:M(r,u)};if(o==="accepted"){const d=await K(t.mcpReq.requestState(),{kv:i,subject:n,baseUrl:e.baseUrl??"",apis:c.map(f=>f.api)}),p=d?.apiName??c[0].name;return{kind:"prependText",text:j(p,d?.url)}}const l=A(e,c,n,i,u);return B(a?.getClientCapabilities())?{kind:"inputRequired",result:await v(l)}:{kind:"prependText",text:await q(l)}}async function x(e,t,r,n,i,s){const u=t.filter(c=>I(c,i));if(u.length===0)return{kind:"prependText",text:M(t,s)};const a=A(e,u,r,n,s);return{kind:"prependText",text:await N(`${r}:${b(u[0])}`,()=>q(a))}}function ee(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function de(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,fs:void 0}}export{ue as createMcpServer,le as createToolDispatch,de as extractSerializableContext};
|
|
@@ -5,6 +5,7 @@ import type { McpErrorCodes, McpServerType } from './constants';
|
|
|
5
5
|
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
|
+
import type { SiteBranding } from './handlers/credentials-page/types.js';
|
|
8
9
|
type ObjectValues<T> = T[keyof T];
|
|
9
10
|
export type McpServerType = ObjectValues<typeof McpServerType>;
|
|
10
11
|
export type McpErrorCodeTypes = ObjectValues<typeof McpErrorCodes>;
|
|
@@ -35,11 +36,17 @@ export type McpDocsStaticData = PageStaticData & {
|
|
|
35
36
|
props: {
|
|
36
37
|
config: McpDocsStaticDataPropsConfig;
|
|
37
38
|
serverOutDir?: string;
|
|
39
|
+
fetchCountSecret?: string;
|
|
38
40
|
tools?: McpToolSchema[];
|
|
39
41
|
skills?: Skill[];
|
|
40
42
|
skillsBaseUrl?: string;
|
|
41
43
|
};
|
|
42
44
|
};
|
|
45
|
+
export type CredentialsPageStaticData = PageStaticData & {
|
|
46
|
+
props?: {
|
|
47
|
+
branding?: SiteBranding;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
43
50
|
export type SkillMcpResource = {
|
|
44
51
|
slug: string;
|
|
45
52
|
name: string;
|
|
@@ -54,7 +61,7 @@ export type XMcpConfig = {
|
|
|
54
61
|
docs?: {
|
|
55
62
|
hide?: boolean;
|
|
56
63
|
};
|
|
57
|
-
|
|
64
|
+
apiCalls?: {
|
|
58
65
|
hide?: boolean;
|
|
59
66
|
};
|
|
60
67
|
};
|
|
@@ -82,6 +89,13 @@ export type McpToolExtra = {
|
|
|
82
89
|
requestId: RequestId;
|
|
83
90
|
_meta?: RequestMeta;
|
|
84
91
|
};
|
|
92
|
+
export type FetchCountRequest = {
|
|
93
|
+
caller: {
|
|
94
|
+
subject?: string;
|
|
95
|
+
ip?: string;
|
|
96
|
+
};
|
|
97
|
+
secret: string;
|
|
98
|
+
};
|
|
85
99
|
export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | keyof ApiFunctionsContextMethods> & {
|
|
86
100
|
apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
|
|
87
101
|
graphqlDescriptions: GraphqlDescriptionInfo[];
|
|
@@ -92,6 +106,7 @@ export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | k
|
|
|
92
106
|
mcpMode?: McpMode;
|
|
93
107
|
elicitationEnabled?: boolean;
|
|
94
108
|
gatewayFetchBudgetPerExec?: number;
|
|
109
|
+
fetchCountRequest?: FetchCountRequest;
|
|
95
110
|
clientIp?: string;
|
|
96
111
|
client?: string;
|
|
97
112
|
clientVersion?: string;
|
|
@@ -10,7 +10,10 @@ import type { McpMode } from '../types.js';
|
|
|
10
10
|
* data / McpToolContext instead (see docs-mcp-handler / execute-mcp-tool).
|
|
11
11
|
*/
|
|
12
12
|
export declare function isMcpCodeModeEnabled(): boolean;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The gateway capability: a guarded `fetch` in the `execute` sandbox. Requires code mode and a
|
|
15
|
+
* project database.
|
|
16
|
+
*/
|
|
14
17
|
export declare function isMcpGatewayEnabled(): boolean;
|
|
15
18
|
export declare function isMcpElicitationEnabled(): boolean;
|
|
16
19
|
export declare function getMcpMode(): McpMode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EntitlementsProvider as e}from"../../../entitlements/entitlements-provider.js";function t(){return e.instance().entitlements?.mcpMode==="code"}function
|
|
1
|
+
import{EntitlementsProvider as e}from"../../../entitlements/entitlements-provider.js";import{hasProjectDatabase as n}from"../../../providers/database/has-project-database.js";function t(){return e.instance().entitlements?.mcpMode==="code"}function o(){return!!e.instance().canAccessFeature("mcpGateway")&&t()&&n()}function i(){return o()}function a(){return t()?"code":"tools"}export{a as getMcpMode,t as isMcpCodeModeEnabled,i as isMcpElicitationEnabled,o as isMcpGatewayEnabled};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type { OpenAPIDefinition } from '@redocly/api-docs';
|
|
2
2
|
import type { XMcpConfig, XMcpSection } from '../types.js';
|
|
3
|
-
/** Whether the path or operation is hidden for `section`. */
|
|
3
|
+
/** Whether the path item or operation is hidden for `section`. */
|
|
4
4
|
export declare function isEndpointHidden(endpoint: {
|
|
5
5
|
'x-mcp'?: XMcpConfig;
|
|
6
6
|
} | undefined, section: XMcpSection): boolean;
|
|
7
|
-
/** Whether the definition's info-level x-mcp hides it for `section
|
|
8
|
-
export declare function isDefinitionHidden(info
|
|
9
|
-
/** Whether the API explicitly opts into the gateway via `x-mcp.gateway`. */
|
|
10
|
-
export declare function hasGatewayConfig(info: OpenAPIDefinition['info'] | undefined): boolean;
|
|
7
|
+
/** Whether the definition's info-level x-mcp hides it for `section`. */
|
|
8
|
+
export declare function isDefinitionHidden(info: OpenAPIDefinition['info'] | undefined, section: XMcpSection): boolean;
|
|
11
9
|
//# sourceMappingURL=xmcp-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function e(i,n){return i?.["x-mcp"]?.[n]?.hide===!0}function t(i,n){return i?.["x-mcp"]?.[n]?.hide===!0}export{t as isDefinitionHidden,e as isEndpointHidden};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as v from"path";import{REDOCLY_ROUTE_RBAC as b,REDOCLY_TEAMS_RBAC as h}from"@redocly/config";import{VERSION_SEPARATOR as M}from"../constants/common.js";import{DEFAULT_LOCALE_PLACEHOLDER as _}from"../../constants/common.js";import{removeTrailingSlash as j}from"../../utils/url/remove-trailing-slash.js";import{isPrimitive as W}from"../../utils/guards/is-primitive.js";import{slash as w}from"../../utils/path/slash.js";import{isAbsoluteUrl as z}from"../../utils/url/is-absolute-url.js";import{normalizeRouteSlug as J}from"../../utils/path/normalize-route-slug.js";import{parsePathVersions as C}from"../../utils/path/parse-path-versions.js";import{logger as A}from"../tools/notifiers/logger.js";import{reporter as S}from"../tools/notifiers/reporter.js";import{shaDirPathShort as R}from"../utils/crypto/sha-dir-path-short.js";import{copyStaticFile as U,FileNotFoundError as E}from"../utils/fs.js";import{isIconPath as H,resolveAssetPath as Y}from"../utils/index.js";import{resolveSrcSet as G}from"../utils/resolve-src-set.js";import{isL10nPath as B}from"../fs/utils/is-l10n-path.js";import{getLocaleFromRelativePath as q}from"../fs/utils/get-locale-from-relative-path.js";async function N(e,i,n,t,a){if(!e)return;const f={...a,ignoreCustomSidebar:!0};if(W(e)){if(typeof e=="string"){const r=F(n.contentDir,i,a,e,t.fs);if(t.fs.exists(r)){if(n.getRouteByFsPath(r))return K({page:e},i,n,t,f);{const g=t.fs.getFileInfo(r);return g?U(n.contentDir,g.realRelativePath,n.outdir):void 0}}}return e}return Array.isArray(e)?I(D(e),i,n,t,f):Object.fromEntries(await Promise.all(Object.entries(e).map(async([r,l])=>[r,await N(l,i,n,t,a)])))}function D(e){return e.map(i=>({...i,items:i.items?D(i.items):void 0}))}async function I(e,i,n,t,a){if(Array.isArray(e))return(await Promise.all(e.map(f=>K(f,i,n,t,a)))).flatMap(f=>f)}async function y(e,i,n,t){let a,f;if(typeof e.icon=="object"){if("srcSet"in e.icon)try{a=await G(e.icon.srcSet,n.fs,{fromFileRelativePath:t.navFile,contentDir:i.contentDir,outdir:i.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`):await S.panicOnBuild(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`)}}else if(typeof e.icon=="string")if(z(e.icon)||H(e.icon))try{f=await Y(e.icon,n.fs,{fromFileRelativePath:t.navFile,contentDir:i.contentDir,outdir:i.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon" from ${t.navFile}: file ${f} does not exist`):await S.panicOnBuild(`Cannot resolve "item.icon" from ${t.navFile}: ${d.message}`)}else f=e.icon;return{icon:f,srcSet:a}}function Q(e){return i=>{if(i.type==="link"||i.type==="group"){const n=i.metadata;return n?Object.entries(e).every(([t,a])=>Array.isArray(a)?a.some(f=>n[t]===f):n[t]===a):!1}return!0}}async function K(e,i,n,t,a){if(e?.tab!==void 0||e?.menu!==void 0){const s=`Navigation tabs ("tab"/"menu") are only allowed at the top level of a sidebars.yaml file: ${JSON.stringify(e)}`;return await S.panicOnBuildContentError(`Invalid nav item in %rp. ${s}`,a.navFile),{type:"error",label:s}}if(e?.directory&&e.items?.length)return{type:"error",label:`Can't have both "directory" and "items" in the nav item: ${JSON.stringify(e)}`};e?.directory&&e?.group&&(e={...e,directory:void 0,items:[{directory:e.directory}]});const f=e?.directory?F(n.contentDir,i,a,e.directory,t.fs):void 0;if(f!==void 0){const s=f===""?"":f+"/",{locale:u,ignoredRoutes:o}=a;let p=n.getAllRoutesForLocale(u).filter(c=>!o?.has(c.baseSlug||"")&&c.fsPath.startsWith(s)&&!c.excludeFromSidebar).sort((c,P)=>c.fsPath===P.fsPath?0:c.baseSlug.localeCompare(P.baseSlug,void 0,{numeric:!0}));const m=e.includeByMetadata?Q(e.includeByMetadata):Boolean;if(!p.length)return[];const T=(await Promise.all(p.map(async c=>{const P=c.versions?.find(x=>x.active),L=P&&{version:P.version,isDefault:P.default,versionFolderId:P.folderId},V=ee(v.posix.relative(f,c.fsPath)),O=c.getSidebar?.(c);return!a.ignoreCustomSidebar&&O?.length?{type:"group",fsPath:c.fsPath,metadata:c.metadata,link:c.slug,routeSlug:c.slug,label:await c.getNavText?.()||c.slug,[h]:c[h],[b]:c[b],sidebarItems:k(O,L,c[h],c[b]),...L,relativePathFromDirectory:v.relative(f,c.fsPath).replace(/@(?<!@[^/]*?@)[^/]+\//,"")}:{type:"link",fsPath:c.fsPath,metadata:c.metadata,[h]:c[h],[b]:c[b],label:await c.getNavText?.()||c.slug,link:c.slug,routeSlug:c.slug,...L,relativePathFromDirectory:V}}))).filter(m);return e.flatten?$(T,a):Z(T,a)}let d=typeof e=="string"?e:e?.page,r,l;if(d){if(d.includes("#")){const[s,u]=d.split("#");u?l=u:A.warn(`Invalid heading anchor format in sidebar: "${u}". Heading anchors should contain only alphanumeric characters, hyphens, and underscores.`),d=s}if(d=j(d),a.locale&&a.locale!==_){const s=J(v.join(a.locale.toLowerCase(),d));r=n.getRouteBySlug(s)}r||(r=n.getRouteBySlug(d)),r||(r=n.getRouteByFsPath(F(n.contentDir,i,a,d,t.fs)))}const g=r?.metadata;if(e?.$ref){let s=F(n.contentDir,i,a,e.$ref,t.fs);if(a.ref!==void 0&&(s=v.posix.join(a.ref,e.$ref)),!t.fs.exists(s))return await S.panicOnBuildContentError(`Failed to load ${s} file. Make sure sidebar $ref path is correct.`),[];const u=await t.cache.load(s,"yaml"),o=v.dirname(s);return await I(u.data,i,n,t,{...a,navFile:s,ref:o})||[]}if(!r){const s=a.excludedFromLinkCheckerPatterns?.catalog.some(o=>o.test(d||"")),u=a.excludedFromLinkCheckerPatterns?.apiFunctions.some(o=>o.test(d||e.href||""));(u||s)&&(e={...e,href:d||e.href,page:void 0,target:e.target??(u?"_blank":void 0)}),await X(e,a,t,i)}if(r&&!e.disconnect&&!a.ignoreCustomSidebar&&(l||r?.getSidebar)){const s=r.versions?.find(o=>o.active),u=s&&{version:s.version,isDefault:s.default,versionFolderId:s.folderId};if(l){let o=[];if(r.getSidebar&&(o=r.getSidebar(r,{...e,...await y(e,n,t,a)}),o&&o.length>0)){const p=o[0];p&&p.link&&(p.link=`${p.link}#${l}`)}if(!o||o.length===0){let p=e.group||e.label||l;o=[{type:"link",fsPath:r.fsPath,metadata:r.metadata,link:`${r.slug}#${l}`,routeSlug:r.slug,label:p,labelTranslationKey:e.labelTranslationKey,...await y(e,n,t,a),[h]:r[h],[b]:{slug:r.slug,fsPath:r.fsPath},...u}]}return k(o,u,r[h],r[b])}if(r?.getSidebar){const o=r.getSidebar(r,{...e,...await y(e,n,t,a)}),p=e.group&&o?.[0]?.routeSlug===r.slug?o.slice(1):o;return k(a.groupCustomSidebars||e.group?[{type:"group",fsPath:r.fsPath,link:r.slug,routeSlug:r.slug,label:e.group||e.label||await r.getNavText?.()||r.slug,items:p,labelTranslationKey:e.labelTranslationKey,metadata:g,badges:e.badges,...await y(e,n,t,a)}]:o,u,r[h],r[b])}}if(r&&!e.group){const s=l?`${r.slug}#${l}`:r.slug;let u=e.label||l||"";u||(u=await r.getNavText?.()||r.slug);const o=r.versions?.find(m=>m.active),p=o&&{version:o.version,isDefault:o.default,versionFolderId:o.folderId};return{type:"link",fsPath:r.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,[h]:e?.rbac||r[h],[b]:{slug:r.slug,fsPath:r.fsPath},label:u,labelTranslationKey:e.labelTranslationKey,link:s,items:await I(e.items,i,n,t,a),separatorLine:e.separatorLine,linePosition:e.linePosition,routeSlug:e.disconnect?void 0:s,external:e.external,target:e.target,badges:e.badges,...await y(e,n,t,a),...p,additionalProps:e.additionalProps}}else if(e?.group){const s=r?.versions?.find(o=>o.active),u=C(a?.navFile);return{type:"group",fsPath:r?.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,version:s?.version||u?.versionName,versionFolderId:s?.folderId||(u?.versionFolderPath?R(u.versionFolderPath):void 0),label:e.group,link:r?.slug,routeSlug:r?.slug,badges:e.badges,labelTranslationKey:e.groupTranslationKey,items:await I(e.items,i,n,t,a),expanded:e.expanded?e.expanded.toString():void 0,selectFirstItemOnExpand:e.selectFirstItemOnExpand,menuStyle:e.menuStyle,separatorLine:e.separatorLine,linePosition:e.linePosition,...await y(e,n,t,a),[h]:e?.rbac,[b]:{slug:r?.slug||"",fsPath:r?.fsPath||""},additionalProps:e.additionalProps}}else{if(e?.href||e?.label)return{type:"link",metadata:g,link:e.href||"",label:e?.label||e?.href||"",labelTranslationKey:e.labelTranslationKey,external:e.external,target:e.target,separatorLine:e.separatorLine,linePosition:e.linePosition,badges:e.badges,...await y(e,n,t,a),[h]:e?.rbac,additionalProps:e.additionalProps};if(e?.separator!=null||e?.separatorLine!=null){const s=C(a?.navFile);return{type:"separator",metadata:g,version:s?.versionName,versionFolderId:s?.versionFolderPath?R(s.versionFolderPath):void 0,label:e.separator,labelTranslationKey:e.separatorTranslationKey,separatorLine:e.separatorLine,linePosition:e.linePosition,...await y(e,n,t,a),[h]:e?.rbac,additionalProps:e.additionalProps}}else{const s=C(a?.navFile);return{type:"error",label:`Can't resolve page: ${JSON.stringify(e)}`,version:s?.versionName,versionFolderId:s?.versionFolderPath?R(s.versionFolderPath):void 0}}}}async function X(e,i,n,t){const{href:a,page:f}=e;if(a||!f)return;const d=F(n.fs.cwd,t,i,f,n.fs),r=n.fs.exists(d),l=await n.isPathIgnored(d),g=(r?"The page is ignored: ":"Can't resolve page: ")+f;(!r||l)&&S.reportBrokenLink({type:"BROKEN_LINK",brokenLinkType:"LINK",title:e.label||e.group||"",link:d,rawLink:f,message:g,sourceFileRelativePath:i.navFile,sourceFileLocation:{line:0}})}function F(e,i,n,t="",a){if(n.ref!==void 0)return w(v.relative(e,v.resolve(e,v.join(n.ref,t))));if(t.startsWith("/")){const f=B(i)?q(i):void 0,d=f?`${a.localizationFolder}/${f}/`:"",r=t.slice(1);return B(r)?r:d+w(r)}return w(v.relative(e,v.resolve(e,i,t)))}function Z(e,i){const n={};for(const r of e){const l=v.dirname(r.relativePathFromDirectory),g=r.version?M+r.version:"",s=v.basename(r.relativePathFromDirectory)+g;d(l,r,s)}const t=f(a(n));return $(t,i);function a(r){const l=[];for(const g of Object.keys(r)){const s=r[g];l.push({...s,items:s.items?a(s.items):void 0})}return l}function f(r){return r.sort((l,g)=>{const s=typeof l=="string"?l.toLowerCase():l.relativePathFromDirectory||l.label||"",u=typeof g=="string"?g.toLowerCase():g.relativePathFromDirectory||g.label||"";return s.startsWith("index.")?-1:u.startsWith("index.")?1:s.localeCompare(u,void 0,{numeric:!0})})}function d(r,l,g){r==="."&&(r="");const s=r.split("/").filter(Boolean);let u=n;for(const o of s){const p=o+(l?.version||"");u[p]||(u[p]={type:"group",version:l?.version,label:o,isDefault:l?.isDefault,versionFolderId:l.versionFolderId,items:{}}),u=u[p].items}u[g]=l}}function $(e,i){return e.flatMap(n=>n?.sidebarItems?i.groupCustomSidebars?{...n,items:n.sidebarItems,sidebarItems:void 0,relativePathFromDirectory:void 0}:n.sidebarItems:{...n,items:n.items?$(n.items,i):void 0})}function k(e,i,n,t){return e.map(a=>({...a,...i,[h]:a[h]||n,[b]:a[b]||t,items:a.type==="group"&&a.items?k(a.items,i,n):a.items}))}function ee(e){return e.replace(/@(?<!@[^/]*?@)[^/]+\//,"")}async function ye(e,i,n,t){const a=(e?.items||[]).filter(r=>r.linkedSidebars?.length).map(r=>({...r,items:void 0})),f=await N(a,i.contentDir,i,n,t),d=new Map;for(const r of f)if(r.linkedSidebars?.length)for(const l of r.linkedSidebars){if(d.has(l)){A.warn(`Only one navbar item can belong to sidebar. "${l}" on 'linkedSidebars' property on "${r.label}" will be ignored.`);continue}d.set(l,{label:r.label,link:r.link})}return d}export{ye as collectItemsLinkedToSidebars,D as normalizeItems,K as resolveItem,I as resolveItems,N as resolveLinksFromConfig};
|
|
1
|
+
import*as v from"path";import{REDOCLY_ROUTE_RBAC as b,REDOCLY_TEAMS_RBAC as h}from"@redocly/config";import{VERSION_SEPARATOR as M}from"../constants/common.js";import{DEFAULT_LOCALE_PLACEHOLDER as _}from"../../constants/common.js";import{removeTrailingSlash as j}from"../../utils/url/remove-trailing-slash.js";import{isPrimitive as W}from"../../utils/guards/is-primitive.js";import{slash as w}from"../../utils/path/slash.js";import{isAbsoluteUrl as z}from"../../utils/url/is-absolute-url.js";import{normalizeRouteSlug as J}from"../../utils/path/normalize-route-slug.js";import{parsePathVersions as C}from"../../utils/path/parse-path-versions.js";import{logger as A}from"../tools/notifiers/logger.js";import{reporter as S}from"../tools/notifiers/reporter.js";import{shaDirPathShort as R}from"../utils/crypto/sha-dir-path-short.js";import{copyStaticFile as U,FileNotFoundError as E}from"../utils/fs.js";import{isIconPath as H,resolveAssetPath as Y}from"../utils/index.js";import{resolveSrcSet as G}from"../utils/resolve-src-set.js";import{isL10nPath as B}from"../fs/utils/is-l10n-path.js";import{getLocaleFromRelativePath as q}from"../fs/utils/get-locale-from-relative-path.js";async function N(e,i,n,t,a){if(!e)return;const f={...a,ignoreCustomSidebar:!0};if(W(e)){if(typeof e=="string"){const r=F(n.contentDir,i,a,e,t.fs);if(t.fs.exists(r)){if(n.getRouteByFsPath(r))return K({page:e},i,n,t,f);{const g=t.fs.getFileInfo(r);return g?U(n.contentDir,g.realRelativePath,n.outdir):void 0}}}return e}return Array.isArray(e)?I(D(e),i,n,t,f):Object.fromEntries(await Promise.all(Object.entries(e).map(async([r,l])=>[r,await N(l,i,n,t,a)])))}function D(e){return e.map(i=>({...i,items:i.items?D(i.items):void 0}))}async function I(e,i,n,t,a){if(Array.isArray(e))return(await Promise.all(e.map(f=>K(f,i,n,t,a)))).flatMap(f=>f)}async function y(e,i,n,t){let a,f;if(typeof e.icon=="object"){if("srcSet"in e.icon)try{a=await G(e.icon.srcSet,n.fs,{fromFileRelativePath:t.navFile,contentDir:i.contentDir,outdir:i.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`):await S.panicOnBuild(`Cannot resolve "item.icon.srcSet" from ${t.navFile}: ${d.message}`)}}else if(typeof e.icon=="string")if(z(e.icon)||H(e.icon))try{f=await Y(e.icon,n.fs,{fromFileRelativePath:t.navFile,contentDir:i.contentDir,outdir:i.outdir})}catch(d){d instanceof E?await S.panicOnBuildContentError(`Cannot resolve "item.icon" from ${t.navFile}: file ${f} does not exist`):await S.panicOnBuild(`Cannot resolve "item.icon" from ${t.navFile}: ${d.message}`)}else f=e.icon;return{icon:f,srcSet:a}}function Q(e){return i=>{if(i.type==="link"||i.type==="group"){const n=i.metadata;return n?Object.entries(e).every(([t,a])=>Array.isArray(a)?a.some(f=>n[t]===f):n[t]===a):!1}return!0}}async function K(e,i,n,t,a){if(e?.tab!==void 0||e?.menu!==void 0){const s=`Navigation tabs ("tab"/"menu") are only allowed at the top level of a sidebars.yaml file: ${JSON.stringify(e)}`;return await S.panicOnBuildContentError(`Invalid nav item in %rp. ${s}`,a.navFile),{type:"error",label:s}}if(e?.directory&&e.items?.length)return{type:"error",label:`Can't have both "directory" and "items" in the nav item: ${JSON.stringify(e)}`};e?.directory&&e?.group&&(e={...e,directory:void 0,items:[{directory:e.directory}]});const f=e?.directory?F(n.contentDir,i,a,e.directory,t.fs):void 0;if(f!==void 0){const s=f===""?"":f+"/",{locale:u,ignoredRoutes:o}=a,p=n.getAllRoutesForLocale(u).filter(c=>!o?.has(c.baseSlug||"")&&c.fsPath.startsWith(s)&&!c.excludeFromSidebar).sort((c,P)=>c.fsPath===P.fsPath?0:c.baseSlug.localeCompare(P.baseSlug,void 0,{numeric:!0})),m=e.includeByMetadata?Q(e.includeByMetadata):Boolean;if(!p.length)return[];const T=(await Promise.all(p.map(async c=>{const P=c.versions?.find(x=>x.active),L=P&&{version:P.version,isDefault:P.default,versionFolderId:P.folderId},V=ee(v.posix.relative(f,c.fsPath)),O=c.getSidebar?.(c);return!a.ignoreCustomSidebar&&O?.length?{type:"group",fsPath:c.fsPath,metadata:c.metadata,link:c.slug,routeSlug:c.slug,label:await c.getNavText?.()||c.slug,[h]:c[h],[b]:c[b],sidebarItems:k(O,L,c[h],c[b]),...L,relativePathFromDirectory:v.relative(f,c.fsPath).replace(/@(?<!@[^/]*?@)[^/]+\//,"")}:{type:"link",fsPath:c.fsPath,metadata:c.metadata,[h]:c[h],[b]:c[b],label:await c.getNavText?.()||c.slug,link:c.slug,routeSlug:c.slug,...L,relativePathFromDirectory:V}}))).filter(m);return e.flatten?$(T,a):Z(T,a)}let d=typeof e=="string"?e:e?.page,r,l;if(d){if(d.includes("#")){const[s,u]=d.split("#");u?l=u:A.warn(`Invalid heading anchor format in sidebar: "${u}". Heading anchors should contain only alphanumeric characters, hyphens, and underscores.`),d=s}if(d=j(d),a.locale&&a.locale!==_){const s=J(v.join(a.locale.toLowerCase(),d));r=n.getRouteBySlug(s)}r||(r=n.getRouteBySlug(d)),r||(r=n.getRouteByFsPath(F(n.contentDir,i,a,d,t.fs)))}const g=r?.metadata;if(e?.$ref){let s=F(n.contentDir,i,a,e.$ref,t.fs);if(a.ref!==void 0&&(s=v.posix.join(a.ref,e.$ref)),!t.fs.exists(s))return await S.panicOnBuildContentError(`Failed to load ${s} file. Make sure sidebar $ref path is correct.`),[];const u=await t.cache.load(s,"yaml"),o=v.dirname(s);return await I(u.data,i,n,t,{...a,navFile:s,ref:o})||[]}if(!r){const s=a.excludedFromLinkCheckerPatterns?.catalog.some(o=>o.test(d||"")),u=a.excludedFromLinkCheckerPatterns?.apiFunctions.some(o=>o.test(d||e.href||""));(u||s)&&(e={...e,href:d||e.href,page:void 0,target:e.target??(u?"_blank":void 0)}),await X(e,a,t,i)}if(r&&!e.disconnect&&!a.ignoreCustomSidebar&&(l||r?.getSidebar)){const s=r.versions?.find(o=>o.active),u=s&&{version:s.version,isDefault:s.default,versionFolderId:s.folderId};if(l){let o=[];if(r.getSidebar&&(o=r.getSidebar(r,{...e,...await y(e,n,t,a)}),o&&o.length>0)){const p=o[0];p&&p.link&&(p.link=`${p.link}#${l}`)}if(!o||o.length===0){const p=e.group||e.label||l;o=[{type:"link",fsPath:r.fsPath,metadata:r.metadata,link:`${r.slug}#${l}`,routeSlug:r.slug,label:p,labelTranslationKey:e.labelTranslationKey,...await y(e,n,t,a),[h]:r[h],[b]:{slug:r.slug,fsPath:r.fsPath},...u}]}return k(o,u,r[h],r[b])}if(r?.getSidebar){const o=r.getSidebar(r,{...e,...await y(e,n,t,a)}),p=e.group&&o?.[0]?.routeSlug===r.slug?o.slice(1):o;return k(a.groupCustomSidebars||e.group?[{type:"group",fsPath:r.fsPath,link:r.slug,routeSlug:r.slug,label:e.group||e.label||await r.getNavText?.()||r.slug,items:p,labelTranslationKey:e.labelTranslationKey,metadata:g,badges:e.badges,...await y(e,n,t,a)}]:o,u,r[h],r[b])}}if(r&&!e.group){const s=l?`${r.slug}#${l}`:r.slug;let u=e.label||l||"";u||(u=await r.getNavText?.()||r.slug);const o=r.versions?.find(m=>m.active),p=o&&{version:o.version,isDefault:o.default,versionFolderId:o.folderId};return{type:"link",fsPath:r.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,[h]:e?.rbac||r[h],[b]:{slug:r.slug,fsPath:r.fsPath},label:u,labelTranslationKey:e.labelTranslationKey,link:s,items:await I(e.items,i,n,t,a),separatorLine:e.separatorLine,linePosition:e.linePosition,routeSlug:e.disconnect?void 0:s,external:e.external,target:e.target,badges:e.badges,...await y(e,n,t,a),...p,additionalProps:e.additionalProps}}else if(e?.group){const s=r?.versions?.find(o=>o.active),u=C(a?.navFile);return{type:"group",fsPath:r?.fsPath,linkedSidebars:e.linkedSidebars,metadata:g,version:s?.version||u?.versionName,versionFolderId:s?.folderId||(u?.versionFolderPath?R(u.versionFolderPath):void 0),label:e.group,link:r?.slug,routeSlug:r?.slug,badges:e.badges,labelTranslationKey:e.groupTranslationKey,items:await I(e.items,i,n,t,a),expanded:e.expanded?e.expanded.toString():void 0,selectFirstItemOnExpand:e.selectFirstItemOnExpand,menuStyle:e.menuStyle,separatorLine:e.separatorLine,linePosition:e.linePosition,...await y(e,n,t,a),[h]:e?.rbac,[b]:{slug:r?.slug||"",fsPath:r?.fsPath||""},additionalProps:e.additionalProps}}else{if(e?.href||e?.label)return{type:"link",metadata:g,link:e.href||"",label:e?.label||e?.href||"",labelTranslationKey:e.labelTranslationKey,external:e.external,target:e.target,separatorLine:e.separatorLine,linePosition:e.linePosition,badges:e.badges,...await y(e,n,t,a),[h]:e?.rbac,additionalProps:e.additionalProps};if(e?.separator!=null||e?.separatorLine!=null){const s=C(a?.navFile);return{type:"separator",metadata:g,version:s?.versionName,versionFolderId:s?.versionFolderPath?R(s.versionFolderPath):void 0,label:e.separator,labelTranslationKey:e.separatorTranslationKey,separatorLine:e.separatorLine,linePosition:e.linePosition,...await y(e,n,t,a),[h]:e?.rbac,additionalProps:e.additionalProps}}else{const s=C(a?.navFile);return{type:"error",label:`Can't resolve page: ${JSON.stringify(e)}`,version:s?.versionName,versionFolderId:s?.versionFolderPath?R(s.versionFolderPath):void 0}}}}async function X(e,i,n,t){const{href:a,page:f}=e;if(a||!f)return;const d=F(n.fs.cwd,t,i,f,n.fs),r=n.fs.exists(d),l=await n.isPathIgnored(d),g=(r?"The page is ignored: ":"Can't resolve page: ")+f;(!r||l)&&S.reportBrokenLink({type:"BROKEN_LINK",brokenLinkType:"LINK",title:e.label||e.group||"",link:d,rawLink:f,message:g,sourceFileRelativePath:i.navFile,sourceFileLocation:{line:0}})}function F(e,i,n,t="",a){if(n.ref!==void 0)return w(v.relative(e,v.resolve(e,v.join(n.ref,t))));if(t.startsWith("/")){const f=B(i)?q(i):void 0,d=f?`${a.localizationFolder}/${f}/`:"",r=t.slice(1);return B(r)?r:d+w(r)}return w(v.relative(e,v.resolve(e,i,t)))}function Z(e,i){const n={};for(const r of e){const l=v.dirname(r.relativePathFromDirectory),g=r.version?M+r.version:"",s=v.basename(r.relativePathFromDirectory)+g;d(l,r,s)}const t=f(a(n));return $(t,i);function a(r){const l=[];for(const g of Object.keys(r)){const s=r[g];l.push({...s,items:s.items?a(s.items):void 0})}return l}function f(r){return r.sort((l,g)=>{const s=typeof l=="string"?l.toLowerCase():l.relativePathFromDirectory||l.label||"",u=typeof g=="string"?g.toLowerCase():g.relativePathFromDirectory||g.label||"";return s.startsWith("index.")?-1:u.startsWith("index.")?1:s.localeCompare(u,void 0,{numeric:!0})})}function d(r,l,g){r==="."&&(r="");const s=r.split("/").filter(Boolean);let u=n;for(const o of s){const p=o+(l?.version||"");u[p]||(u[p]={type:"group",version:l?.version,label:o,isDefault:l?.isDefault,versionFolderId:l.versionFolderId,items:{}}),u=u[p].items}u[g]=l}}function $(e,i){return e.flatMap(n=>n?.sidebarItems?i.groupCustomSidebars?{...n,items:n.sidebarItems,sidebarItems:void 0,relativePathFromDirectory:void 0}:n.sidebarItems:{...n,items:n.items?$(n.items,i):void 0})}function k(e,i,n,t){return e.map(a=>({...a,...i,[h]:a[h]||n,[b]:a[b]||t,items:a.type==="group"&&a.items?k(a.items,i,n):a.items}))}function ee(e){return e.replace(/@(?<!@[^/]*?@)[^/]+\//,"")}async function ye(e,i,n,t){const a=(e?.items||[]).filter(r=>r.linkedSidebars?.length).map(r=>({...r,items:void 0})),f=await N(a,i.contentDir,i,n,t),d=new Map;for(const r of f)if(r.linkedSidebars?.length)for(const l of r.linkedSidebars){if(d.has(l)){A.warn(`Only one navbar item can belong to sidebar. "${l}" on 'linkedSidebars' property on "${r.label}" will be ignored.`);continue}d.set(l,{label:r.label,link:r.link})}return d}export{ye as collectItemsLinkedToSidebars,D as normalizeItems,K as resolveItem,I as resolveItems,N as resolveLinksFromConfig};
|