@stainless-api/docs 0.1.0-beta.1 → 0.1.0-beta.100
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 +917 -0
- package/eslint-suppressions.json +27 -0
- package/locals.d.ts +17 -0
- package/package.json +50 -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/assets/languages/php.svg +4 -0
- package/plugin/buildAlgoliaIndex.ts +40 -39
- 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 +37 -0
- package/plugin/components/RequestBuilder/props.ts +9 -0
- package/plugin/components/RequestBuilder/spec-helpers.ts +47 -0
- package/plugin/components/RequestBuilder/styles.css +67 -0
- package/plugin/components/SDKSelect.astro +18 -105
- package/plugin/components/SnippetCode.tsx +111 -66
- package/plugin/components/StainlessIslands.tsx +126 -0
- package/plugin/components/search/SearchAlgolia.astro +45 -35
- 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 +40 -11
- package/plugin/globalJs/copy.ts +95 -17
- package/plugin/globalJs/create-playground.shim.ts +3 -0
- package/plugin/globalJs/method-descriptions.ts +33 -0
- package/plugin/globalJs/navigation.ts +12 -33
- package/plugin/globalJs/playground-data.shim.ts +1 -0
- package/plugin/globalJs/playground-data.ts +14 -0
- package/plugin/helpers/generateDocsRoutes.ts +59 -0
- package/plugin/helpers/getPageLoadEvent.ts +1 -1
- package/plugin/helpers/multiSpec.ts +8 -0
- package/plugin/index.ts +299 -117
- package/plugin/languages.ts +8 -2
- package/plugin/loadPluginConfig.ts +254 -102
- package/plugin/middlewareBuilder/stainlessMiddleware.d.ts +1 -1
- package/plugin/react/Routing.tsx +210 -140
- package/plugin/referencePlaceholderUtils.ts +18 -15
- package/plugin/replaceSidebarPlaceholderMiddleware.ts +40 -32
- package/plugin/routes/Docs.astro +70 -119
- package/plugin/routes/DocsStatic.astro +6 -5
- package/plugin/routes/Overview.astro +37 -27
- package/plugin/routes/markdown.ts +13 -12
- package/plugin/{cms → sidebar-utils}/sidebar-builder.ts +49 -60
- package/plugin/specs/FileCache.ts +99 -0
- package/plugin/specs/fetchSpecSSR.ts +27 -0
- package/plugin/specs/generateSpec.ts +112 -0
- package/plugin/specs/index.ts +132 -0
- package/plugin/specs/inputResolver.ts +146 -0
- package/plugin/{cms → specs}/worker.ts +82 -5
- package/plugin/vendor/preview.worker.docs.js +22406 -17955
- package/plugin/vendor/templates/cli.md +1 -0
- package/plugin/vendor/templates/go.md +4 -2
- package/plugin/vendor/templates/java.md +3 -1
- package/plugin/vendor/templates/kotlin.md +3 -1
- package/plugin/vendor/templates/node.md +4 -2
- package/plugin/vendor/templates/python.md +4 -2
- package/plugin/vendor/templates/ruby.md +4 -2
- package/plugin/vendor/templates/terraform.md +1 -1
- package/plugin/vendor/templates/typescript.md +3 -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 +7 -9
- 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 -144
- package/stl-docs/components/content-panel/ContentPanel.astro +16 -46
- package/stl-docs/components/headers/DefaultHeader.astro +1 -1
- package/stl-docs/components/headers/HeaderLinks.astro +1 -1
- 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 +17 -0
- package/stl-docs/components/icons/claude.tsx +10 -0
- 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 +10 -0
- package/stl-docs/components/index.ts +1 -0
- package/stl-docs/components/mintlify-compat/Accordion.astro +7 -38
- package/stl-docs/components/mintlify-compat/AccordionGroup.astro +9 -23
- 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 +10 -3
- package/stl-docs/components/mintlify-compat/callouts/Check.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Danger.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Info.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Note.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Tip.astro +7 -3
- package/stl-docs/components/mintlify-compat/callouts/Warning.astro +7 -3
- 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 -75
- 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 +4 -3
- 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 +87 -0
- package/stl-docs/components/sidebars/SDKSelectSidebar.astro +8 -0
- 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 +159 -43
- package/stl-docs/loadStlDocsConfig.ts +60 -9
- 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 +14 -5
- package/styles/code.css +133 -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 +13 -3
- package/tsconfig.json +2 -5
- package/virtual-module.d.ts +65 -7
- package/components/variables.css +0 -139
- 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 -86
- package/stl-docs/components/Sidebar.astro +0 -11
- package/stl-docs/components/content-panel/ProseAIDropdown.tsx +0 -64
- 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,78 @@
|
|
|
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 { parseRoute, parseStainlessPath } from '@stainless-api/docs-ui/routing';
|
|
12
6
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
7
|
+
CONTENT_PANEL_LAYOUT,
|
|
8
|
+
MIDDLEWARE,
|
|
9
|
+
EXPERIMENTAL_REQUEST_BUILDER,
|
|
10
|
+
RESOLVED_API_REFERENCE_PATH,
|
|
11
|
+
} from 'virtual:stl-starlight-virtual-module';
|
|
12
|
+
import { generateDocsRoutes } from '../helpers/generateDocsRoutes';
|
|
13
|
+
import { StainlessIslands } from '../components/StainlessIslands';
|
|
14
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
21
15
|
|
|
16
|
+
const language = parseRoute(RESOLVED_API_REFERENCE_PATH, Astro.url.pathname)?.language;
|
|
22
17
|
|
|
23
|
-
const spec = await
|
|
24
|
-
const routes = generateDocsRoutes(spec);
|
|
18
|
+
const spec = await getSDKJSONInSSR(language);
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
export type Props = Awaited<ReturnType<typeof generateDocsRoutes>>[number]['props'] | Record<string, never>;
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
const props =
|
|
23
|
+
'language' in Astro.props
|
|
24
|
+
? // In prod, we pass the props down to this page
|
|
25
|
+
Astro.props
|
|
26
|
+
: // In the dev server, we skip the DocsStatic wrapper so we need to find the props ourselves
|
|
27
|
+
generateDocsRoutes(spec).find((r) => r.params.slug === Astro.params.slug)?.props;
|
|
28
|
+
if (!props) throw new Error(`Could not find a route for slug '${Astro.params.slug}'`);
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
: null;
|
|
30
|
+
// PageTitle override will skip rendering the default Starlight title
|
|
31
|
+
Astro.locals._stlStarlightPage = {
|
|
32
|
+
skipRenderingStarlightTitle: props.kind === 'readme' ? false : true,
|
|
33
|
+
};
|
|
37
34
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const readmeContent = await getReadmeContent(spec, props.language);
|
|
36
|
+
const readme = props.kind === 'readme' ? await astroMarkdownRender(readmeContent ?? '') : null;
|
|
37
|
+
|
|
38
|
+
const resource = props.stainlessPath ? getResourceFromSpec(props.stainlessPath, spec) : null;
|
|
41
39
|
|
|
42
40
|
const pageNav =
|
|
43
|
-
|
|
41
|
+
props.kind === 'resource' && resource
|
|
44
42
|
? buildPageNavigation(resource)
|
|
45
|
-
:
|
|
43
|
+
: props.kind === 'readme' && readme?.metadata
|
|
46
44
|
? readme?.metadata.headings
|
|
47
45
|
: [];
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
Astro.locals.language = props.language;
|
|
50
48
|
|
|
49
|
+
// Use first heading in README as page title
|
|
51
50
|
if (readme) {
|
|
52
51
|
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";
|
|
52
|
+
readme.code = readme.code.replace(/<a href="(?!(?:https?:\/\/|\/\/))([^"]+)"/g, `<a href="${repo}/$1"`);
|
|
53
|
+
props.title = readme.metadata.headings[0]!.text ?? 'Overview';
|
|
57
54
|
}
|
|
58
55
|
|
|
56
|
+
// use summary for the page title of method pages
|
|
57
|
+
if (props.kind === 'http_method' && props.stainlessPath) {
|
|
58
|
+
const parsed = parseStainlessPath(props.stainlessPath);
|
|
59
|
+
const resource = getResourceFromSpec(props.stainlessPath, spec);
|
|
60
|
+
if (parsed?.method && resource?.methods[parsed.method]) {
|
|
61
|
+
const method = resource.methods[parsed.method];
|
|
62
|
+
props.title = method?.summary ?? method?.title ?? props.title;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
59
65
|
---
|
|
60
66
|
|
|
61
|
-
|
|
62
67
|
<StarlightPage
|
|
63
68
|
headings={pageNav}
|
|
64
69
|
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
|
-
],
|
|
70
|
+
title: props.title,
|
|
76
71
|
pagefind: false,
|
|
77
|
-
tableOfContents:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
stainlessStarlight: {
|
|
82
|
-
basePath: BASE_PATH,
|
|
83
|
-
...props,
|
|
84
|
-
},
|
|
72
|
+
tableOfContents:
|
|
73
|
+
props.kind === 'readme' || (props.kind === 'resource' && props.language !== 'terraform')
|
|
74
|
+
? { maxHeadingLevel: 6 }
|
|
75
|
+
: false,
|
|
85
76
|
}}
|
|
86
77
|
>
|
|
87
78
|
{
|
|
@@ -96,76 +87,36 @@ if (readme) {
|
|
|
96
87
|
contentPanelLayout={CONTENT_PANEL_LAYOUT}
|
|
97
88
|
transformRequestSnippet={MIDDLEWARE.transformRequestSnippet}
|
|
98
89
|
/>
|
|
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
90
|
</div>
|
|
131
91
|
) : (
|
|
132
92
|
<>
|
|
133
93
|
<Fragment set:html={readme?.code} />
|
|
134
|
-
<style
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
background-color: currentColor;
|
|
152
|
-
color: inherit;
|
|
153
|
-
display: inline-block;
|
|
154
|
-
vertical-align: text-bottom;
|
|
155
|
-
width: 1em;
|
|
156
|
-
height: 1em;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
.sl-markdown-content code {
|
|
160
|
-
white-space: pre-wrap;
|
|
161
|
-
}
|
|
162
|
-
</style>
|
|
94
|
+
<style
|
|
95
|
+
is:inline
|
|
96
|
+
set:text={`
|
|
97
|
+
.sl-markdown-content h1:first-of-type {
|
|
98
|
+
display: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.sl-markdown-content img {
|
|
102
|
+
display: inline-block;
|
|
103
|
+
vertical-align: text-bottom;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.sl-markdown-content code {
|
|
107
|
+
white-space: pre-wrap;
|
|
108
|
+
}
|
|
109
|
+
`}
|
|
110
|
+
/>
|
|
163
111
|
</>
|
|
164
112
|
)
|
|
165
113
|
}
|
|
166
114
|
</StarlightPage>
|
|
167
115
|
|
|
116
|
+
{EXPERIMENTAL_REQUEST_BUILDER && <StainlessIslands client:load />}
|
|
117
|
+
|
|
168
118
|
<script src="../globalJs/navigation.ts"></script>
|
|
169
119
|
<script src="../globalJs/copy.ts"></script>
|
|
170
120
|
<script src="../globalJs/tooltip.ts"></script>
|
|
171
121
|
<script src="../globalJs/code-snippets.ts"></script>
|
|
122
|
+
<script src="../globalJs/method-descriptions.ts"></script>
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { GetStaticPaths } from 'astro';
|
|
3
3
|
import Docs from './Docs.astro';
|
|
4
|
-
import {
|
|
5
|
-
import { generateDocsRoutes } from '../react/Routing';
|
|
4
|
+
import { generateAllDocsRoutes } from '../helpers/generateDocsRoutes';
|
|
6
5
|
|
|
7
6
|
export const getStaticPaths = (async () => {
|
|
8
|
-
const
|
|
9
|
-
const routes = generateDocsRoutes(spec);
|
|
7
|
+
const routes = await generateAllDocsRoutes();
|
|
10
8
|
return routes;
|
|
11
9
|
}) satisfies GetStaticPaths;
|
|
10
|
+
|
|
11
|
+
export type Props = Awaited<ReturnType<typeof getStaticPaths>>[number]['props'];
|
|
12
|
+
const props = Astro.props;
|
|
12
13
|
---
|
|
13
14
|
|
|
14
|
-
<Docs />
|
|
15
|
+
<Docs {...props} />
|
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
---
|
|
2
2
|
import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
|
|
3
|
-
import {
|
|
4
|
-
import { cmsClient } from '../cms/client';
|
|
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';
|
|
13
4
|
import { RenderLibraries, RenderSpecOverview, type SpecMetadata } from '../react/Routing';
|
|
5
|
+
import { getSDKJSONInSSR } from '../specs/fetchSpecSSR';
|
|
6
|
+
import { api } from 'virtual:stainless-apis-manifest';
|
|
7
|
+
|
|
8
|
+
const spec = await getSDKJSONInSSR('http');
|
|
9
|
+
|
|
10
|
+
const langTargets = api.languages
|
|
11
|
+
.map((l) => l.language)
|
|
12
|
+
.filter((l) => !EXCLUDE_LANGUAGES.includes(l))
|
|
13
|
+
.filter((l) => l !== 'http');
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const langsWithSpecs = await Promise.all(
|
|
16
|
+
langTargets.map(async (language) => {
|
|
17
|
+
const spec = await getSDKJSONInSSR(language);
|
|
18
|
+
return {
|
|
19
|
+
language,
|
|
20
|
+
spec,
|
|
21
|
+
};
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
16
24
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
const metadata: SpecMetadata = langsWithSpecs.map(({ language, spec }) => [
|
|
26
|
+
language,
|
|
27
|
+
spec.metadata[language]!,
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
// PageTitle override will skip rendering the default Starlight title
|
|
31
|
+
Astro.locals._stlStarlightPage = {
|
|
32
|
+
hasMarkdownRoute: false,
|
|
33
|
+
};
|
|
22
34
|
---
|
|
23
35
|
|
|
24
36
|
<StarlightPage
|
|
@@ -26,22 +38,20 @@ const metadata = languages
|
|
|
26
38
|
title: 'API Reference',
|
|
27
39
|
pagefind: false,
|
|
28
40
|
tableOfContents: false,
|
|
29
|
-
stainlessStarlight: {
|
|
30
|
-
basePath: BASE_PATH,
|
|
31
|
-
language: 'http',
|
|
32
|
-
},
|
|
33
41
|
}}
|
|
34
42
|
>
|
|
35
|
-
<
|
|
43
|
+
<div class="stl-overview">
|
|
44
|
+
<h3>Libraries</h3>
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
<div class="stldocs-root language-blocks stl-ui-not-prose not-content">
|
|
47
|
+
<RenderLibraries metadata={metadata} />
|
|
48
|
+
</div>
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
<h3>API Overview</h3>
|
|
42
51
|
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
<div class="stldocs-root api-overview stl-ui-not-prose">
|
|
53
|
+
<RenderSpecOverview spec={spec} language="http" />
|
|
54
|
+
</div>
|
|
45
55
|
</div>
|
|
46
56
|
</StarlightPage>
|
|
47
57
|
|
|
@@ -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 { generateAllDocsRoutes } 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
|
|
20
|
-
return
|
|
20
|
+
const paths = await generateAllDocsRoutes();
|
|
21
|
+
return paths;
|
|
21
22
|
}) satisfies GetStaticPaths;
|
|
22
23
|
|
|
23
24
|
export const GET: APIRoute<RouteProps> = async ({ props }) => {
|
|
24
|
-
const spec = await
|
|
25
|
+
const spec = await getSDKJSONInSSR(props.language);
|
|
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,7 +1,20 @@
|
|
|
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
|
+
function makeMethodOrResourceKey(entry: SDKJSON.Method | SDKJSON.Resource): string {
|
|
6
|
+
if (entry.kind === 'http_method') {
|
|
7
|
+
if (entry.endpoint && entry.endpoint !== '') {
|
|
8
|
+
return entry.endpoint;
|
|
9
|
+
}
|
|
10
|
+
return entry.stainlessPath;
|
|
11
|
+
}
|
|
12
|
+
if (entry.kind === 'resource') {
|
|
13
|
+
return entry.stainlessPath;
|
|
14
|
+
}
|
|
15
|
+
throw new Error(`Unknown entry kind ${JSON.stringify(entry)}`);
|
|
16
|
+
}
|
|
17
|
+
|
|
5
18
|
function isResourceNonEmpty(resource: SDKJSON.Resource) {
|
|
6
19
|
return (
|
|
7
20
|
Object.keys(resource.methods ?? {}).length > 0 ||
|
|
@@ -119,23 +132,12 @@ export type GeneratedSidebarConfig = {
|
|
|
119
132
|
) => ReferenceSidebarConfigItem[] | void;
|
|
120
133
|
};
|
|
121
134
|
|
|
122
|
-
function countKeys(obj?: Record<string,
|
|
123
|
-
|
|
124
|
-
return Object.keys(o).length;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function getMethodDeclForLanguage(entry: SDKJSON.Method, spec: SDKJSON.Spec, language: DocsLanguage) {
|
|
128
|
-
const decls = spec.decls[language] ?? {};
|
|
129
|
-
const decl = decls[entry.stainlessPath];
|
|
130
|
-
if (decl !== undefined) {
|
|
131
|
-
if ('ident' in decl) {
|
|
132
|
-
return decl;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
135
|
+
function countKeys(obj?: Record<string, unknown>) {
|
|
136
|
+
return Object.keys(obj ?? {}).length;
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
type
|
|
139
|
+
type HasIdent<T> = T extends { ident: unknown } ? T : never;
|
|
140
|
+
type MethodDecl = HasIdent<SDKJSON.LanguageDeclNodes[SDKJSON.SpecLanguage]>;
|
|
139
141
|
|
|
140
142
|
function makeAPIOverviewPage(): UserSidebarAPIOverviewPage {
|
|
141
143
|
return {
|
|
@@ -166,7 +168,7 @@ function pullOutSharedModelsResource(resources: SDKJSON.Resource[]): {
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
export class SidebarConfigItemsBuilder {
|
|
169
|
-
private getMethodDeclForLanguage(entry: SDKJSON.Method) {
|
|
171
|
+
private getMethodDeclForLanguage(entry: SDKJSON.Method): MethodDecl | null {
|
|
170
172
|
const decls = this.spec.decls[this.language] ?? {};
|
|
171
173
|
const decl = decls[entry.stainlessPath];
|
|
172
174
|
if (decl !== undefined) {
|
|
@@ -177,11 +179,15 @@ export class SidebarConfigItemsBuilder {
|
|
|
177
179
|
return null;
|
|
178
180
|
}
|
|
179
181
|
|
|
182
|
+
private isWebhookResource(resource: SDKJSON.Resource): boolean {
|
|
183
|
+
return resource.stainlessPath === '(resource) webhooks';
|
|
184
|
+
}
|
|
185
|
+
|
|
180
186
|
private toResourceOverviewPage(entry: SDKJSON.Resource): UserSidebarResourceOverviewPage {
|
|
181
187
|
return {
|
|
182
188
|
kind: 'resource_overview_page',
|
|
183
|
-
label: 'Overview',
|
|
184
|
-
key: entry
|
|
189
|
+
label: this.isWebhookResource(entry) ? 'Events' : 'Overview',
|
|
190
|
+
key: makeMethodOrResourceKey(entry),
|
|
185
191
|
badge: undefined,
|
|
186
192
|
metadata: {
|
|
187
193
|
subResourceCount: countKeys(entry.subresources),
|
|
@@ -195,7 +201,7 @@ export class SidebarConfigItemsBuilder {
|
|
|
195
201
|
return {
|
|
196
202
|
kind: 'method_page',
|
|
197
203
|
label: entry.title,
|
|
198
|
-
key: entry
|
|
204
|
+
key: makeMethodOrResourceKey(entry),
|
|
199
205
|
badge: undefined,
|
|
200
206
|
metadata: {
|
|
201
207
|
deprecated: Boolean(entry.deprecated),
|
|
@@ -208,16 +214,10 @@ export class SidebarConfigItemsBuilder {
|
|
|
208
214
|
};
|
|
209
215
|
}
|
|
210
216
|
|
|
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
217
|
private generateResourceGroup(resource: SDKJSON.Resource, collapsed: boolean): ReferenceSidebarGroup {
|
|
219
218
|
const entries: ReferenceSidebarConfigItem[] = [];
|
|
220
|
-
if
|
|
219
|
+
// even if we aren't generating resource overview pages, we want to generate them for webhooks
|
|
220
|
+
if (!this.options?.excludeResourceOverviewPages || this.isWebhookResource(resource)) {
|
|
221
221
|
entries.push(this.toResourceOverviewPage(resource));
|
|
222
222
|
}
|
|
223
223
|
const methods = Object.values(resource.methods ?? {});
|
|
@@ -228,7 +228,6 @@ export class SidebarConfigItemsBuilder {
|
|
|
228
228
|
methodPages.push(this.toMethodPage(m, langDecl));
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
-
this.sortByLabel(methodPages);
|
|
232
231
|
entries.push(...methodPages);
|
|
233
232
|
|
|
234
233
|
const subresources = Object.values(resource.subresources ?? {});
|
|
@@ -238,14 +237,13 @@ export class SidebarConfigItemsBuilder {
|
|
|
238
237
|
subresourceGroups.push(this.generateResourceGroup(sub, true));
|
|
239
238
|
}
|
|
240
239
|
}
|
|
241
|
-
this.sortByLabel(subresourceGroups);
|
|
242
240
|
entries.push(...subresourceGroups);
|
|
243
241
|
|
|
244
242
|
return {
|
|
245
243
|
kind: 'group',
|
|
246
244
|
badge: undefined,
|
|
247
245
|
label: resource.title,
|
|
248
|
-
resourceGroupKey: resource
|
|
246
|
+
resourceGroupKey: makeMethodOrResourceKey(resource),
|
|
249
247
|
entries,
|
|
250
248
|
collapsed,
|
|
251
249
|
};
|
|
@@ -253,7 +251,7 @@ export class SidebarConfigItemsBuilder {
|
|
|
253
251
|
|
|
254
252
|
public generateItems(): ReferenceSidebarConfigItem[] {
|
|
255
253
|
const resourceMap = this.spec.resources;
|
|
256
|
-
|
|
254
|
+
const { resources, sharedModelsResource } = pullOutSharedModelsResource(Object.values(resourceMap ?? {}));
|
|
257
255
|
|
|
258
256
|
const entries: ReferenceSidebarConfigItem[] = resources.filter(isResourceNonEmpty).map((r) => {
|
|
259
257
|
return this.generateResourceGroup(r, false);
|
|
@@ -276,35 +274,24 @@ export class SidebarConfigItemsBuilder {
|
|
|
276
274
|
) {}
|
|
277
275
|
}
|
|
278
276
|
|
|
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
277
|
type SidebarEntry = StarlightRouteData['sidebar'][number];
|
|
292
278
|
|
|
293
279
|
// This allows us to be a bit more forgiving to the user.
|
|
294
280
|
// As long as they don't modify the key, we can still find the item.
|
|
281
|
+
|
|
295
282
|
function getResourceOrMethod(spec: SDKJSON.Spec, endpointOrConfigRef: string) {
|
|
296
283
|
for (const entry of walkTree(spec, false)) {
|
|
297
|
-
if (entry.data.kind === '
|
|
298
|
-
|
|
284
|
+
if (entry.data.kind === 'model') {
|
|
285
|
+
continue;
|
|
299
286
|
}
|
|
300
|
-
if (entry.data
|
|
287
|
+
if (makeMethodOrResourceKey(entry.data) === endpointOrConfigRef) {
|
|
301
288
|
return entry;
|
|
302
289
|
}
|
|
303
290
|
}
|
|
304
291
|
return null;
|
|
305
292
|
}
|
|
306
293
|
|
|
307
|
-
|
|
294
|
+
function forceGenerateRoute({
|
|
308
295
|
basePath,
|
|
309
296
|
stainlessPath,
|
|
310
297
|
language,
|
|
@@ -325,19 +312,17 @@ export type BuildSidebarParams = {
|
|
|
325
312
|
currentSlug: string;
|
|
326
313
|
};
|
|
327
314
|
|
|
328
|
-
type ToStarlightSidebarParams =
|
|
315
|
+
type ToStarlightSidebarParams = {
|
|
316
|
+
basePath: string;
|
|
329
317
|
spec: SDKJSON.Spec;
|
|
330
318
|
entries: ReferenceSidebarConfigItem[];
|
|
331
|
-
currentStainlessPath: string;
|
|
332
319
|
currentLanguage: DocsLanguage;
|
|
333
320
|
};
|
|
334
321
|
|
|
335
322
|
export function toStarlightSidebar({
|
|
336
323
|
basePath,
|
|
337
|
-
currentSlug,
|
|
338
324
|
spec,
|
|
339
325
|
entries,
|
|
340
|
-
currentStainlessPath,
|
|
341
326
|
currentLanguage,
|
|
342
327
|
}: ToStarlightSidebarParams): SidebarEntry[] {
|
|
343
328
|
const starlightEntries: SidebarEntry[] = [];
|
|
@@ -350,7 +335,7 @@ export function toStarlightSidebar({
|
|
|
350
335
|
type: 'link',
|
|
351
336
|
href: readmeSlug,
|
|
352
337
|
label: entry.label,
|
|
353
|
-
isCurrent:
|
|
338
|
+
isCurrent: false,
|
|
354
339
|
badge: entry.badge,
|
|
355
340
|
attrs: {
|
|
356
341
|
'data-stldocs-overview': 'readme',
|
|
@@ -369,14 +354,12 @@ export function toStarlightSidebar({
|
|
|
369
354
|
language: currentLanguage,
|
|
370
355
|
});
|
|
371
356
|
|
|
372
|
-
const isCurrent = resourceOrMethod.data.stainlessPath === currentStainlessPath;
|
|
373
|
-
|
|
374
357
|
if (resourceOrMethod.data.kind === 'http_method') {
|
|
375
358
|
starlightEntries.push({
|
|
376
359
|
type: 'link',
|
|
377
360
|
href: route,
|
|
378
361
|
label: entry.label,
|
|
379
|
-
isCurrent,
|
|
362
|
+
isCurrent: false,
|
|
380
363
|
badge: entry.badge,
|
|
381
364
|
attrs: {
|
|
382
365
|
'data-stldocs-method': resourceOrMethod.data.httpMethod,
|
|
@@ -387,7 +370,7 @@ export function toStarlightSidebar({
|
|
|
387
370
|
type: 'link',
|
|
388
371
|
href: route,
|
|
389
372
|
label: entry.label,
|
|
390
|
-
isCurrent,
|
|
373
|
+
isCurrent: false,
|
|
391
374
|
badge: entry.badge,
|
|
392
375
|
attrs: {
|
|
393
376
|
// TODO: @Ryan: is data.name unique? This is what we used before so I'm not changing, but I am curious.
|
|
@@ -398,14 +381,20 @@ export function toStarlightSidebar({
|
|
|
398
381
|
throw new Error(`Unknown entry kind ${JSON.stringify(entry)}`);
|
|
399
382
|
}
|
|
400
383
|
} else if (entry.kind === 'group') {
|
|
384
|
+
// Skip pushing the group if if the resource it represents is not available in the current language.
|
|
385
|
+
// This occurs when SDK generation for the current language is skipped in the Stainless config for that resource.
|
|
386
|
+
if (entry.resourceGroupKey) {
|
|
387
|
+
const resourceOrMethod = getResourceOrMethod(spec, entry.resourceGroupKey);
|
|
388
|
+
if (resourceOrMethod?.data?.kind === 'resource' && !resourceOrMethod?.data?.[currentLanguage]) {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
401
392
|
starlightEntries.push({
|
|
402
393
|
type: 'group',
|
|
403
394
|
label: entry.label,
|
|
404
395
|
entries: toStarlightSidebar({
|
|
405
396
|
basePath,
|
|
406
|
-
currentSlug,
|
|
407
397
|
spec,
|
|
408
|
-
currentStainlessPath,
|
|
409
398
|
entries: entry.entries,
|
|
410
399
|
currentLanguage,
|
|
411
400
|
}),
|