Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RND-2311: enums for server url in openapi block #2452

Open
wants to merge 66 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
4d476a8
Select variables in server url
BrettJephson Aug 27, 2024
7e79e14
Update server url based on variable selection
BrettJephson Sep 3, 2024
e852206
Update server choice based on selection
BrettJephson Sep 12, 2024
cb454a3
Format
BrettJephson Sep 12, 2024
ca4518d
Changeset
BrettJephson Sep 12, 2024
2d15453
Revised client state with context
BrettJephson Sep 20, 2024
d919d2c
Add icons for editing url
BrettJephson Sep 20, 2024
adaf0de
Fix type
BrettJephson Sep 20, 2024
69414bd
Formatting
BrettJephson Sep 20, 2024
3b0f5d8
Add server url cache to update request code sample
BrettJephson Sep 24, 2024
087a783
Formatting
BrettJephson Sep 24, 2024
9573535
Update icon
BrettJephson Sep 24, 2024
e793a17
Select variables in server url
BrettJephson Aug 27, 2024
b87ec84
Update server url based on variable selection
BrettJephson Sep 3, 2024
4f59d18
Update server choice based on selection
BrettJephson Sep 12, 2024
c338bca
Format
BrettJephson Sep 12, 2024
7244a04
Changeset
BrettJephson Sep 12, 2024
d29a7a6
Revised client state with context
BrettJephson Sep 20, 2024
a6adfaa
Add icons for editing url
BrettJephson Sep 20, 2024
3d14790
Fix type
BrettJephson Sep 20, 2024
28c59d8
Formatting
BrettJephson Sep 20, 2024
96d5537
Add server url cache to update request code sample
BrettJephson Sep 24, 2024
768b555
Formatting
BrettJephson Sep 24, 2024
ea4f70e
Update icon
BrettJephson Sep 24, 2024
0b44528
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Sep 24, 2024
949f25c
Merge branch 'brett/RND-2311-openapi-enum' of github.com:GitbookIO/gi…
BrettJephson Sep 24, 2024
f6b75e7
Self review changes
BrettJephson Sep 24, 2024
4b9f206
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Sep 25, 2024
4026fc1
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Sep 25, 2024
8d1c349
Don't make server url editable if no update function or context
BrettJephson Sep 25, 2024
5b93377
Merge remote-tracking branch 'origin/main' into brett/RND-2311-openap…
BrettJephson Oct 1, 2024
ce890c6
Refactor - naming and comments
BrettJephson Oct 2, 2024
cb3c1f9
Formatting
BrettJephson Oct 2, 2024
abf7ec3
Remove unused imports
BrettJephson Oct 2, 2024
f98b7b2
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Oct 2, 2024
39d8886
Formatting
BrettJephson Oct 2, 2024
586e66d
Update comment
BrettJephson Oct 2, 2024
60a9b95
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Oct 3, 2024
c1193fd
Select variables in server url
BrettJephson Aug 27, 2024
1ae1715
Update server url based on variable selection
BrettJephson Sep 3, 2024
77d64d0
Update server choice based on selection
BrettJephson Sep 12, 2024
9437aa2
Format
BrettJephson Sep 12, 2024
f6823e9
Changeset
BrettJephson Sep 12, 2024
ac492e0
Revised client state with context
BrettJephson Sep 20, 2024
f65e3f5
Add icons for editing url
BrettJephson Sep 20, 2024
f67b143
Fix type
BrettJephson Sep 20, 2024
9b78692
Formatting
BrettJephson Sep 20, 2024
184d616
Add server url cache to update request code sample
BrettJephson Sep 24, 2024
74392ec
Formatting
BrettJephson Sep 24, 2024
7b02f72
Update icon
BrettJephson Sep 24, 2024
dce39c4
Update server url based on variable selection
BrettJephson Sep 3, 2024
e866080
Update server choice based on selection
BrettJephson Sep 12, 2024
662df6f
Format
BrettJephson Sep 12, 2024
65d7729
Revised client state with context
BrettJephson Sep 20, 2024
2d4ddc9
Formatting
BrettJephson Sep 20, 2024
c7ca921
Self review changes
BrettJephson Sep 24, 2024
9675290
Don't make server url editable if no update function or context
BrettJephson Sep 25, 2024
95e8772
Refactor - naming and comments
BrettJephson Oct 2, 2024
0ccc503
Formatting
BrettJephson Oct 2, 2024
3ee149d
Remove unused imports
BrettJephson Oct 2, 2024
152aad2
Update comment
BrettJephson Oct 2, 2024
d19e350
Merge branch 'brett/RND-2311-openapi-enum' of github.com:GitbookIO/gi…
BrettJephson Oct 9, 2024
5beb2db
Tidy
BrettJephson Oct 9, 2024
3d9aefa
Merge remote-tracking branch 'origin/main' into brett/RND-2311-openap…
BrettJephson Oct 14, 2024
846de0e
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Oct 18, 2024
d9ee1a7
Merge branch 'main' into brett/RND-2311-openapi-enum
BrettJephson Oct 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/long-shrimps-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@gitbook/react-openapi': minor
'gitbook': minor
---

