@stainless-api/docs 0.1.0-beta.9 → 0.1.0-beta.91
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 +757 -0
- package/eslint-suppressions.json +32 -0
- package/locals.d.ts +17 -0
- package/package.json +49 -40
- package/playground-virtual-modules.d.ts +96 -0
- package/plugin/assets/languages/cli.svg +14 -0
- package/plugin/assets/languages/csharp.svg +1 -0
- package/plugin/buildAlgoliaIndex.ts +38 -11
- package/plugin/components/MethodDescription.tsx +54 -0
- package/plugin/components/RequestBuilder/ParamEditor.tsx +55 -0
- package/plugin/components/RequestBuilder/SnippetStainlessIsland.tsx +107 -0
- package/plugin/components/RequestBuilder/index.tsx +31 -0
- package/plugin/components/RequestBuilder/props.ts +9 -0
- package/plugin/components/RequestBuilder/spec-helpers.ts +50 -0
- package/plugin/components/RequestBuilder/styles.css +67 -0
- package/plugin/components/SDKSelect.astro +20 -104
- package/plugin/components/SnippetCode.tsx +111 -66
- package/plugin/components/StainlessIslands.tsx +126 -0
- package/plugin/components/search/SearchAlgolia.astro +45 -28
- package/plugin/components/search/SearchIsland.tsx +47 -29
- package/plugin/generateAPIReferenceLink.ts +2 -2
- package/plugin/globalJs/ai-dropdown-options.ts +243 -0
- package/plugin/globalJs/code-snippets.ts +15 -8
- package/plugin/globalJs/copy.ts +94 -17
- package/plugin/globalJs/create-playground.shim.ts +3 -0
- package/plugin/globalJs/method-descriptions.ts +33 -0
- package/plugin/globalJs/navigation.ts +10 -29
- package/plugin/globalJs/playground-data.shim.ts +1 -0
- package/plugin/globalJs/playground-data.ts +14 -0
- package/plugin/helpers/generateDocsRoutes.ts +27 -0
- package/plugin/helpers/getDocsLanguages.ts +9 -0
- package/plugin/index.ts +292 -116
- package/plugin/languages.ts +7 -2
- package/plugin/loadPluginConfig.ts +155 -79
- package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +1 -1
- package/plugin/react/Routing.tsx +204 -132
- package/plugin/referencePlaceholderUtils.ts +18 -15
- package/plugin/replaceSidebarPlaceholderMiddleware.ts +38 -34
- package/plugin/routes/Docs.astro +65 -117
- package/plugin/routes/DocsStatic.astro +7 -4
- package/plugin/routes/Overview.astro +20 -24
- package/plugin/routes/markdown.ts +12 -11
- package/plugin/{cms → sidebar-utils}/sidebar-builder.ts +30 -54
- package/plugin/specs/fetchSpecSSR.ts +21 -0
- package/plugin/specs/generateSpec.ts +50 -0
- package/plugin/specs/index.ts +238 -0
- package/plugin/{cms → specs}/worker.ts +82 -5
- package/plugin/vendor/preview.worker.docs.js +22142 -18005
- package/plugin/vendor/templates/go.md +1 -1
- package/plugin/vendor/templates/python.md +1 -1
- package/resolveSrcFile.ts +10 -0
- package/scripts/vendor_deps.ts +5 -5
- package/shared/getProsePages.ts +42 -0
- package/shared/getSharedLogger.ts +15 -0
- package/shared/terminalUtils.ts +3 -0
- package/shared/virtualModule.ts +54 -1
- package/src/content.config.ts +9 -0
- package/stl-docs/components/AIDropdown.tsx +63 -0
- package/stl-docs/components/AiChatIsland.tsx +14 -0
- package/stl-docs/components/{content-panel/ContentBreadcrumbs.tsx → ContentBreadcrumbs.tsx} +2 -2
- package/stl-docs/components/Head.astro +20 -0
- package/stl-docs/components/Header.astro +6 -8
- package/stl-docs/components/PageFrame.astro +18 -0
- package/stl-docs/components/PageTitle.astro +82 -0
- package/stl-docs/components/TableOfContents.astro +34 -0
- package/stl-docs/components/ThemeProvider.astro +36 -0
- package/stl-docs/components/ThemeSelect.astro +84 -139
- package/stl-docs/components/content-panel/ContentPanel.astro +16 -46
- package/stl-docs/components/headers/SplashMobileMenuToggle.astro +17 -1
- package/stl-docs/components/headers/StackedHeader.astro +29 -24
- package/stl-docs/components/icons/chat-gpt.tsx +2 -2
- package/stl-docs/components/icons/cursor.tsx +10 -0
- package/stl-docs/components/icons/gemini.tsx +19 -0
- package/stl-docs/components/icons/markdown.tsx +1 -1
- package/stl-docs/components/index.ts +1 -0
- package/stl-docs/components/mintlify-compat/Accordion.astro +7 -5
- package/stl-docs/components/mintlify-compat/AccordionGroup.astro +7 -3
- package/stl-docs/components/mintlify-compat/Columns.astro +40 -42
- package/stl-docs/components/mintlify-compat/Frame.astro +16 -18
- package/stl-docs/components/mintlify-compat/callouts/Callout.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Check.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Danger.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Info.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Note.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Tip.astro +1 -1
- package/stl-docs/components/mintlify-compat/callouts/Warning.astro +1 -1
- package/stl-docs/components/mintlify-compat/card.css +33 -35
- package/stl-docs/components/mintlify-compat/index.ts +2 -4
- package/stl-docs/components/nav-tabs/NavDropdown.astro +31 -70
- package/stl-docs/components/nav-tabs/NavTabs.astro +78 -80
- package/stl-docs/components/nav-tabs/SecondaryNavTabs.astro +15 -8
- package/stl-docs/components/nav-tabs/buildNavLinks.ts +3 -2
- package/stl-docs/components/pagination/HomeLink.astro +10 -0
- package/stl-docs/components/pagination/Pagination.astro +175 -0
- package/stl-docs/components/pagination/PaginationLinkEmphasized.astro +22 -0
- package/stl-docs/components/pagination/PaginationLinkQuiet.astro +13 -0
- package/stl-docs/components/pagination/util.ts +71 -0
- package/stl-docs/components/scripts.ts +1 -0
- package/stl-docs/components/sidebars/BaseSidebar.astro +9 -2
- package/stl-docs/components/sidebars/SidebarWithComponents.tsx +10 -0
- package/stl-docs/components/sidebars/convertAstroSidebarToStl.tsx +62 -0
- package/stl-docs/disableCalloutSyntax.ts +36 -0
- package/stl-docs/fonts.ts +186 -0
- package/stl-docs/index.ts +153 -50
- package/stl-docs/loadStlDocsConfig.ts +51 -7
- package/stl-docs/proseMarkdown/proseMarkdownIntegration.ts +61 -0
- package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +41 -0
- package/stl-docs/proseMarkdown/toMarkdown.ts +158 -0
- package/stl-docs/proseSearchIndexing.ts +606 -0
- package/stl-docs/tabsMiddleware.ts +13 -4
- package/styles/code.css +128 -136
- package/styles/links.css +11 -48
- package/styles/method-descriptions.css +36 -0
- package/styles/overrides.css +49 -57
- package/styles/page.css +100 -59
- package/styles/sdk_select.css +9 -7
- package/styles/search.css +57 -69
- package/styles/sidebar.css +26 -156
- package/styles/{variables.css → sl-variables.css} +3 -2
- package/styles/stldocs-variables.css +6 -0
- package/styles/toc.css +41 -34
- package/theme.css +11 -11
- package/tsconfig.json +2 -5
- package/virtual-module.d.ts +47 -7
- package/components/variables.css +0 -135
- package/plugin/cms/client.ts +0 -62
- package/plugin/cms/server.ts +0 -268
- package/plugin/globalJs/ai-dropdown.ts +0 -57
- package/stl-docs/components/APIReferenceAIDropdown.tsx +0 -58
- package/stl-docs/components/content-panel/ProseAIDropdown.tsx +0 -55
- package/stl-docs/components/mintlify-compat/Step.astro +0 -58
- package/stl-docs/components/mintlify-compat/Steps.astro +0 -17
- package/styles/fonts.css +0 -68
- /package/{plugin/assets → assets}/fonts/geist/OFL.txt +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-italic-latin.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-latin.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-italic-latin.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin-ext.woff2 +0 -0
- /package/{plugin/assets → assets}/fonts/geist/geist-mono-latin.woff2 +0 -0
package/plugin/routes/Docs.astro
CHANGED
|
@@ -1,87 +1,75 @@
|
|
|
1
1
|
---
|
|
2
|
-
import StarlightPage from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import "@stainless-api/docs-ui/src/styles/primitives.css";
|
|
7
|
-
import "@stainless-api/docs-ui/src/styles/main.css";
|
|
8
|
-
import "@stainless-api/docs-ui/src/styles/snippets.css";
|
|
9
|
-
// TODO: fix variables.css import
|
|
10
|
-
// import "./variables.css";
|
|
11
|
-
|
|
2
|
+
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
|
|
3
|
+
import { getReadmeContent, buildPageNavigation, RenderSpec, astroMarkdownRender } from '../react/Routing';
|
|
4
|
+
import { getResourceFromSpec } from '@stainless-api/docs-ui/utils';
|
|
5
|
+
import { parseStainlessPath } from '@stainless-api/docs-ui/routing';
|
|
12
6
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from
|
|
19
|
-
import {
|
|
20
|
-
import { BASE_PATH, CONTENT_PANEL_LAYOUT,MIDDLEWARE } from "virtual:stl-starlight-virtual-module";
|
|
7
|
+
CONTENT_PANEL_LAYOUT,
|
|
8
|
+
MIDDLEWARE,
|
|
9
|
+
EXPERIMENTAL_REQUEST_BUILDER,
|
|
10
|
+
} from 'virtual:stl-starlight-virtual-module';
|
|
11
|
+
import { generateDocsRoutes } from '../helpers/generateDocsRoutes';
|
|
12
|
+
import { StainlessIslands } from '../components/StainlessIslands';
|
|
13
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
21
14
|
|
|
15
|
+
const spec = await getSDKJSONInSSR();
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
const routes = generateDocsRoutes(spec);
|
|
17
|
+
export type Props = Awaited<ReturnType<typeof generateDocsRoutes>>[number]['props'] | Record<string, never>;
|
|
25
18
|
|
|
26
|
-
const
|
|
19
|
+
const props =
|
|
20
|
+
'language' in Astro.props
|
|
21
|
+
? // In prod, we pass the props down to this page
|
|
22
|
+
Astro.props
|
|
23
|
+
: // In the dev server, we skip the DocsStatic wrapper so we need to find the props ourselves
|
|
24
|
+
generateDocsRoutes(spec).find((r) => r.params.slug === Astro.params.slug)?.props;
|
|
25
|
+
if (!props) throw new Error(`Could not find a route for slug '${Astro.params.slug}'`);
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
// PageTitle override will skip rendering the default Starlight title
|
|
28
|
+
Astro.locals._stlStarlightPage = {
|
|
29
|
+
skipRenderingStarlightTitle: props.kind === 'readme' ? false : true,
|
|
30
|
+
};
|
|
31
31
|
|
|
32
|
-
const readmeContent = await getReadmeContent(spec,
|
|
33
|
-
const readme =
|
|
34
|
-
route.props.kind === "readme"
|
|
35
|
-
? await astroMarkdownRender(readmeContent ?? "")
|
|
36
|
-
: null;
|
|
32
|
+
const readmeContent = await getReadmeContent(spec, props.language);
|
|
33
|
+
const readme = props.kind === 'readme' ? await astroMarkdownRender(readmeContent ?? '') : null;
|
|
37
34
|
|
|
38
|
-
const resource =
|
|
39
|
-
? getResourceFromSpec(route.props.stainlessPath, spec)
|
|
40
|
-
: null;
|
|
35
|
+
const resource = props.stainlessPath ? getResourceFromSpec(props.stainlessPath, spec) : null;
|
|
41
36
|
|
|
42
37
|
const pageNav =
|
|
43
|
-
|
|
38
|
+
props.kind === 'resource' && resource
|
|
44
39
|
? buildPageNavigation(resource)
|
|
45
|
-
:
|
|
40
|
+
: props.kind === 'readme' && readme?.metadata
|
|
46
41
|
? readme?.metadata.headings
|
|
47
42
|
: [];
|
|
48
43
|
|
|
49
|
-
|
|
44
|
+
Astro.locals.language = props.language;
|
|
50
45
|
|
|
46
|
+
// Use first heading in README as page title
|
|
51
47
|
if (readme) {
|
|
52
48
|
const repo = spec.metadata?.[props.language]?.code_url;
|
|
53
|
-
readme.code = readme.code.replace(
|
|
54
|
-
|
|
55
|
-
`<a href="${repo}/$1"`);
|
|
56
|
-
props.title = readme.metadata.headings[0].text ?? "Overview";
|
|
49
|
+
readme.code = readme.code.replace(/<a href="(?!(?:https?:\/\/|\/\/))([^"]+)"/g, `<a href="${repo}/$1"`);
|
|
50
|
+
props.title = readme.metadata.headings[0]!.text ?? 'Overview';
|
|
57
51
|
}
|
|
58
52
|
|
|
53
|
+
// use summary for the page title of method pages
|
|
54
|
+
if (props.kind === 'http_method' && props.stainlessPath) {
|
|
55
|
+
const parsed = parseStainlessPath(props.stainlessPath);
|
|
56
|
+
const resource = getResourceFromSpec(props.stainlessPath, spec);
|
|
57
|
+
if (parsed?.method && resource?.methods[parsed.method]) {
|
|
58
|
+
const method = resource.methods[parsed.method];
|
|
59
|
+
props.title = method?.summary ?? method?.title ?? props.title;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
59
62
|
---
|
|
60
63
|
|
|
61
|
-
|
|
62
64
|
<StarlightPage
|
|
63
65
|
headings={pageNav}
|
|
64
66
|
frontmatter={{
|
|
65
|
-
title: props
|
|
66
|
-
head: [
|
|
67
|
-
{
|
|
68
|
-
tag: "link",
|
|
69
|
-
attrs: {
|
|
70
|
-
rel: "alternate",
|
|
71
|
-
type: "text/markdown",
|
|
72
|
-
href: `${BASE_PATH}/${Astro.params.slug}.md`
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
],
|
|
67
|
+
title: props.title,
|
|
76
68
|
pagefind: false,
|
|
77
|
-
tableOfContents:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
stainlessStarlight: {
|
|
82
|
-
basePath: BASE_PATH,
|
|
83
|
-
...props,
|
|
84
|
-
},
|
|
69
|
+
tableOfContents:
|
|
70
|
+
props.kind === 'readme' || (props.kind === 'resource' && props.language !== 'terraform')
|
|
71
|
+
? { maxHeadingLevel: 6 }
|
|
72
|
+
: false,
|
|
85
73
|
}}
|
|
86
74
|
>
|
|
87
75
|
{
|
|
@@ -96,76 +84,36 @@ if (readme) {
|
|
|
96
84
|
contentPanelLayout={CONTENT_PANEL_LAYOUT}
|
|
97
85
|
transformRequestSnippet={MIDDLEWARE.transformRequestSnippet}
|
|
98
86
|
/>
|
|
99
|
-
|
|
100
|
-
<style is:inline>
|
|
101
|
-
#stldocs-snippet-title {
|
|
102
|
-
display: flex;
|
|
103
|
-
gap: 5px;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.stldocs-snippet-code:not(.stldocs-snippet-response .stldocs-snippet-code) {
|
|
107
|
-
padding: 0 !important;
|
|
108
|
-
|
|
109
|
-
.astro-code {
|
|
110
|
-
padding: 1rem;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
[data-has-sidebar]:not([data-has-toc]) .sl-container {
|
|
116
|
-
max-width: 1428px;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
.content-panel:nth-of-type(1) {
|
|
120
|
-
display: none;
|
|
121
|
-
}
|
|
122
|
-
.content-panel:nth-of-type(2) .stl-page-nav-container {
|
|
123
|
-
display: none;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.content-panel:nth-of-type(2) .stldocs-root .stl-page-nav-container {
|
|
127
|
-
display: flex;
|
|
128
|
-
}
|
|
129
|
-
</style>
|
|
130
87
|
</div>
|
|
131
88
|
) : (
|
|
132
89
|
<>
|
|
133
90
|
<Fragment set:html={readme?.code} />
|
|
134
|
-
<style
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
display: inline-block;
|
|
141
|
-
vertical-align: text-bottom;
|
|
142
|
-
}
|
|
91
|
+
<style
|
|
92
|
+
is:inline
|
|
93
|
+
set:text={`
|
|
94
|
+
.sl-markdown-content h1:first-of-type {
|
|
95
|
+
display: none;
|
|
96
|
+
}
|
|
143
97
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
mask: var(--oct-icon) no-repeat;
|
|
149
|
-
-webkit-mask-size: 100% 100%;
|
|
150
|
-
mask-size: 100% 100%;
|
|
151
|
-
background-color: currentColor;
|
|
152
|
-
color: inherit;
|
|
153
|
-
display: inline-block;
|
|
154
|
-
vertical-align: text-bottom;
|
|
155
|
-
width: 1em;
|
|
156
|
-
height: 1em;
|
|
157
|
-
}
|
|
98
|
+
.sl-markdown-content img {
|
|
99
|
+
display: inline-block;
|
|
100
|
+
vertical-align: text-bottom;
|
|
101
|
+
}
|
|
158
102
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
103
|
+
.sl-markdown-content code {
|
|
104
|
+
white-space: pre-wrap;
|
|
105
|
+
}
|
|
106
|
+
`}
|
|
107
|
+
/>
|
|
163
108
|
</>
|
|
164
109
|
)
|
|
165
110
|
}
|
|
166
111
|
</StarlightPage>
|
|
167
112
|
|
|
113
|
+
{EXPERIMENTAL_REQUEST_BUILDER && <StainlessIslands client:load />}
|
|
114
|
+
|
|
168
115
|
<script src="../globalJs/navigation.ts"></script>
|
|
169
116
|
<script src="../globalJs/copy.ts"></script>
|
|
170
117
|
<script src="../globalJs/tooltip.ts"></script>
|
|
171
118
|
<script src="../globalJs/code-snippets.ts"></script>
|
|
119
|
+
<script src="../globalJs/method-descriptions.ts"></script>
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { GetStaticPaths } from 'astro';
|
|
3
3
|
import Docs from './Docs.astro';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { generateDocsRoutes } from '../helpers/generateDocsRoutes';
|
|
5
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
6
6
|
|
|
7
7
|
export const getStaticPaths = (async () => {
|
|
8
|
-
const spec = await
|
|
8
|
+
const spec = await getSDKJSONInSSR();
|
|
9
9
|
const routes = generateDocsRoutes(spec);
|
|
10
10
|
return routes;
|
|
11
11
|
}) satisfies GetStaticPaths;
|
|
12
|
+
|
|
13
|
+
export type Props = Awaited<ReturnType<typeof getStaticPaths>>[number]['props'];
|
|
14
|
+
const props = Astro.props;
|
|
12
15
|
---
|
|
13
16
|
|
|
14
|
-
<Docs />
|
|
17
|
+
<Docs {...props} />
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import type { DocsLanguage } from '@stainless-api/docs-ui/src/routing';
|
|
6
|
-
|
|
7
|
-
import '@stainless-api/docs-ui/src/styles/resets.css';
|
|
8
|
-
import '@stainless-api/docs-ui/src/styles/primitives.css';
|
|
9
|
-
import '@stainless-api/docs-ui/src/styles/main.css';
|
|
10
|
-
import '@stainless-api/docs-ui/src/styles/snippets.css';
|
|
11
|
-
// TODO: fix variables.css import
|
|
12
|
-
// import '../components/variables.css';
|
|
3
|
+
import { EXCLUDE_LANGUAGES } from 'virtual:stl-starlight-virtual-module';
|
|
4
|
+
import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
13
5
|
import { RenderLibraries, RenderSpecOverview, type SpecMetadata } from '../react/Routing';
|
|
6
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
14
7
|
|
|
15
|
-
const spec = await
|
|
8
|
+
const spec = await getSDKJSONInSSR();
|
|
16
9
|
|
|
17
10
|
const languages: DocsLanguage[] = spec.docs!.languages ?? ['http'];
|
|
18
|
-
const metadata = languages
|
|
11
|
+
const metadata: SpecMetadata = languages
|
|
19
12
|
.filter((language) => !['http', 'terraform'].includes(language) && spec.metadata[language])
|
|
20
13
|
.filter((language) => !EXCLUDE_LANGUAGES.includes(language))
|
|
21
|
-
.map((language) => [language, spec.metadata[language]])
|
|
14
|
+
.map<SpecMetadata[number]>((language) => [language, spec.metadata[language]!]);
|
|
15
|
+
|
|
16
|
+
// PageTitle override will skip rendering the default Starlight title
|
|
17
|
+
Astro.locals._stlStarlightPage = {
|
|
18
|
+
hasMarkdownRoute: false,
|
|
19
|
+
};
|
|
22
20
|
---
|
|
23
21
|
|
|
24
22
|
<StarlightPage
|
|
@@ -26,22 +24,20 @@ const metadata = languages
|
|
|
26
24
|
title: 'API Reference',
|
|
27
25
|
pagefind: false,
|
|
28
26
|
tableOfContents: false,
|
|
29
|
-
stainlessStarlight: {
|
|
30
|
-
basePath: BASE_PATH,
|
|
31
|
-
language: 'http',
|
|
32
|
-
},
|
|
33
27
|
}}
|
|
34
28
|
>
|
|
35
|
-
<
|
|
29
|
+
<div class="stl-overview">
|
|
30
|
+
<h3>Libraries</h3>
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
<div class="stldocs-root language-blocks stl-ui-not-prose not-content">
|
|
33
|
+
<RenderLibraries metadata={metadata} />
|
|
34
|
+
</div>
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
<h3>API Overview</h3>
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
<div class="stldocs-root api-overview stl-ui-not-prose">
|
|
39
|
+
<RenderSpecOverview spec={spec} language="http" />
|
|
40
|
+
</div>
|
|
45
41
|
</div>
|
|
46
42
|
</StarlightPage>
|
|
47
43
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { APIRoute, GetStaticPaths } from 'astro';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { getResourceFromSpec } from '@stainless-api/docs-ui/src/utils';
|
|
2
|
+
import { getReadmeContent } from '../react/Routing';
|
|
3
|
+
import { getResourceFromSpec } from '@stainless-api/docs-ui/utils';
|
|
5
4
|
|
|
6
|
-
import { renderMarkdown } from '@stainless-api/docs-ui/
|
|
5
|
+
import { renderMarkdown } from '@stainless-api/docs-ui/markdown';
|
|
7
6
|
|
|
8
|
-
import { parseStainlessPath, type DocsLanguage } from '@stainless-api/docs-ui/
|
|
9
|
-
import type { EnvironmentType } from '@stainless-api/docs-ui/
|
|
7
|
+
import { parseStainlessPath, type DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
8
|
+
import type { EnvironmentType } from '@stainless-api/docs-ui/markdown/utils';
|
|
10
9
|
import { PROPERTY_SETTINGS, MIDDLEWARE } from 'virtual:stl-starlight-virtual-module';
|
|
10
|
+
import { generateDocsRoutes } from '../helpers/generateDocsRoutes';
|
|
11
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
11
12
|
|
|
12
13
|
type RouteProps = {
|
|
13
14
|
stainlessPath: string;
|
|
@@ -16,17 +17,17 @@ type RouteProps = {
|
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
export const getStaticPaths = (async () => {
|
|
19
|
-
const spec = await
|
|
20
|
+
const spec = await getSDKJSONInSSR();
|
|
20
21
|
return generateDocsRoutes(spec);
|
|
21
22
|
}) satisfies GetStaticPaths;
|
|
22
23
|
|
|
23
24
|
export const GET: APIRoute<RouteProps> = async ({ props }) => {
|
|
24
|
-
const spec = await
|
|
25
|
+
const spec = await getSDKJSONInSSR();
|
|
25
26
|
|
|
26
27
|
if (props.kind === 'readme') {
|
|
27
28
|
const readmeContent = await getReadmeContent(spec, props.language);
|
|
28
29
|
return new Response(readmeContent, {
|
|
29
|
-
headers: { 'Content-Type': 'text/
|
|
30
|
+
headers: { 'Content-Type': 'text/plain' },
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
|
|
@@ -47,11 +48,11 @@ export const GET: APIRoute<RouteProps> = async ({ props }) => {
|
|
|
47
48
|
},
|
|
48
49
|
};
|
|
49
50
|
|
|
50
|
-
const target = props.kind === 'http_method' && parsed?.method ? resource.methods[parsed.method] : resource;
|
|
51
|
+
const target = props.kind === 'http_method' && parsed?.method ? resource.methods[parsed.method]! : resource;
|
|
51
52
|
const output = renderMarkdown(env, target);
|
|
52
53
|
|
|
53
54
|
return new Response(output, {
|
|
54
|
-
headers: { 'Content-Type': 'text/
|
|
55
|
+
headers: { 'Content-Type': 'text/plain' },
|
|
55
56
|
});
|
|
56
57
|
};
|
|
57
58
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type * as SDKJSON from '
|
|
2
|
-
import { generateRoute, walkTree, type DocsLanguage } from '@stainless-api/docs-ui/
|
|
1
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
2
|
+
import { generateRoute, walkTree, type DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
3
3
|
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
|
|
4
4
|
|
|
5
5
|
function isResourceNonEmpty(resource: SDKJSON.Resource) {
|
|
@@ -119,23 +119,12 @@ export type GeneratedSidebarConfig = {
|
|
|
119
119
|
) => ReferenceSidebarConfigItem[] | void;
|
|
120
120
|
};
|
|
121
121
|
|
|
122
|
-
function countKeys(obj?: Record<string,
|
|
123
|
-
|
|
124
|
-
return Object.keys(o).length;
|
|
122
|
+
function countKeys(obj?: Record<string, unknown>) {
|
|
123
|
+
return Object.keys(obj ?? {}).length;
|
|
125
124
|
}
|
|
126
125
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const decl = decls[entry.stainlessPath];
|
|
130
|
-
if (decl !== undefined) {
|
|
131
|
-
if ('ident' in decl) {
|
|
132
|
-
return decl;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
type MethodDecl = Exclude<ReturnType<typeof getMethodDeclForLanguage>, null>;
|
|
126
|
+
type HasIdent<T> = T extends { ident: unknown } ? T : never;
|
|
127
|
+
type MethodDecl = HasIdent<SDKJSON.LanguageDeclNodes[SDKJSON.SpecLanguage]>;
|
|
139
128
|
|
|
140
129
|
function makeAPIOverviewPage(): UserSidebarAPIOverviewPage {
|
|
141
130
|
return {
|
|
@@ -166,7 +155,7 @@ function pullOutSharedModelsResource(resources: SDKJSON.Resource[]): {
|
|
|
166
155
|
}
|
|
167
156
|
|
|
168
157
|
export class SidebarConfigItemsBuilder {
|
|
169
|
-
private getMethodDeclForLanguage(entry: SDKJSON.Method) {
|
|
158
|
+
private getMethodDeclForLanguage(entry: SDKJSON.Method): MethodDecl | null {
|
|
170
159
|
const decls = this.spec.decls[this.language] ?? {};
|
|
171
160
|
const decl = decls[entry.stainlessPath];
|
|
172
161
|
if (decl !== undefined) {
|
|
@@ -177,10 +166,14 @@ export class SidebarConfigItemsBuilder {
|
|
|
177
166
|
return null;
|
|
178
167
|
}
|
|
179
168
|
|
|
169
|
+
private isWebhookResource(resource: SDKJSON.Resource): boolean {
|
|
170
|
+
return resource.stainlessPath === '(resource) webhooks';
|
|
171
|
+
}
|
|
172
|
+
|
|
180
173
|
private toResourceOverviewPage(entry: SDKJSON.Resource): UserSidebarResourceOverviewPage {
|
|
181
174
|
return {
|
|
182
175
|
kind: 'resource_overview_page',
|
|
183
|
-
label: 'Overview',
|
|
176
|
+
label: this.isWebhookResource(entry) ? 'Events' : 'Overview',
|
|
184
177
|
key: entry.configRef,
|
|
185
178
|
badge: undefined,
|
|
186
179
|
metadata: {
|
|
@@ -208,16 +201,10 @@ export class SidebarConfigItemsBuilder {
|
|
|
208
201
|
};
|
|
209
202
|
}
|
|
210
203
|
|
|
211
|
-
private sortByLabel<T extends UserSidebarConfigItem>(items: T[]) {
|
|
212
|
-
// sorts in place
|
|
213
|
-
items.sort((a, b) => {
|
|
214
|
-
return a.label.localeCompare(b.label);
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
204
|
private generateResourceGroup(resource: SDKJSON.Resource, collapsed: boolean): ReferenceSidebarGroup {
|
|
219
205
|
const entries: ReferenceSidebarConfigItem[] = [];
|
|
220
|
-
if
|
|
206
|
+
// even if we aren't generating resource overview pages, we want to generate them for webhooks
|
|
207
|
+
if (!this.options?.excludeResourceOverviewPages || this.isWebhookResource(resource)) {
|
|
221
208
|
entries.push(this.toResourceOverviewPage(resource));
|
|
222
209
|
}
|
|
223
210
|
const methods = Object.values(resource.methods ?? {});
|
|
@@ -228,7 +215,6 @@ export class SidebarConfigItemsBuilder {
|
|
|
228
215
|
methodPages.push(this.toMethodPage(m, langDecl));
|
|
229
216
|
}
|
|
230
217
|
}
|
|
231
|
-
this.sortByLabel(methodPages);
|
|
232
218
|
entries.push(...methodPages);
|
|
233
219
|
|
|
234
220
|
const subresources = Object.values(resource.subresources ?? {});
|
|
@@ -238,7 +224,6 @@ export class SidebarConfigItemsBuilder {
|
|
|
238
224
|
subresourceGroups.push(this.generateResourceGroup(sub, true));
|
|
239
225
|
}
|
|
240
226
|
}
|
|
241
|
-
this.sortByLabel(subresourceGroups);
|
|
242
227
|
entries.push(...subresourceGroups);
|
|
243
228
|
|
|
244
229
|
return {
|
|
@@ -253,7 +238,7 @@ export class SidebarConfigItemsBuilder {
|
|
|
253
238
|
|
|
254
239
|
public generateItems(): ReferenceSidebarConfigItem[] {
|
|
255
240
|
const resourceMap = this.spec.resources;
|
|
256
|
-
|
|
241
|
+
const { resources, sharedModelsResource } = pullOutSharedModelsResource(Object.values(resourceMap ?? {}));
|
|
257
242
|
|
|
258
243
|
const entries: ReferenceSidebarConfigItem[] = resources.filter(isResourceNonEmpty).map((r) => {
|
|
259
244
|
return this.generateResourceGroup(r, false);
|
|
@@ -276,22 +261,11 @@ export class SidebarConfigItemsBuilder {
|
|
|
276
261
|
) {}
|
|
277
262
|
}
|
|
278
263
|
|
|
279
|
-
export function walkSidebarConfigItems(
|
|
280
|
-
sidebar: ReferenceSidebarConfigItem[],
|
|
281
|
-
fn: (item: ReferenceSidebarConfigItem) => void,
|
|
282
|
-
) {
|
|
283
|
-
for (const item of sidebar) {
|
|
284
|
-
fn(item);
|
|
285
|
-
if (item.kind === 'group') {
|
|
286
|
-
walkSidebarConfigItems(item.entries, fn);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
264
|
type SidebarEntry = StarlightRouteData['sidebar'][number];
|
|
292
265
|
|
|
293
266
|
// This allows us to be a bit more forgiving to the user.
|
|
294
267
|
// As long as they don't modify the key, we can still find the item.
|
|
268
|
+
|
|
295
269
|
function getResourceOrMethod(spec: SDKJSON.Spec, endpointOrConfigRef: string) {
|
|
296
270
|
for (const entry of walkTree(spec, false)) {
|
|
297
271
|
if (entry.data.kind === 'resource' && entry.data.configRef === endpointOrConfigRef) {
|
|
@@ -304,7 +278,7 @@ function getResourceOrMethod(spec: SDKJSON.Spec, endpointOrConfigRef: string) {
|
|
|
304
278
|
return null;
|
|
305
279
|
}
|
|
306
280
|
|
|
307
|
-
|
|
281
|
+
function forceGenerateRoute({
|
|
308
282
|
basePath,
|
|
309
283
|
stainlessPath,
|
|
310
284
|
language,
|
|
@@ -325,19 +299,17 @@ export type BuildSidebarParams = {
|
|
|
325
299
|
currentSlug: string;
|
|
326
300
|
};
|
|
327
301
|
|
|
328
|
-
type ToStarlightSidebarParams =
|
|
302
|
+
type ToStarlightSidebarParams = {
|
|
303
|
+
basePath: string;
|
|
329
304
|
spec: SDKJSON.Spec;
|
|
330
305
|
entries: ReferenceSidebarConfigItem[];
|
|
331
|
-
currentStainlessPath: string;
|
|
332
306
|
currentLanguage: DocsLanguage;
|
|
333
307
|
};
|
|
334
308
|
|
|
335
309
|
export function toStarlightSidebar({
|
|
336
310
|
basePath,
|
|
337
|
-
currentSlug,
|
|
338
311
|
spec,
|
|
339
312
|
entries,
|
|
340
|
-
currentStainlessPath,
|
|
341
313
|
currentLanguage,
|
|
342
314
|
}: ToStarlightSidebarParams): SidebarEntry[] {
|
|
343
315
|
const starlightEntries: SidebarEntry[] = [];
|
|
@@ -350,7 +322,7 @@ export function toStarlightSidebar({
|
|
|
350
322
|
type: 'link',
|
|
351
323
|
href: readmeSlug,
|
|
352
324
|
label: entry.label,
|
|
353
|
-
isCurrent:
|
|
325
|
+
isCurrent: false,
|
|
354
326
|
badge: entry.badge,
|
|
355
327
|
attrs: {
|
|
356
328
|
'data-stldocs-overview': 'readme',
|
|
@@ -369,14 +341,12 @@ export function toStarlightSidebar({
|
|
|
369
341
|
language: currentLanguage,
|
|
370
342
|
});
|
|
371
343
|
|
|
372
|
-
const isCurrent = resourceOrMethod.data.stainlessPath === currentStainlessPath;
|
|
373
|
-
|
|
374
344
|
if (resourceOrMethod.data.kind === 'http_method') {
|
|
375
345
|
starlightEntries.push({
|
|
376
346
|
type: 'link',
|
|
377
347
|
href: route,
|
|
378
348
|
label: entry.label,
|
|
379
|
-
isCurrent,
|
|
349
|
+
isCurrent: false,
|
|
380
350
|
badge: entry.badge,
|
|
381
351
|
attrs: {
|
|
382
352
|
'data-stldocs-method': resourceOrMethod.data.httpMethod,
|
|
@@ -387,7 +357,7 @@ export function toStarlightSidebar({
|
|
|
387
357
|
type: 'link',
|
|
388
358
|
href: route,
|
|
389
359
|
label: entry.label,
|
|
390
|
-
isCurrent,
|
|
360
|
+
isCurrent: false,
|
|
391
361
|
badge: entry.badge,
|
|
392
362
|
attrs: {
|
|
393
363
|
// TODO: @Ryan: is data.name unique? This is what we used before so I'm not changing, but I am curious.
|
|
@@ -398,14 +368,20 @@ export function toStarlightSidebar({
|
|
|
398
368
|
throw new Error(`Unknown entry kind ${JSON.stringify(entry)}`);
|
|
399
369
|
}
|
|
400
370
|
} else if (entry.kind === 'group') {
|
|
371
|
+
// Skip pushing the group if if the resource it represents is not available in the current language.
|
|
372
|
+
// This occurs when SDK generation for the current language is skipped in the Stainless config for that resource.
|
|
373
|
+
if (entry.resourceGroupKey) {
|
|
374
|
+
const resourceOrMethod = getResourceOrMethod(spec, entry.resourceGroupKey);
|
|
375
|
+
if (resourceOrMethod?.data?.kind === 'resource' && !resourceOrMethod?.data?.[currentLanguage]) {
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
401
379
|
starlightEntries.push({
|
|
402
380
|
type: 'group',
|
|
403
381
|
label: entry.label,
|
|
404
382
|
entries: toStarlightSidebar({
|
|
405
383
|
basePath,
|
|
406
|
-
currentSlug,
|
|
407
384
|
spec,
|
|
408
|
-
currentStainlessPath,
|
|
409
385
|
entries: entry.entries,
|
|
410
386
|
currentLanguage,
|
|
411
387
|
}),
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFile } from 'fs/promises';
|
|
2
|
+
|
|
3
|
+
import { specPath } from 'virtual:stainless-sdk-json-manifest';
|
|
4
|
+
import { SpecWithAuth } from './generateSpec';
|
|
5
|
+
|
|
6
|
+
let cachedSpecWithAuth: SpecWithAuth | null = null;
|
|
7
|
+
|
|
8
|
+
async function getSpecWithAuthInSSR() {
|
|
9
|
+
if (cachedSpecWithAuth) {
|
|
10
|
+
return cachedSpecWithAuth;
|
|
11
|
+
}
|
|
12
|
+
const specStr = await readFile(specPath, 'utf8');
|
|
13
|
+
const json = JSON.parse(specStr) as SpecWithAuth;
|
|
14
|
+
cachedSpecWithAuth = json;
|
|
15
|
+
return json;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function getSDKJSONInSSR() {
|
|
19
|
+
const specWithAuth = await getSpecWithAuthInSSR();
|
|
20
|
+
return specWithAuth.data;
|
|
21
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
2
|
+
import { Languages } from '@stainless-api/docs-ui/routing';
|
|
3
|
+
import { createSDKJSON, ParsedConfig, parseInputs, transformOAS } from './worker';
|
|
4
|
+
|
|
5
|
+
function addAuthToSpec(spec: SDKJSON.Spec, config: ParsedConfig) {
|
|
6
|
+
const opts = Object.entries(config.client_settings.opts).map(([k, v]) => ({ name: k, ...v }));
|
|
7
|
+
return {
|
|
8
|
+
data: spec,
|
|
9
|
+
auth: spec.security_schemes.map((scheme) => ({
|
|
10
|
+
...scheme,
|
|
11
|
+
opts: opts.filter((opt) => opt.auth?.security_scheme === scheme.name),
|
|
12
|
+
})),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type SpecWithAuth = ReturnType<typeof addAuthToSpec>;
|
|
17
|
+
|
|
18
|
+
export async function generateSpecFromStrings({
|
|
19
|
+
oasStr,
|
|
20
|
+
configStr,
|
|
21
|
+
projectName,
|
|
22
|
+
}: {
|
|
23
|
+
oasStr: string;
|
|
24
|
+
configStr: string;
|
|
25
|
+
projectName: string;
|
|
26
|
+
}) {
|
|
27
|
+
const { oas, config } = await parseInputs({
|
|
28
|
+
oas: oasStr,
|
|
29
|
+
config: configStr,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const transformedOAS = await transformOAS({ oas, config });
|
|
33
|
+
|
|
34
|
+
const languages =
|
|
35
|
+
config.docs?.languages ??
|
|
36
|
+
(Object.entries(config.targets)
|
|
37
|
+
.filter(([name, target]) => Languages.includes(name) && !target.skip)
|
|
38
|
+
.map(([name]) => name) as SDKJSON.SpecLanguage[]);
|
|
39
|
+
|
|
40
|
+
const sdkJson = await createSDKJSON({
|
|
41
|
+
oas: transformedOAS,
|
|
42
|
+
config,
|
|
43
|
+
languages,
|
|
44
|
+
projectName,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const specWithAuth = addAuthToSpec(sdkJson, config);
|
|
48
|
+
|
|
49
|
+
return specWithAuth;
|
|
50
|
+
}
|