From 0224b517b20bc943dddd31857280cbe1b83e5777 Mon Sep 17 00:00:00 2001 From: Zach Shilton <4624598+zchsh@users.noreply.github.com> Date: Thu, 6 Jul 2023 08:55:50 -0400 Subject: [PATCH 1/4] feat: add HCP Vault Secrets API docs --- .../api-docs/vault-secrets/[[...page]].tsx | 111 ++++++++++++++++++ .../path-truncation-aside/index.tsx | 17 ++- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx diff --git a/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx b/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx new file mode 100644 index 0000000000..ac4e3dec9e --- /dev/null +++ b/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx @@ -0,0 +1,111 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// View +import ApiDocsView from 'views/api-docs-view' +import { + getApiDocsStaticProps, + getApiDocsStaticPaths, + ApiDocsParams, +} from 'views/api-docs-view/server' +import { buildApiDocsBreadcrumbs } from 'views/api-docs-view/server/get-api-docs-static-props/utils' +import { fetchCloudApiVersionData } from 'views/api-docs-view/utils' +// Components +import { + PathTruncationAside, + truncateVaultSecretsOperationPath, +} from 'views/api-docs-view/components' +// Types +import type { OperationObjectType } from 'components/open-api-page/types' +import type { ApiDocsViewProps } from 'views/api-docs-view/types' +import type { GetStaticPaths, GetStaticProps } from 'next' +import { isDeployPreview } from 'lib/env-checks' + +/** + * The product slug is used to fetch product data for the layout. + */ +const PRODUCT_SLUG = 'hcp' + +/** + * The baseUrl is used to generate + * breadcrumb links, sidebar nav levels, and version switcher links. + */ +const BASE_URL = '/hcp/api-docs/vault-secrets' + +/** + * We source version data from a directory in the `hcp-specs` repo. + * See `fetchCloudApiVersionData` for details. + */ +const GITHUB_SOURCE_DIRECTORY = { + owner: 'hashicorp', + repo: 'hcp-specs', + path: 'specs/cloud-vault-secrets', + ref: 'main', +} + +/** + * Render `` with custom operation path truncation + * for HCP Vault secrets. + */ +function HcpVaultSecretsApiDocsView(props: ApiDocsViewProps) { + return ( + ( + + )} + /> + ) +} + +/** + * Get static paths, using `versionData` fetched from GitHub. + */ +export const getStaticPaths: GetStaticPaths = async () => { + // If we are in a deploy preview, don't pre-render any paths + if (isDeployPreview()) { + return { paths: [], fallback: 'blocking' } + } + // Otherwise, fetch version data, and use that to generate paths + const versionData = await fetchCloudApiVersionData(GITHUB_SOURCE_DIRECTORY) + return await getApiDocsStaticPaths({ productSlug: PRODUCT_SLUG, versionData }) +} + +/** + * Get static props, using `versionData` fetched from GitHub. + * + * We need all version data for the version selector, + * and of course we need specific data for the current version. + */ +export const getStaticProps: GetStaticProps< + ApiDocsViewProps, + ApiDocsParams +> = async ({ params }: { params: ApiDocsParams }) => { + // Fetch all version data, based on remote `stable` & `preview` subfolders + const versionData = await fetchCloudApiVersionData(GITHUB_SOURCE_DIRECTORY) + // If we can't find any version data at all, render a 404 page. + if (!versionData) { + return { notFound: true } + } + // Return static props + return await getApiDocsStaticProps({ + productSlug: PRODUCT_SLUG, + baseUrl: BASE_URL, + pathParts: params.page, + versionData, + buildCustomBreadcrumbs: ({ productData, serviceData, versionId }) => { + return buildApiDocsBreadcrumbs({ + productData, + // HCP API docs at `/api-docs` are not linkable, so we pass url=null + apiDocs: { name: 'API', url: null }, + serviceData, + versionId, + }) + }, + }) +} + +export default HcpVaultSecretsApiDocsView diff --git a/src/views/api-docs-view/components/path-truncation-aside/index.tsx b/src/views/api-docs-view/components/path-truncation-aside/index.tsx index bc7e18a65d..c5d56aa767 100644 --- a/src/views/api-docs-view/components/path-truncation-aside/index.tsx +++ b/src/views/api-docs-view/components/path-truncation-aside/index.tsx @@ -6,6 +6,17 @@ import DevDotContent from 'components/dev-dot-content' import CodeBlock from '@hashicorp/react-code-block' +/** + * Truncates HCP Vault Secrets API operation paths for clarity. + * Intended to be used with a `` in each operation intro. + */ +function truncateVaultSecretsOperationPath(path: string) { + return path.replace( + /\/secrets\/\d\d\d\d-\d\d-\d\d\/organizations\/\{location.organization_id\}\/projects\/\{location\.project_id\}/, + '' + ) +} + /** * Truncates HCP Packer API operation paths for clarity. * Intended to be used with a `` in each operation intro. @@ -39,4 +50,8 @@ function PathTruncationAside({ path }: { path: string }) { ) } -export { PathTruncationAside, truncatePackerOperationPath } +export { + PathTruncationAside, + truncatePackerOperationPath, + truncateVaultSecretsOperationPath, +} From 2275f81aebf12d4568e65bd78df8fca5d8312394 Mon Sep 17 00:00:00 2001 From: Zach Shilton <4624598+zchsh@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:21:41 -0400 Subject: [PATCH 2/4] chore: allow empty serviceData.name for Vault Secrets --- src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx | 12 +++++++++++- src/views/api-docs-view/api-docs-view.module.css | 8 +++++++- src/views/api-docs-view/index.tsx | 12 +++++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx b/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx index ac4e3dec9e..5a5c3632eb 100644 --- a/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx +++ b/src/pages/hcp/api-docs/vault-secrets/[[...page]].tsx @@ -91,7 +91,7 @@ export const getStaticProps: GetStaticProps< return { notFound: true } } // Return static props - return await getApiDocsStaticProps({ + const staticPropsResult = await getApiDocsStaticProps({ productSlug: PRODUCT_SLUG, baseUrl: BASE_URL, pathParts: params.page, @@ -106,6 +106,16 @@ export const getStaticProps: GetStaticProps< }) }, }) + /** + * Shims specific to HCP Vault Secrets + */ + if (!('props' in staticPropsResult)) { + return staticPropsResult + } + // We shim in the removal of the service name, as it's redundant. + staticPropsResult.props.serviceData.name = '' + // Return the static props results with shimmed modifications + return staticPropsResult } export default HcpVaultSecretsApiDocsView diff --git a/src/views/api-docs-view/api-docs-view.module.css b/src/views/api-docs-view/api-docs-view.module.css index f4206eebc1..508a92fa03 100644 --- a/src/views/api-docs-view/api-docs-view.module.css +++ b/src/views/api-docs-view/api-docs-view.module.css @@ -3,10 +3,16 @@ * SPDX-License-Identifier: MPL-2.0 */ +.serviceData { + margin-top: 32px; + display: flex; + flex-direction: column; +} + .serviceHeading { composes: hds-typography-display-400 from global; font-weight: var(--token-typography-font-weight-bold); - margin: 32px 0 16px 0; + margin-bottom: 16px; } .sidebarPrompt { diff --git a/src/views/api-docs-view/index.tsx b/src/views/api-docs-view/index.tsx index 4f4e2077c0..547499a229 100644 --- a/src/views/api-docs-view/index.tsx +++ b/src/views/api-docs-view/index.tsx @@ -36,12 +36,12 @@ function ApiDocsView({ /** * We always render the API docs name in a heading-styled element. * - * When `serviceData` is provided, we'll render the service name + * When `serviceData.name` is provided, we'll render the service name * in an `h1` element, as the `serviceName` is a more meaningful page title. * In such cases, our page heading needs to be a `p` element to avoid * having multiple `h1` elements on the page. */ - const pageHeadingTag = serviceData ? 'p' : 'h1' + const pageHeadingTag = serviceData && serviceData.name ? 'p' : 'h1' /** * We only show the version switcher if we have at least 2 options. @@ -73,8 +73,10 @@ function ApiDocsView({ } /> {serviceData ? ( - <> -

