Skip to content

Commit 0278a14

Browse files
authored
Upgrade Scalar client & fix opening endpoint (#2933)
1 parent e5366d3 commit 0278a14

File tree

6 files changed

+84
-92
lines changed

6 files changed

+84
-92
lines changed

.changeset/forty-rabbits-brush.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@gitbook/openapi-parser': patch
3+
'@gitbook/react-openapi': patch
4+
---
5+
6+
Upgrade Scalar dependencies

bun.lock

Lines changed: 41 additions & 59 deletions
Large diffs are not rendered by default.

packages/openapi-parser/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
"version": "2.0.2",
1313
"sideEffects": false,
1414
"dependencies": {
15-
"@scalar/openapi-parser": "^0.10.4",
16-
"@scalar/openapi-types": "^0.1.6"
15+
"@scalar/openapi-parser": "^0.10.9",
16+
"@scalar/openapi-types": "^0.1.9"
1717
},
1818
"devDependencies": {
1919
"@tsconfig/strictest": "^2.0.5",

packages/react-openapi/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
"sideEffects": false,
1313
"dependencies": {
1414
"@gitbook/openapi-parser": "workspace:*",
15-
"@scalar/api-client-react": "1.0.87",
16-
"@scalar/oas-utils": "^0.2.101",
15+
"@scalar/api-client-react": "^1.1.36",
16+
"@scalar/oas-utils": "^0.2.110",
1717
"clsx": "^2.1.1",
1818
"flatted": "^3.2.9",
1919
"json-xml-parse": "^1.3.0",

packages/react-openapi/src/OpenAPIPath.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { OpenAPIV3_1 } from '@gitbook/openapi-parser';
12
import type React from 'react';
23
import { ScalarApiButton } from './ScalarApiButton';
34
import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
@@ -12,20 +13,25 @@ export function OpenAPIPath(props: {
1213
const { data, context } = props;
1314
const { method, path } = data;
1415
const { specUrl } = context;
16+
const hideTryItPanel = data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'];
1517

1618
return (
1719
<div className="openapi-path">
1820
<div className={`openapi-method openapi-method-${method}`}>{method}</div>
1921
<div className="openapi-path-title" data-deprecated={data.operation.deprecated}>
2022
<p>{formatPath(path)}</p>
2123
</div>
22-
{data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'] ? null : (
24+
{!hideTryItPanel && validateHttpMethod(method) && (
2325
<ScalarApiButton method={method} path={path} specUrl={specUrl} />
2426
)}
2527
</div>
2628
);
2729
}
2830

31+
function validateHttpMethod(method: string): method is OpenAPIV3_1.HttpMethods {
32+
return ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'].includes(method);
33+
}
34+
2935
// Format the path to highlight placeholders
3036
function formatPath(path: string) {
3137
// Matches placeholders like {id}, {userId}, etc.

packages/react-openapi/src/ScalarApiButton.tsx

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,21 @@
11
'use client';
22

33
import { ApiClientModalProvider, useApiClientModal } from '@scalar/api-client-react';
4-
import { useEffect, useImperativeHandle, useRef, useState } from 'react';
4+
import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
55
import { createPortal } from 'react-dom';
66

7-
import { useEventCallback } from 'usehooks-ts';
7+
import type { OpenAPIV3_1 } from '@gitbook/openapi-parser';
88
import { useOpenAPIOperationContext } from './OpenAPIOperationContext';
99

1010
/**
1111
* Button which launches the Scalar API Client
1212
*/
13-
export function ScalarApiButton({
14-
method,
15-
path,
16-
specUrl,
17-
}: {
18-
method: string;
13+
export function ScalarApiButton(props: {
14+
method: OpenAPIV3_1.HttpMethods;
1915
path: string;
2016
specUrl: string;
2117
}) {
18+
const { method, path, specUrl } = props;
2219
const [isOpen, setIsOpen] = useState(false);
2320
const controllerRef = useRef<ScalarModalControllerRef>(null);
2421
return (
@@ -55,21 +52,18 @@ export function ScalarApiButton({
5552
}
5653

5754
function ScalarModal(props: {
58-
method: string;
55+
method: OpenAPIV3_1.HttpMethods;
5956
path: string;
6057
specUrl: string;
6158
controllerRef: React.Ref<ScalarModalControllerRef>;
6259
}) {
60+
const { method, path, specUrl, controllerRef } = props;
6361
return (
6462
<ApiClientModalProvider
65-
configuration={{ spec: { url: props.specUrl } }}
66-
initialRequest={{ path: props.path, method: props.method }}
63+
configuration={{ spec: { url: specUrl } }}
64+
initialRequest={{ method, path }}
6765
>
68-
<ScalarModalController
69-
method={props.method}
70-
path={props.path}
71-
controllerRef={props.controllerRef}
72-
/>
66+
<ScalarModalController method={method} path={path} controllerRef={controllerRef} />
7367
</ApiClientModalProvider>
7468
);
7569
}
@@ -79,28 +73,32 @@ type ScalarModalControllerRef = {
7973
};
8074

8175
function ScalarModalController(props: {
82-
method: string;
76+
method: OpenAPIV3_1.HttpMethods;
8377
path: string;
8478
controllerRef: React.Ref<ScalarModalControllerRef>;
8579
}) {
80+
const { method, path, controllerRef } = props;
8681
const client = useApiClientModal();
87-
const openClient = client?.open;
82+
const openScalarClient = client?.open;
83+
const { onOpenClient: trackClientOpening } = useOpenAPIOperationContext();
84+
const openClient = useMemo(() => {
85+
if (openScalarClient) {
86+
return () => {
87+
openScalarClient({ method, path, _source: 'gitbook' });
88+
trackClientOpening({ method, path });
89+
};
90+
}
91+
return null;
92+
}, [openScalarClient, method, path, trackClientOpening]);
8893
useImperativeHandle(
89-
props.controllerRef,
94+
controllerRef,
9095
() => ({ openClient: openClient ? () => openClient() : undefined }),
9196
[openClient]
9297
);
9398

94-
// Open the client when the component is mounted.
95-
const { onOpenClient } = useOpenAPIOperationContext();
96-
const trackOpening = useEventCallback(() => {
97-
onOpenClient({ method: props.method, path: props.path });
98-
});
99+
// Open at mount
99100
useEffect(() => {
100-
if (openClient) {
101-
openClient();
102-
trackOpening();
103-
}
101+
openClient?.();
104102
}, [openClient]);
105103
return null;
106104
}

0 commit comments

Comments
 (0)