@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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"plugin/buildAlgoliaIndex.ts": {
|
|
3
|
+
"@typescript-eslint/no-explicit-any": {
|
|
4
|
+
"count": 2
|
|
5
|
+
}
|
|
6
|
+
},
|
|
7
|
+
"plugin/components/SnippetCode.tsx": {
|
|
8
|
+
"@typescript-eslint/no-explicit-any": {
|
|
9
|
+
"count": 1
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"plugin/globalJs/copy.ts": {
|
|
13
|
+
"@typescript-eslint/no-explicit-any": {
|
|
14
|
+
"count": 3
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"plugin/index.ts": {
|
|
18
|
+
"@typescript-eslint/no-explicit-any": {
|
|
19
|
+
"count": 1
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"plugin/languages.ts": {
|
|
23
|
+
"@typescript-eslint/no-explicit-any": {
|
|
24
|
+
"count": 1
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"plugin/specs/worker.ts": {
|
|
28
|
+
"@typescript-eslint/no-explicit-any": {
|
|
29
|
+
"count": 3
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/locals.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type SidebarEntry = App.Locals['starlightRoute']['sidebar'][number];
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Extending Astro’s `App.Locals` interface
|
|
5
|
+
*/
|
|
6
|
+
declare namespace App {
|
|
7
|
+
interface Locals {
|
|
8
|
+
_stlStarlightPage?: {
|
|
9
|
+
skipRenderingStarlightTitle?: boolean;
|
|
10
|
+
hasMarkdownRoute?: boolean;
|
|
11
|
+
fullSidebar?: SidebarEntry[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
stainlessProject?: string;
|
|
15
|
+
language?: import('@stainless-api/docs-ui/routing').DocsLanguage;
|
|
16
|
+
}
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stainless-api/docs",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.91",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -9,24 +9,18 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
".": "./stl-docs/index.ts",
|
|
11
11
|
"./plugin": "./plugin/index.ts",
|
|
12
|
-
"./OverviewRoute": "./plugin/routes/Overview.astro",
|
|
13
|
-
"./DocsRoute": "./plugin/routes/Docs.astro",
|
|
14
|
-
"./DocsStaticRoute": "./plugin/routes/DocsStatic.astro",
|
|
15
|
-
"./MarkdownRoute": "./plugin/routes/markdown.ts",
|
|
16
|
-
"./Search": "./plugin/components/search/Search.astro",
|
|
17
|
-
"./replaceSidebarPlaceholderMiddleware": "./plugin/replaceSidebarPlaceholderMiddleware.ts",
|
|
18
12
|
"./plugin/middleware": "./plugin/middlewareBuilder/stlStarlightMiddleware.ts",
|
|
19
13
|
"./plugin/MiddlewareTypes": "./plugin/middlewareBuilder/stainlessMiddleware.d.ts",
|
|
20
|
-
"./
|
|
21
|
-
"./ThemeSelect": "./stl-docs/components/ThemeSelect.astro",
|
|
22
|
-
"./BaseSidebar": "./stl-docs/components/sidebars/BaseSidebar.astro",
|
|
23
|
-
"./SDKSelectSidebar": "./stl-docs/components/sidebars/SDKSelectSidebar.astro",
|
|
24
|
-
"./ContentPanel": "./stl-docs/components/content-panel/ContentPanel.astro",
|
|
25
|
-
"./tabsMiddleware": "./stl-docs/tabsMiddleware.ts",
|
|
14
|
+
"./plugin/languages": "./plugin/languages.ts",
|
|
26
15
|
"./stainless-docs/mintlify-compat": "./stl-docs/components/mintlify-compat/index.ts",
|
|
27
|
-
"./theme": "./theme.css",
|
|
28
16
|
"./mintlify-compat.css": "./styles/mintlify-compat.css",
|
|
29
|
-
"./
|
|
17
|
+
"./components": "./stl-docs/components/index.ts",
|
|
18
|
+
"./components/scripts": "./stl-docs/components/scripts.ts",
|
|
19
|
+
"./docs-config": "./stl-docs/loadStlDocsConfig.ts",
|
|
20
|
+
"./specs/fetchSpecSSR": "./plugin/specs/fetchSpecSSR.ts",
|
|
21
|
+
"./generate-docs-routes": "./plugin/helpers/generateDocsRoutes.ts",
|
|
22
|
+
"./components/Head": "./stl-docs/components/Head.astro",
|
|
23
|
+
"./components/ContentBreadcrumbs": "./stl-docs/components/ContentBreadcrumbs.tsx"
|
|
30
24
|
},
|
|
31
25
|
"keywords": [],
|
|
32
26
|
"author": "",
|
|
@@ -35,41 +29,56 @@
|
|
|
35
29
|
"node": ">=18.17.1"
|
|
36
30
|
},
|
|
37
31
|
"peerDependencies": {
|
|
38
|
-
"@astrojs/starlight": ">=0.
|
|
39
|
-
"astro": ">=5.
|
|
32
|
+
"@astrojs/starlight": ">=0.37.5",
|
|
33
|
+
"astro": ">=5.15.3",
|
|
34
|
+
"react": ">=19.0.0",
|
|
35
|
+
"react-dom": ">=19.0.0",
|
|
36
|
+
"vite": ">=6.2.1"
|
|
40
37
|
},
|
|
41
38
|
"dependencies": {
|
|
42
|
-
"@astrojs/markdown-remark": "^6.3.
|
|
43
|
-
"@astrojs/react": "^4.
|
|
44
|
-
"@stainless-api/sdk": "0.1.0-alpha.
|
|
39
|
+
"@astrojs/markdown-remark": "^6.3.10",
|
|
40
|
+
"@astrojs/react": "^4.4.2",
|
|
41
|
+
"@stainless-api/sdk": "0.1.0-alpha.19",
|
|
42
|
+
"astro-expressive-code": "^0.41.6",
|
|
45
43
|
"cheerio": "^1.1.2",
|
|
46
44
|
"clsx": "^2.1.1",
|
|
47
|
-
"dotenv": "17.2.
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
45
|
+
"dotenv": "17.2.3",
|
|
46
|
+
"lucide-react": "^0.562.0",
|
|
47
|
+
"marked": "^17.0.1",
|
|
48
|
+
"node-html-parser": "^7.0.1",
|
|
49
|
+
"rehype-parse": "^9.0.1",
|
|
50
|
+
"rehype-remark": "^10.0.1",
|
|
51
|
+
"remark-gfm": "^4.0.1",
|
|
54
52
|
"remark-github-alerts": "^0.1.1",
|
|
55
|
-
"
|
|
53
|
+
"remark-stringify": "^11.0.0",
|
|
54
|
+
"shiki": "^3.22.0",
|
|
55
|
+
"unified": "^11.0.5",
|
|
56
|
+
"vite-plugin-prebundle-workers": "^0.2.0",
|
|
56
57
|
"web-worker": "^1.5.0",
|
|
57
|
-
"yaml": "^2.8.
|
|
58
|
-
"@stainless-api/docs-
|
|
59
|
-
"@stainless-api/ui
|
|
58
|
+
"yaml": "^2.8.2",
|
|
59
|
+
"@stainless-api/docs-search": "0.1.0-beta.21",
|
|
60
|
+
"@stainless-api/docs-ui": "0.1.0-beta.68",
|
|
61
|
+
"@stainless-api/ui-primitives": "0.1.0-beta.47"
|
|
60
62
|
},
|
|
61
63
|
"devDependencies": {
|
|
62
|
-
"@
|
|
63
|
-
"@
|
|
64
|
-
"@types/
|
|
65
|
-
"@types/react
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
64
|
+
"@astrojs/check": "^0.9.6",
|
|
65
|
+
"@markdoc/markdoc": "^0.5.4",
|
|
66
|
+
"@types/node": "24.10.9",
|
|
67
|
+
"@types/react": "19.2.10",
|
|
68
|
+
"@types/react-dom": "^19.2.3",
|
|
69
|
+
"react": "^19.2.4",
|
|
70
|
+
"react-dom": "^19.2.4",
|
|
71
|
+
"tsx": "^4.21.0",
|
|
72
|
+
"typescript": "5.9.3",
|
|
73
|
+
"vite": "^6.4.1",
|
|
74
|
+
"zod": "^4.3.5",
|
|
75
|
+
"@stainless/eslint-config": "0.1.0-beta.1",
|
|
76
|
+
"@stainless/sdk-json": "^0.1.0-beta.4"
|
|
69
77
|
},
|
|
70
78
|
"scripts": {
|
|
71
|
-
"vendor-deps": "
|
|
79
|
+
"vendor-deps": "tsx scripts/vendor_deps.ts",
|
|
72
80
|
"lint": "eslint . --max-warnings 0",
|
|
73
|
-
"sync": "astro sync"
|
|
81
|
+
"sync": "astro sync",
|
|
82
|
+
"check:types": "astro check"
|
|
74
83
|
}
|
|
75
84
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
declare module 'virtual:stl-playground/typescript.json' {
|
|
2
|
+
const data: {
|
|
3
|
+
links: [string, string][];
|
|
4
|
+
files: [string, string][];
|
|
5
|
+
} | null;
|
|
6
|
+
export { data as default };
|
|
7
|
+
}
|
|
8
|
+
declare module 'virtual:stl-playground/python.json' {
|
|
9
|
+
const data: { files: Record<string, string>; wheel: string } | null;
|
|
10
|
+
export { data as default };
|
|
11
|
+
}
|
|
12
|
+
declare module 'virtual:stl-playground/auth.json' {
|
|
13
|
+
const data:
|
|
14
|
+
| ({
|
|
15
|
+
type: 'http_bearer' | 'query' | 'header' | 'oauth2' | 'http_basic' | 'http_digest';
|
|
16
|
+
description?: string;
|
|
17
|
+
name: string;
|
|
18
|
+
title: string;
|
|
19
|
+
header: string | undefined;
|
|
20
|
+
example: string | undefined;
|
|
21
|
+
} & {
|
|
22
|
+
opts: {
|
|
23
|
+
name: string;
|
|
24
|
+
type: 'string' | 'number' | 'boolean' | 'null' | 'integer';
|
|
25
|
+
nullable: boolean;
|
|
26
|
+
description?: string | undefined;
|
|
27
|
+
example?: unknown;
|
|
28
|
+
default?: unknown;
|
|
29
|
+
read_env?: string | undefined;
|
|
30
|
+
auth?:
|
|
31
|
+
| {
|
|
32
|
+
security_scheme: string;
|
|
33
|
+
role?: 'value' | 'password' | 'username' | 'client_id' | 'client_secret' | undefined;
|
|
34
|
+
}
|
|
35
|
+
| undefined;
|
|
36
|
+
}[];
|
|
37
|
+
})[]
|
|
38
|
+
| null;
|
|
39
|
+
export { data as default };
|
|
40
|
+
}
|
|
41
|
+
declare module 'virtual:stl-playground/data' {
|
|
42
|
+
import type { Config } from 'virtual:stl-playground/create';
|
|
43
|
+
declare const data: Config;
|
|
44
|
+
export { data as default };
|
|
45
|
+
}
|
|
46
|
+
declare module 'virtual:stl-playground/create' {
|
|
47
|
+
export type PlaygroundLanguage = 'python' | 'typescript' | 'http';
|
|
48
|
+
export type Config = {
|
|
49
|
+
wheelUrl: string;
|
|
50
|
+
pyTypes: {
|
|
51
|
+
files: Record<string, string>;
|
|
52
|
+
wheel: string;
|
|
53
|
+
} | null;
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
HIGHLIGHT_THEMES: any;
|
|
56
|
+
tsTypes: {
|
|
57
|
+
links: [string, string][];
|
|
58
|
+
files: [string, string][];
|
|
59
|
+
} | null;
|
|
60
|
+
authData:
|
|
61
|
+
| ({
|
|
62
|
+
type: 'http_bearer' | 'query' | 'header' | 'oauth2' | 'http_basic' | 'http_digest';
|
|
63
|
+
description?: string;
|
|
64
|
+
name: string;
|
|
65
|
+
title: string;
|
|
66
|
+
header: string | undefined;
|
|
67
|
+
example: string | undefined;
|
|
68
|
+
} & {
|
|
69
|
+
opts: {
|
|
70
|
+
name: string;
|
|
71
|
+
type: 'string' | 'number' | 'boolean' | 'null' | 'integer';
|
|
72
|
+
nullable: boolean;
|
|
73
|
+
description?: string | undefined;
|
|
74
|
+
example?: unknown;
|
|
75
|
+
default?: unknown;
|
|
76
|
+
read_env?: string | undefined;
|
|
77
|
+
auth?:
|
|
78
|
+
| {
|
|
79
|
+
security_scheme: string;
|
|
80
|
+
role?: 'value' | 'password' | 'username' | 'client_id' | 'client_secret' | undefined;
|
|
81
|
+
}
|
|
82
|
+
| undefined;
|
|
83
|
+
}[];
|
|
84
|
+
})[]
|
|
85
|
+
| null;
|
|
86
|
+
};
|
|
87
|
+
export function createPlayground(
|
|
88
|
+
props: {
|
|
89
|
+
lang: PlaygroundLanguage;
|
|
90
|
+
doc: string;
|
|
91
|
+
/** div.stl-snippet-request-container */
|
|
92
|
+
container: HTMLElement;
|
|
93
|
+
onLanguageSelect: (value: string) => void;
|
|
94
|
+
} & Config,
|
|
95
|
+
): () => Promise<void>;
|
|
96
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svg
|
|
2
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3
|
+
viewBox="0 0 20 20"
|
|
4
|
+
width="24"
|
|
5
|
+
height="24"
|
|
6
|
+
fill="nopne"
|
|
7
|
+
>
|
|
8
|
+
<path
|
|
9
|
+
fill-rule="evenodd"
|
|
10
|
+
d="M3.25 3A2.25 2.25 0 0 0 1 5.25v9.5A2.25 2.25 0 0 0 3.25 17h13.5A2.25 2.25 0 0 0 19 14.75v-9.5A2.25 2.25 0 0 0 16.75 3zm.943 8.752a.75.75 0 0 1 .055-1.06L6.128 9l-1.88-1.693a.75.75 0 1 1 1.004-1.114l2.5 2.25a.75.75 0 0 1 0 1.114l-2.5 2.25a.75.75 0 0 1-1.06-.055M9.75 10.25a.75.75 0 0 0 0 1.5h2.5a.75.75 0 0 0 0-1.5z"
|
|
11
|
+
clip-rule="evenodd"
|
|
12
|
+
fill="#a2a1a1"
|
|
13
|
+
/>
|
|
14
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none"><defs><linearGradient id="a-_r_1_" x1="46.77" x2="69.91" y1="86.46" y2="126.73" gradientTransform="matrix(8.78996,0,0,8.78996,-233.98,-518.97)" gradientUnits="userSpaceOnUse"><stop stop-color="#927be5"></stop><stop offset="1" stop-color="#512bd4"></stop></linearGradient><filter id="b-_r_1_" width="42.84" height="39.14" x="44.63" y="91.89" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"></feFlood><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"></feColorMatrix><feOffset></feOffset><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"></feColorMatrix><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_2037_2800"></feBlend><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"></feColorMatrix><feOffset dy="1"></feOffset><feGaussianBlur stdDeviation="2.5"></feGaussianBlur><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"></feColorMatrix><feBlend in2="effect1_dropShadow_2037_2800" result="effect2_dropShadow_2037_2800"></feBlend><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"></feColorMatrix><feOffset dy="4"></feOffset><feGaussianBlur stdDeviation="2"></feGaussianBlur><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0"></feColorMatrix><feBlend in2="effect2_dropShadow_2037_2800" result="effect3_dropShadow_2037_2800"></feBlend><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"></feColorMatrix><feOffset dy="9"></feOffset><feGaussianBlur stdDeviation="2.5"></feGaussianBlur><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0"></feColorMatrix><feBlend in2="effect3_dropShadow_2037_2800" result="effect4_dropShadow_2037_2800"></feBlend><feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"></feColorMatrix><feOffset dy="15"></feOffset><feGaussianBlur stdDeviation="3"></feGaussianBlur><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0"></feColorMatrix><feBlend in2="effect4_dropShadow_2037_2800" result="effect5_dropShadow_2037_2800"></feBlend><feBlend in="SourceGraphic" in2="effect5_dropShadow_2037_2800" result="shape"></feBlend></filter></defs><path fill="url(#a-_r_1_)" d="M135.73 285.85v173.93a60.2 60.2 0 0 0 30.13 52.17l150.62 86.97a60.2 60.2 0 0 0 60.25 0l150.62-86.97a60.2 60.2 0 0 0 30.13-52.17V285.85a60.2 60.2 0 0 0-30.13-52.18l-150.62-86.95a60.2 60.2 0 0 0-60.25 0l-150.62 86.95a60.3 60.3 0 0 0-30.13 52.18" transform="scale(0.44288615) matrix(0.1,0,0,0.1,-7.57,-10.19)"></path><path fill="#fff" d="M54.06 98.03v6.86a1.7 1.7 0 0 0 1.71 1.7 1.7 1.7 0 0 0 1.71-1.7 1.71 1.71 0 1 1 3.43 0 5.14 5.14 0 1 1-10.28 0v-6.86a5.14 5.14 0 1 1 10.28 0 1.71 1.71 0 1 1-3.43 0 1.71 1.71 0 1 0-3.42 0zm27.41 6.86a1.7 1.7 0 0 1-1.71 1.7h-1.71v1.72c0 .46-.18.9-.5 1.21a1.7 1.7 0 0 1-2.43 0 1.7 1.7 0 0 1-.5-1.2v-1.72h-3.43v1.71a1.7 1.7 0 0 1-1.71 1.72 1.7 1.7 0 0 1-1.72-1.72v-1.71h-1.71a1.71 1.71 0 1 1 0-3.43h1.71v-3.43h-1.71a1.71 1.71 0 1 1 0-3.42h1.71V94.6a1.71 1.71 0 1 1 3.43 0v1.72h3.43V94.6a1.71 1.71 0 1 1 3.43 0v1.72h1.7c.46 0 .9.18 1.22.5a1.7 1.7 0 0 1 0 2.42 1.7 1.7 0 0 1-1.21.5h-1.71v3.43h1.7a1.7 1.7 0 0 1 1.72 1.71m-6.85-5.14h-3.43v3.42h3.43z" filter="url(#b-_r_1_)" style="mix-blend-mode: screen;" transform="scale(0.44288615) matrix(0.879,0,0,0.879,-30.96,-62.09)"></path></svg>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import Markdoc from '@markdoc/markdoc';
|
|
2
2
|
import Stainless from '@stainless-api/sdk';
|
|
3
|
-
import { createSDKJSON, parseInputs, transformOAS } from './
|
|
4
|
-
import type * as SDKJSON from '
|
|
5
|
-
import { Languages } from '@stainless-api/docs-ui/
|
|
6
|
-
import { buildIndex } from '@stainless-api/docs-
|
|
7
|
-
import type {
|
|
3
|
+
import { createSDKJSON, parseInputs, transformOAS } from './specs/worker';
|
|
4
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
5
|
+
import { Languages } from '@stainless-api/docs-ui/routing';
|
|
6
|
+
import { buildIndex } from '@stainless-api/docs-search/providers/algolia';
|
|
7
|
+
import type { AstroIntegrationLogger } from 'astro';
|
|
8
8
|
|
|
9
9
|
const markdocConfig = {
|
|
10
10
|
nodes: {
|
|
@@ -20,11 +20,38 @@ function renderMarkdown(content?: string) {
|
|
|
20
20
|
return Markdoc.renderers.html(transformed);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export async function buildAlgoliaIndex({
|
|
23
|
+
export async function buildAlgoliaIndex({
|
|
24
|
+
stainlessProject,
|
|
25
|
+
branch,
|
|
26
|
+
apiKey,
|
|
27
|
+
logger,
|
|
28
|
+
}: {
|
|
29
|
+
stainlessProject: string;
|
|
30
|
+
branch: string;
|
|
31
|
+
apiKey: string;
|
|
32
|
+
logger?: AstroIntegrationLogger;
|
|
33
|
+
}) {
|
|
34
|
+
function warnLog(message: string) {
|
|
35
|
+
if (logger) {
|
|
36
|
+
logger.warn(message);
|
|
37
|
+
} else {
|
|
38
|
+
console.warn(message);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function infoLog(message: string) {
|
|
43
|
+
if (logger) {
|
|
44
|
+
logger.info(message);
|
|
45
|
+
} else {
|
|
46
|
+
console.log(message);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// TODO: this is all redundant with the spec code and should be DRYed
|
|
24
51
|
const client = new Stainless({ apiKey });
|
|
25
52
|
const configs = await client.projects.configs.retrieve({
|
|
26
|
-
project:
|
|
27
|
-
branch
|
|
53
|
+
project: stainlessProject,
|
|
54
|
+
branch,
|
|
28
55
|
include: 'openapi',
|
|
29
56
|
});
|
|
30
57
|
|
|
@@ -42,7 +69,6 @@ export async function buildAlgoliaIndex({ version, apiKey }: { version: VersionU
|
|
|
42
69
|
const languages =
|
|
43
70
|
config.docs?.languages ??
|
|
44
71
|
(Object.entries(config.targets)
|
|
45
|
-
// @ts-expect-error we don't have the actual Stainless config type here
|
|
46
72
|
.filter(([name, target]) => Languages.includes(name) && !target.skip)
|
|
47
73
|
.map(([name]) => name) as SDKJSON.SpecLanguage[]);
|
|
48
74
|
|
|
@@ -50,6 +76,7 @@ export async function buildAlgoliaIndex({ version, apiKey }: { version: VersionU
|
|
|
50
76
|
oas: transformedOAS,
|
|
51
77
|
config,
|
|
52
78
|
languages,
|
|
79
|
+
projectName: stainlessProject,
|
|
53
80
|
});
|
|
54
81
|
|
|
55
82
|
const {
|
|
@@ -64,9 +91,9 @@ export async function buildAlgoliaIndex({ version, apiKey }: { version: VersionU
|
|
|
64
91
|
!indexName && 'PUBLIC_ALGOLIA_INDEX',
|
|
65
92
|
!algoliaWriteKey && 'PRIVATE_ALGOLIA_WRITE_KEY',
|
|
66
93
|
].filter(Boolean);
|
|
67
|
-
|
|
94
|
+
warnLog(`Skipping Algolia indexing due to missing environment variables: ${missing.join(', ')}`);
|
|
68
95
|
return;
|
|
69
96
|
}
|
|
70
97
|
await buildIndex(appId, indexName, algoliaWriteKey, sdkJson, renderMarkdown);
|
|
71
|
-
|
|
98
|
+
infoLog('Indexing complete.');
|
|
72
99
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { MethodDescriptionProps } from '@stainless-api/docs-ui/components';
|
|
2
|
+
import { useComponents } from '@stainless-api/docs-ui/contexts/use-components';
|
|
3
|
+
import style from '@stainless-api/docs-ui/style';
|
|
4
|
+
import { Button } from '@stainless-api/ui-primitives';
|
|
5
|
+
|
|
6
|
+
function shouldCollapseDescription(description: string) {
|
|
7
|
+
const MIN_CHARS = 400;
|
|
8
|
+
const MIN_LINES = 6;
|
|
9
|
+
|
|
10
|
+
const lineCount = description.split('\n').length;
|
|
11
|
+
|
|
12
|
+
if (description.length >= MIN_CHARS) return true;
|
|
13
|
+
if (lineCount >= MIN_LINES) return true;
|
|
14
|
+
|
|
15
|
+
// Markdown structure often means longer content
|
|
16
|
+
if (/#\s/.test(description)) return true; // has headings
|
|
17
|
+
if (/```/.test(description)) return true; // has code blocks
|
|
18
|
+
if (/^\s*[-*]\s+/m.test(description)) return true; // has lists
|
|
19
|
+
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function MethodDescription({ description }: MethodDescriptionProps) {
|
|
24
|
+
const { Markdown } = useComponents();
|
|
25
|
+
|
|
26
|
+
if (description) {
|
|
27
|
+
// Attempt to determine if we should make the description collapsible initially
|
|
28
|
+
// or not. If we get this right, there will be no FOUC.
|
|
29
|
+
const collapsible = shouldCollapseDescription(description);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className="stl-method-description">
|
|
33
|
+
<div
|
|
34
|
+
className={style.MethodDescription}
|
|
35
|
+
data-stldocs-property-group="method-description"
|
|
36
|
+
data-collapsed={collapsible ? 'true' : 'false'}
|
|
37
|
+
>
|
|
38
|
+
<Markdown content={description} />
|
|
39
|
+
</div>
|
|
40
|
+
<div className="stl-method-description-overflow-wrapper">
|
|
41
|
+
<Button
|
|
42
|
+
type="button"
|
|
43
|
+
data-method-description-toggle
|
|
44
|
+
size="sm"
|
|
45
|
+
variant="ghost"
|
|
46
|
+
hidden={!collapsible}
|
|
47
|
+
>
|
|
48
|
+
Show more
|
|
49
|
+
</Button>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { Button } from '@stainless-api/ui-primitives';
|
|
3
|
+
import type { Param } from './spec-helpers';
|
|
4
|
+
import { InfoIcon } from 'lucide-react';
|
|
5
|
+
import { Input } from '@stainless-api/docs-ui/components';
|
|
6
|
+
|
|
7
|
+
function setHighlight(stainlessPath: string, highlighted: boolean) {
|
|
8
|
+
const ele = document.getElementById(stainlessPath);
|
|
9
|
+
if (!ele) return;
|
|
10
|
+
ele.classList.toggle('stldocs-property-highlighted', highlighted);
|
|
11
|
+
if (highlighted) {
|
|
12
|
+
if (location.hash) {
|
|
13
|
+
const prevScroll = document.documentElement.scrollTop;
|
|
14
|
+
location.hash = '';
|
|
15
|
+
document.documentElement.scrollTop = prevScroll;
|
|
16
|
+
}
|
|
17
|
+
if (document.body.clientWidth >= 1280) {
|
|
18
|
+
ele.scrollIntoView({
|
|
19
|
+
behavior: 'smooth',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function htmlToText(html: string) {
|
|
26
|
+
const template = document.createElement('template');
|
|
27
|
+
template.innerHTML = html;
|
|
28
|
+
return template.content.textContent;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function ParamEditor({ param }: { param: Param }) {
|
|
32
|
+
const type = useMemo(() => htmlToText(param.type), [param.type]);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<label className="request-builder-param">
|
|
36
|
+
<Button
|
|
37
|
+
className="request-builder-param-info-button"
|
|
38
|
+
variant="ghost"
|
|
39
|
+
href={`#${encodeURIComponent(param.stainlessPath)}`}
|
|
40
|
+
>
|
|
41
|
+
<Button.Icon icon={InfoIcon} size={16} />
|
|
42
|
+
</Button>
|
|
43
|
+
|
|
44
|
+
<span className="request-builder-param-label">{param.key}</span>
|
|
45
|
+
<span className="request-builder-param-colon">:</span>
|
|
46
|
+
|
|
47
|
+
<Input
|
|
48
|
+
className="request-builder-param-value"
|
|
49
|
+
onFocus={() => setHighlight(param.stainlessPath, true)}
|
|
50
|
+
onBlur={() => setHighlight(param.stainlessPath, false)}
|
|
51
|
+
placeholder={type}
|
|
52
|
+
/>
|
|
53
|
+
</label>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { useState, useMemo, useEffect, useId, useSyncExternalStore, Activity, Fragment } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { Button } from '@stainless-api/ui-primitives';
|
|
4
|
+
import { PlayIcon, RotateCcw } from 'lucide-react';
|
|
5
|
+
import { SnippetStainlessIslandPropsSchema } from './props';
|
|
6
|
+
import { ParamEditor } from './ParamEditor';
|
|
7
|
+
import './styles.css';
|
|
8
|
+
|
|
9
|
+
function useRequiredChild<T extends Element = Element>(
|
|
10
|
+
parent: Element | null,
|
|
11
|
+
selector: string,
|
|
12
|
+
): React.RefObject<T> {
|
|
13
|
+
const elementRef = useMemo(() => {
|
|
14
|
+
const el = parent?.querySelector<T>(selector);
|
|
15
|
+
return el ? { current: el } : null;
|
|
16
|
+
}, [parent, selector]);
|
|
17
|
+
if (!elementRef) throw new Error(`Required child not found: ${selector}`);
|
|
18
|
+
return elementRef;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function useSetVisibility(elementRef: React.RefObject<HTMLElement>, visible: boolean) {
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
elementRef.current.style.display = visible ? '' : 'none';
|
|
24
|
+
}, [elementRef, visible]);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default function SnippetStainlessIsland({ parent }: { parent: HTMLElement }) {
|
|
28
|
+
const [expanded, setExpanded] = useState(false);
|
|
29
|
+
|
|
30
|
+
const trigger = useRequiredChild<HTMLButtonElement>(parent, '.try-it-footer .try-it-button');
|
|
31
|
+
const codeContainer = useRequiredChild<HTMLElement>(parent, '.stldocs-snippet-code');
|
|
32
|
+
const exampleContainer = useRequiredChild<HTMLElement>(parent, '.stldocs-snippet-multi-response');
|
|
33
|
+
useSetVisibility(codeContainer, !expanded);
|
|
34
|
+
useSetVisibility(exampleContainer, !expanded);
|
|
35
|
+
useSetVisibility(trigger, !expanded);
|
|
36
|
+
// Attach click handler to trigger
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!trigger.current) return;
|
|
39
|
+
const ac = new AbortController();
|
|
40
|
+
trigger.current.addEventListener('click', () => setExpanded(true), { signal: ac.signal });
|
|
41
|
+
return () => ac.abort();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const requestBuilderContainer = useRequiredChild<HTMLElement>(parent, '.request-builder-container');
|
|
45
|
+
const requestBuilderFooter = useRequiredChild<HTMLElement>(parent, '.request-builder-footer');
|
|
46
|
+
const requestBuilderResponse = useRequiredChild<HTMLElement>(parent, '.request-builder-response');
|
|
47
|
+
const requestBuilderProps = useRequiredChild<HTMLTemplateElement>(parent, '.request-builder-props').current;
|
|
48
|
+
const serializedProps = useSyncExternalStore(
|
|
49
|
+
(cb) => {
|
|
50
|
+
const mutationObserver = new MutationObserver(() => cb());
|
|
51
|
+
mutationObserver.observe(requestBuilderProps, { childList: true });
|
|
52
|
+
return () => mutationObserver.disconnect();
|
|
53
|
+
},
|
|
54
|
+
() => requestBuilderProps.content.textContent,
|
|
55
|
+
);
|
|
56
|
+
const deserializedProps = SnippetStainlessIslandPropsSchema.parse(JSON.parse(serializedProps));
|
|
57
|
+
const groupedParams = Map.groupBy(deserializedProps.params, (p) => p.location);
|
|
58
|
+
|
|
59
|
+
const formId = `request-builder-form-${useId()}`;
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
{createPortal(
|
|
64
|
+
<Activity mode={expanded ? 'visible' : 'hidden'}>
|
|
65
|
+
<form
|
|
66
|
+
onSubmit={(e) => {
|
|
67
|
+
alert('TODO: Submit button clicked');
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
}}
|
|
70
|
+
id={formId}
|
|
71
|
+
>
|
|
72
|
+
{[...groupedParams.entries()].map(([location, params]) => (
|
|
73
|
+
<Fragment key={location}>
|
|
74
|
+
<h4>{location} parameters</h4>
|
|
75
|
+
{params.map((e) => (
|
|
76
|
+
<ParamEditor param={e} key={e.location + e.key} />
|
|
77
|
+
))}
|
|
78
|
+
</Fragment>
|
|
79
|
+
))}
|
|
80
|
+
</form>
|
|
81
|
+
</Activity>,
|
|
82
|
+
requestBuilderContainer.current,
|
|
83
|
+
)}
|
|
84
|
+
|
|
85
|
+
{createPortal(
|
|
86
|
+
<Activity mode={expanded ? 'visible' : 'hidden'}>
|
|
87
|
+
<Button variant="ghost" border={true} onClick={() => setExpanded(false)}>
|
|
88
|
+
<Button.Icon icon={RotateCcw} />
|
|
89
|
+
</Button>
|
|
90
|
+
|
|
91
|
+
<Button variant="success" className="send-button" type="submit" form={formId}>
|
|
92
|
+
<Button.Label>Send</Button.Label>
|
|
93
|
+
<Button.Icon icon={PlayIcon} />
|
|
94
|
+
</Button>
|
|
95
|
+
</Activity>,
|
|
96
|
+
requestBuilderFooter.current,
|
|
97
|
+
)}
|
|
98
|
+
|
|
99
|
+
{createPortal(
|
|
100
|
+
<Activity mode={expanded ? 'visible' : 'hidden'}>
|
|
101
|
+
<div>{/* TODO */}</div>
|
|
102
|
+
</Activity>,
|
|
103
|
+
requestBuilderResponse.current,
|
|
104
|
+
)}
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import * as SDKJSON from '@stainless/sdk-json';
|
|
3
|
+
import { useSpec } from '@stainless-api/docs-ui/contexts';
|
|
4
|
+
import { extractParams } from './spec-helpers';
|
|
5
|
+
import type { SnippetStainlessIslandProps } from './props';
|
|
6
|
+
|
|
7
|
+
/** Load and process the spec on the server side to avoid inflating client bundle */
|
|
8
|
+
export function RequestBuilder({
|
|
9
|
+
className,
|
|
10
|
+
children,
|
|
11
|
+
method,
|
|
12
|
+
}: {
|
|
13
|
+
className: string;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
method: SDKJSON.Method;
|
|
16
|
+
}) {
|
|
17
|
+
const spec = useSpec();
|
|
18
|
+
if (!spec) throw new Error('Spec is required for RequestBuilder');
|
|
19
|
+
const params = spec && extractParams(spec, method);
|
|
20
|
+
const [httpMethod, path] = method.endpoint.split(' ') as [string, string];
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<stl-island component="SnippetStainlessIsland" className={className}>
|
|
24
|
+
{/* Pass state down to the client component. TODO: we need a better solution for this */}
|
|
25
|
+
<template className="request-builder-props">
|
|
26
|
+
{JSON.stringify({ method: httpMethod, path, params } satisfies SnippetStainlessIslandProps)}
|
|
27
|
+
</template>
|
|
28
|
+
{children}
|
|
29
|
+
</stl-island>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { ParamSchema } from './spec-helpers';
|
|
3
|
+
|
|
4
|
+
export const SnippetStainlessIslandPropsSchema = z.object({
|
|
5
|
+
method: z.string(),
|
|
6
|
+
path: z.string(),
|
|
7
|
+
params: z.array(ParamSchema),
|
|
8
|
+
});
|
|
9
|
+
export type SnippetStainlessIslandProps = z.infer<typeof SnippetStainlessIslandPropsSchema>;
|