{serviceData.name}

+
+ {serviceData.name ? ( +

{serviceData.name}

+ ) : null} {serviceData.operations.map((operation: OperationObjectType) => { return ( ) })} - +
) : (

Select a service from the sidebar.

)} From 0c5e64d50307777edae999aed3ebde6638304c69 Mon Sep 17 00:00:00 2001 From: Zach Shilton <4624598+zchsh@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:16:14 -0400 Subject: [PATCH 3/4] docs: add comment on path truncation --- .../components/path-truncation-aside/index.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/views/api-docs-view/components/path-truncation-aside/index.tsx b/src/views/api-docs-view/components/path-truncation-aside/index.tsx index c5d56aa767..eb299fe06e 100644 --- a/src/views/api-docs-view/components/path-truncation-aside/index.tsx +++ b/src/views/api-docs-view/components/path-truncation-aside/index.tsx @@ -9,6 +9,10 @@ import CodeBlock from '@hashicorp/react-code-block' /** * Truncates HCP Vault Secrets API operation paths for clarity. * Intended to be used with a `` in each operation intro. + * + * This regex matches a standard prefix in HCP Vault Secrets API paths: + * /secrets//organizations/{location.organization_id}/projects/{location.project_id} + * where `` is a date-based version in the format YYYY-MM-DD. */ function truncateVaultSecretsOperationPath(path: string) { return path.replace( @@ -20,6 +24,10 @@ function truncateVaultSecretsOperationPath(path: string) { /** * Truncates HCP Packer API operation paths for clarity. * Intended to be used with a `` in each operation intro. + * + * This regex matches a standard prefix in HCP Packer API paths: + * /packer//organizations/{location.organization_id}/projects/{location.project_id} + * where `` is a date-based version in the format YYYY-MM-DD. */ function truncatePackerOperationPath(path: string) { return path.replace( From 955ae4b50dfc26cce1674dd55c71835b4bce6a3d Mon Sep 17 00:00:00 2001 From: Zach Shilton <4624598+zchsh@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:16:58 -0400 Subject: [PATCH 4/4] style: use cleaner serviceData.name check Co-authored-by: Kendall Strautman Swarthout <36613477+kendallstrautman@users.noreply.github.com> --- src/views/api-docs-view/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/api-docs-view/index.tsx b/src/views/api-docs-view/index.tsx index 547499a229..6f885ed6d4 100644 --- a/src/views/api-docs-view/index.tsx +++ b/src/views/api-docs-view/index.tsx @@ -41,7 +41,7 @@ function ApiDocsView({ * In such cases, our page heading needs to be a `p` element to avoid * having multiple `h1` elements on the page. */ - const pageHeadingTag = serviceData && serviceData.name ? 'p' : 'h1' + const pageHeadingTag = serviceData?.name ? 'p' : 'h1' /** * We only show the version switcher if we have at least 2 options.