Allow selection of server url
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Metadata, Viewport } from 'next';
import { notFound, redirect } from 'next/navigation';
import React from 'react';

import { serverUrlCache } from '@/components/DocumentView/OpenAPI/ServerUrlCache';
import { PageAside } from '@/components/PageAside';
import { PageBody, PageCover } from '@/components/PageBody';
import { PageHrefContext, absoluteHref, pageHref } from '@/lib/links';
Expand All @@ -26,6 +27,8 @@ export default async function Page(props: {
}) {
const { params, searchParams } = props;

serverUrlCache.parse(searchParams);

const {
content: contentPointer,
contentTarget,
Expand Down
41 changes: 26 additions & 15 deletions packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { LoadingPane } from '@/components/primitives';
import { fetchOpenAPIBlock } from '@/lib/openapi';
import { tcls } from '@/lib/tailwind';

import OpenAPIClientStateContainer from './OpenAPIClientStateContainer';
import { serverUrlCache } from './ServerUrlCache';
import { BlockProps } from '../Block';
import { PlainCodeBlock } from '../CodeBlock';

Expand All @@ -17,7 +19,7 @@ import './scalar.css';
* Render an OpenAPI block.
*/
export async function OpenAPI(props: BlockProps<DocumentBlockSwagger>) {
const { block, style } = props;
const { style } = props;
return (
<div className={tcls('w-full', 'flex', 'flex-row', style, 'max-w-full')}>
<React.Suspense fallback={<OpenAPIFallback />}>
Expand Down Expand Up @@ -45,21 +47,30 @@ async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) {
return null;
}

// To update the code sample we need to re-render the server component
// so reading the cached value from search params
const serverUrl = serverUrlCache.get('serverUrl');

return (
<OpenAPIOperation
data={data}
context={{
icons: {
chevronDown: <Icon icon="chevron-down" />,
chevronRight: <Icon icon="chevron-right" />,
},
CodeBlock: PlainCodeBlock,
defaultInteractiveOpened: context.mode === 'print',
id: block.meta?.id,
blockKey: block.key,
}}
className="openapi-block"
/>
<OpenAPIClientStateContainer block={block} servers={data.servers}>
<OpenAPIOperation
data={data}
context={{
icons: {
chevronDown: <Icon icon="chevron-down" />,
chevronRight: <Icon icon="chevron-right" />,
edit: <Icon icon="edit" />,
editDone: <Icon icon="check" />,
},
CodeBlock: PlainCodeBlock,
defaultInteractiveOpened: context.mode === 'print',
id: block.meta?.id,
blockKey: block.key,
serverUrl,
}}
className="openapi-block"
/>
</OpenAPIClientStateContainer>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client';

import { DocumentBlock } from '@gitbook/api';
import { OpenAPIClientState } from '@gitbook/react-openapi/client';
import { useRouter, useSearchParams } from 'next/navigation';
import { OpenAPIV3 } from 'openapi-types';
import * as React from 'react';

/**
* Client component that wraps `OpenAPIClientState` so we can
* use some hooks (e.g. useRouter) in the `onUpdate` callback.
*/
export default function OpenAPIClientStateContainer(props: {
children: React.ReactNode;
block: DocumentBlock;
servers: OpenAPIV3.ServerObject[];
}) {
const { block, children, servers } = props;
const [isPending, startTransition] = React.useTransition();
const router = useRouter();
const searchParams = useSearchParams();

return (
<OpenAPIClientState
isPending={isPending}
servers={servers}
params={
searchParams.get('block') === block.key
? Object.fromEntries(searchParams.entries())
: undefined
}
onUpdate={async (params) => {
startTransition(() => {
const queryParams = new URLSearchParams(params ?? '');
router.replace(`?${queryParams}`, { scroll: false });
});
}}
>
{children}
</OpenAPIClientState>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createSearchParamsCache, parseAsString } from 'nuqs/server';

export const serverUrlCache = createSearchParamsCache({
serverUrl: parseAsString,
});
23 changes: 22 additions & 1 deletion packages/gitbook/src/components/DocumentView/OpenAPI/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
/** URL */

.openapi-url {
@apply font-mono text-sm text-dark/8 dark:text-light/8;
@apply flex items-center font-mono text-sm text-dark/8 dark:text-light/8;
}

.openapi-url-var {
Expand Down Expand Up @@ -364,3 +364,24 @@
.openapi-markdown > *:last-child {
@apply mb-0;
}

.openapi-select-button,
.openapi-edit-button {
@apply p-0.5 inline-flex text-dark/6 dark:text-light/6 hover:opacity-8;
}

.openapi-edit-button {
@apply p-0.5 ml-4 size-4;
}

.openapi-edit-button > * {
@apply size-full;
}

.openapi-select-button {
@apply leading-[1cap] disabled:opacity-5;
}

.openapi-pending {
@apply opacity-5;
}
1 change: 0 additions & 1 deletion packages/gitbook/src/components/PageBody/PageBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ export function PageBody(props: {
const language = getSpaceLanguage(customization);
const updatedAt = page.updatedAt ?? page.createdAt;
const shouldHighlightCode = createHighlightingContext();

return (
<>
<main
Expand Down
3 changes: 2 additions & 1 deletion packages/react-openapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"types": "./dist/index.d.ts",
"development": "./src/index.ts",
"default": "./dist/index.js"
}
},
"./client": "./src/client.ts"
BrettJephson marked this conversation as resolved.
Show resolved Hide resolved
},
"version": "0.6.0",
"dependencies": {
Expand Down
92 changes: 92 additions & 0 deletions packages/react-openapi/src/OpenAPIClientStateContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
'use client';

import * as React from 'react';
import { getServersURL } from './utils';
import { OpenAPIV3 } from 'openapi-types';

type OpenAPIClientStateContextProps = {
/**
* Whether client state updates are in a pending state,
* i.e. is a transition in progress.
*/
isPending?: boolean;
/**
* The server url
*/
serverUrl?: string;
/**
* The current state
*/
state?: Record<string, string> | null;
/**
* Callback for when the client state is updated
*/
onUpdate: (params: Record<string, string> | null) => void;
};

const OpenAPIClientStateContext = React.createContext<OpenAPIClientStateContextProps | null>(null);

export function useOpenAPIClientState() {
return React.useContext(OpenAPIClientStateContext);
}

/**
* Control client state for an OpenAPI operation
*/
export function OpenAPIClientState(props: {
children: React.ReactNode;
servers: OpenAPIV3.ServerObject[];
isPending?: boolean;
params?: Record<string, string>;
onUpdate: OpenAPIClientStateContextProps['onUpdate'];
}) {
const { children, servers, isPending, params, onUpdate } = props;

const clientState = React.useMemo(() => {
if (!params) {
return null;
}
return parseClientStateModifiers(servers, params);
}, [servers, params]);
const serverUrl = getServersURL(servers, clientState ?? undefined);

return (
<OpenAPIClientStateContext.Provider
value={{
isPending,
state: clientState,
serverUrl,
onUpdate,
}}
>
{children}
</OpenAPIClientStateContext.Provider>
);
}

function parseClientStateModifiers(
servers: OpenAPIV3.ServerObject[],
params: Record<string, string>,
) {
if (!servers) {
return null;
}
const serverQueryParam = params['server'];
const serverIndex =
serverQueryParam && !isNaN(Number(serverQueryParam))
? Math.max(0, Math.min(Number(serverQueryParam), servers.length - 1))
: 0;
const server = servers[serverIndex];
return server
? Object.keys(server.variables ?? {}).reduce<Record<string, string>>(
(result, key) => {
const selection = params[key];
if (!isNaN(Number(selection))) {
result[key] = selection;
}
return result;
},
{ server: `${serverIndex}`, edit: params['edit'] },
)
: null;
}
10 changes: 3 additions & 7 deletions packages/react-openapi/src/OpenAPICodeSample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import { CodeSampleInput, codeSampleGenerators } from './code-samples';
import { OpenAPIOperationData, toJSON } from './fetchOpenAPIOperation';
import { generateMediaTypeExample, generateSchemaExample } from './generateSchemaExample';
import { InteractiveSection } from './InteractiveSection';
import { getServersURL } from './OpenAPIServerURL';
import { ScalarApiButton } from './ScalarApiButton';
import { OpenAPIContextProps } from './types';
import { noReference } from './utils';
import { getServersURL, noReference } from './utils';

/**
* Display code samples to execute the operation.
Expand Down Expand Up @@ -49,14 +48,11 @@ export function OpenAPICodeSample(props: {
}
});

const serverUrl = context.serverUrl ?? getServersURL(data.servers);
const requestBody = noReference(data.operation.requestBody);
const requestBodyContent = requestBody ? Object.entries(requestBody.content)[0] : undefined;

const input: CodeSampleInput = {
url:
getServersURL(data.servers) +
data.path +
(searchParams.size ? `?${searchParams.toString()}` : ''),
url: serverUrl + data.path + (searchParams.size ? `?${searchParams.toString()}` : ''),
method: data.method,
body: requestBodyContent
? generateMediaTypeExample(requestBodyContent[1], { onlyRequired: true })
Expand Down
9 changes: 6 additions & 3 deletions packages/react-openapi/src/OpenAPIOperation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function OpenAPIOperation(props: {
{operation.description ? (
<Markdown className="openapi-description" source={operation.description} />
) : null}
<div className="openapi-target">
<div className="openapi-target flex items-center">
<span
className={classNames(
'openapi-method',
Expand All @@ -47,8 +47,11 @@ export function OpenAPIOperation(props: {
{method.toUpperCase()}
</span>
<span className="openapi-url">
<OpenAPIServerURL servers={servers} />
{path}
<OpenAPIServerURL
servers={servers}
context={clientContext}
path={path}
/>
</span>
</div>
</div>
Expand Down
Loading
Loading