Skip to content

Commit 020cd8d

Browse files
committed
chore: minor fixes and linking
1 parent 9babcef commit 020cd8d

File tree

6 files changed

+149
-37
lines changed

6 files changed

+149
-37
lines changed

components/ApiReference/ApiReferenceContext.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { createContext, useContext, ReactNode } from "react";
22
import { OpenAPIV3 } from "@scalar/openapi-types";
33
import { StainlessConfig } from "../../lib/openApiSpec";
4+
import { buildSchemaReferences } from "./helpers";
5+
import { useRouter } from "next/router";
46

57
interface ApiReferenceContextType {
68
openApiSpec: OpenAPIV3.Document;
79
stainlessConfig: StainlessConfig;
810
baseUrl: string;
11+
schemaReferences: Record<string, string>;
912
}
1013

1114
const ApiReferenceContext = createContext<ApiReferenceContextType | undefined>(
@@ -23,11 +26,20 @@ export function ApiReferenceProvider({
2326
openApiSpec,
2427
stainlessConfig,
2528
}: ApiReferenceProviderProps) {
29+
const router = useRouter();
30+
const basePath = router.pathname.split("/")[1];
31+
2632
const baseUrl = stainlessConfig.environments.production;
33+
const schemaReferences = buildSchemaReferences(
34+
openApiSpec,
35+
stainlessConfig,
36+
Object.keys(stainlessConfig.resources),
37+
`/${basePath}`,
38+
);
2739

2840
return (
2941
<ApiReferenceContext.Provider
30-
value={{ openApiSpec, stainlessConfig, baseUrl }}
42+
value={{ openApiSpec, stainlessConfig, baseUrl, schemaReferences }}
3143
>
3244
{children}
3345
</ApiReferenceContext.Provider>

components/ApiReference/ApiReferenceMethod/ApiReferenceMethod.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import OperationParameters from "../OperationParameters/OperationParameters";
1111
import { PropertyRow } from "../SchemaProperties/PropertyRow";
1212
import MultiLangExample from "../MultiLangExample";
1313
import { augmentSnippetsWithCurlRequest } from "../helpers";
14+
import Link from "next/link";
1415

1516
type Props = {
1617
methodName: string;
@@ -19,7 +20,7 @@ type Props = {
1920
};
2021

2122
function ApiReferenceMethod({ methodName, methodType, endpoint }: Props) {
22-
const { openApiSpec, baseUrl } = useApiReference();
23+
const { openApiSpec, baseUrl, schemaReferences } = useApiReference();
2324
const [isResponseExpanded, setIsResponseExpanded] = useState(false);
2425
const method = openApiSpec.paths?.[endpoint]?.[methodType];
2526

@@ -52,7 +53,7 @@ function ApiReferenceMethod({ methodName, methodType, endpoint }: Props) {
5253

5354
<Endpoint
5455
method={methodType.toUpperCase()}
55-
path={`${baseUrl}${endpoint}`}
56+
path={`${endpoint}`}
5657
name={methodName}
5758
/>
5859

@@ -83,7 +84,11 @@ function ApiReferenceMethod({ methodName, methodType, endpoint }: Props) {
8384
<PropertyRow.Wrapper>
8485
<PropertyRow.Container>
8586
<PropertyRow.Header>
86-
<PropertyRow.Type>{responseSchema.title}</PropertyRow.Type>
87+
<PropertyRow.Type
88+
href={schemaReferences[responseSchema.title ?? ""]}
89+
>
90+
{responseSchema.title}
91+
</PropertyRow.Type>
8792
</PropertyRow.Header>
8893
<PropertyRow.Description>
8994
<Markdown>{responseSchema.description ?? ""}</Markdown>

components/ApiReference/ApiReferenceSection/ApiReferenceSection.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ function ApiReferenceSection({ resourceName, resource, path }: Props) {
7676
);
7777
})}
7878

79+
{Object.entries(resource.subresources ?? {}).map(
80+
([subresourceName, subresource]) => {
81+
return (
82+
<ApiReferenceSection
83+
key={subresourceName}
84+
resourceName={subresourceName}
85+
resource={subresource}
86+
path={`${basePath}/${subresourceName}`}
87+
/>
88+
);
89+
},
90+
)}
91+
7992
{Object.entries(models).map(([modelName, modelReference]) => {
8093
const schema: OpenAPIV3.SchemaObject | undefined = JSONPointer.get(
8194
openApiSpec,
@@ -113,19 +126,6 @@ function ApiReferenceSection({ resourceName, resource, path }: Props) {
113126
</div>
114127
);
115128
})}
116-
117-
{Object.entries(resource.subresources ?? {}).map(
118-
([subresourceName, subresource]) => {
119-
return (
120-
<ApiReferenceSection
121-
key={subresourceName}
122-
resourceName={subresourceName}
123-
resource={subresource}
124-
path={`${basePath}/${subresourceName}`}
125-
/>
126-
);
127-
},
128-
)}
129129
</>
130130
);
131131
}

components/ApiReference/SchemaProperties/PropertyRow.tsx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import classNames from "classnames";
2+
import Link from "next/link";
23
import { IoChevronDown } from "react-icons/io5";
34

45
const Header = ({ children }) => (
@@ -29,11 +30,30 @@ const Types = ({ children }) => (
2930
</div>
3031
);
3132

32-
const Type = ({ children }) => (
33-
<span className="font-mono text-xs px-1 bg-gray-50 dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-md">
34-
{children}
35-
</span>
36-
);
33+
const Type = ({
34+
children,
35+
href,
36+
}: {
37+
children: React.ReactNode;
38+
href?: string;
39+
}) => {
40+
if (href) {
41+
return (
42+
<Link
43+
href={href}
44+
className="font-mono text-xs px-1 bg-gray-50 dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-md !no-underline"
45+
>
46+
{children}
47+
</Link>
48+
);
49+
}
50+
51+
return (
52+
<span className="font-mono text-xs px-1 bg-gray-50 dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-md">
53+
{children}
54+
</span>
55+
);
56+
};
3757

3858
const Description = ({ children }) => (
3959
<div className="text-sm text-gray-500 dark:text-gray-300 schema-property-description">

components/ApiReference/SchemaProperties/SchemaProperty.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
maybeFlattenUnionSchema,
1010
resolveChildProperties,
1111
} from "./helpers";
12+
import { useApiReference } from "../ApiReferenceContext";
1213

1314
type Props = {
1415
name?: string;
@@ -18,6 +19,7 @@ type Props = {
1819
const MAX_TYPES_TO_DISPLAY = 2;
1920

2021
const SchemaProperty = ({ name, schema }: Props) => {
22+
const { schemaReferences } = useApiReference();
2123
const [isPossibleTypesOpen, setIsPossibleTypesOpen] = useState(false);
2224
const [isChildPropertiesOpen, setIsChildPropertiesOpen] = useState(false);
2325
// If the schema is an array, then we want to show the possible types that the array can contain.
@@ -35,7 +37,9 @@ const SchemaProperty = ({ name, schema }: Props) => {
3537
{name && <PropertyRow.Name>{name}</PropertyRow.Name>}
3638
<PropertyRow.Types>
3739
{typesForDisplay.slice(0, MAX_TYPES_TO_DISPLAY).map((type) => (
38-
<PropertyRow.Type key={type}>{type}</PropertyRow.Type>
40+
<PropertyRow.Type key={type} href={schemaReferences[type]}>
41+
{type}
42+
</PropertyRow.Type>
3943
))}
4044
{hasAdditionalTypes && (
4145
<span className="text-xs text-gray-500 dark:text-gray-300">

components/ApiReference/helpers.ts

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,76 @@ function resolveEndpointFromMethod(
1515
return [methodType, endpoint];
1616
}
1717

18+
function buildSchemaReferencesForResource(
19+
resource: StainlessResource,
20+
openApiSpec: OpenAPIV3.Document,
21+
basePath: string,
22+
) {
23+
const schemaReferences: Record<string, string> = {};
24+
25+
if (resource.models) {
26+
Object.entries(resource.models).forEach(([modelName, modelRef]) => {
27+
const schema: OpenAPIV3.SchemaObject | undefined = JSONPointer.get(
28+
openApiSpec,
29+
modelRef.replace("#", ""),
30+
);
31+
32+
const title = schema?.title ?? modelName;
33+
34+
if (schema) {
35+
schemaReferences[title] = `${basePath}/schemas/${modelName}`;
36+
// This is a hack to make lists work without doing anything to the inner type behavior
37+
schemaReferences[`${title}[]`] = `${basePath}/schemas/${modelName}`;
38+
}
39+
});
40+
}
41+
42+
if (resource.subresources) {
43+
Object.entries(resource.subresources).forEach(
44+
([subresourceName, subresource]) => {
45+
Object.assign(
46+
schemaReferences,
47+
buildSchemaReferencesForResource(
48+
subresource,
49+
openApiSpec,
50+
`${basePath}/${subresourceName}`,
51+
),
52+
);
53+
},
54+
);
55+
}
56+
57+
return schemaReferences;
58+
}
59+
60+
/**
61+
* Given a spec and config, builds a complete list of all of the schemas referenced
62+
* as a map for easy lookup from SchemaName -> path. We use this to then link to schemas
63+
*/
64+
function buildSchemaReferences(
65+
openApiSpec: OpenAPIV3.Document,
66+
stainlessSpec: StainlessConfig,
67+
resourceOrder: string[],
68+
basePath: string,
69+
) {
70+
const schemaReferences: Record<string, string> = {};
71+
72+
resourceOrder.forEach((resourceName) => {
73+
const resource = stainlessSpec.resources[resourceName];
74+
75+
Object.assign(
76+
schemaReferences,
77+
buildSchemaReferencesForResource(
78+
resource,
79+
openApiSpec,
80+
`${basePath}/${resourceName}`,
81+
),
82+
);
83+
});
84+
85+
return schemaReferences;
86+
}
87+
1888
function getSidebarContent(
1989
openApiSpec: OpenAPIV3.Document,
2090
stainlessSpec: StainlessConfig,
@@ -60,6 +130,20 @@ function buildSidebarPages(
60130
);
61131
}
62132

133+
if (resource.subresources) {
134+
pages.push(
135+
...Object.entries(resource.subresources).map(
136+
([subresourceName, subresource]) => {
137+
return {
138+
title: subresource.name || subresourceName,
139+
slug: `/${subresourceName}`,
140+
pages: buildSidebarPages(subresource, openApiSpec),
141+
};
142+
},
143+
),
144+
);
145+
}
146+
63147
if (resource.models) {
64148
pages.push({
65149
title: "Object definitions",
@@ -78,20 +162,6 @@ function buildSidebarPages(
78162
});
79163
}
80164

81-
if (resource.subresources) {
82-
pages.push(
83-
...Object.entries(resource.subresources).map(
84-
([subresourceName, subresource]) => {
85-
return {
86-
title: subresource.name || subresourceName,
87-
slug: `/${subresourceName}`,
88-
pages: buildSidebarPages(subresource, openApiSpec),
89-
};
90-
},
91-
),
92-
);
93-
}
94-
95165
return pages;
96166
}
97167

@@ -127,4 +197,5 @@ export {
127197
resolveEndpointFromMethod,
128198
buildSidebarPages,
129199
augmentSnippetsWithCurlRequest,
200+
buildSchemaReferences,
130201
};

0 commit comments

Comments
 (0)