@stainless-api/docs-ui 0.1.0-beta.14 → 0.1.0-beta.15
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/dist/breadcrumbs-Z-hEqjcp.d.ts +19 -0
- package/dist/chunk-Bp6m_JJh.js +13 -0
- package/dist/component-generics-DzI21jRn.js +35 -0
- package/dist/component-generics-q5Dqiu2D.d.ts +30 -0
- package/dist/components/breadcrumbs.d.ts +2 -0
- package/dist/components/breadcrumbs.js +16 -0
- package/dist/components/chat.d.ts +14 -0
- package/dist/components/chat.js +144 -0
- package/dist/components/dropdown.d.ts +2 -0
- package/dist/components/dropdown.js +4 -0
- package/dist/components/icons.d.ts +50 -0
- package/dist/components/icons.js +3 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/components/index.js +16 -0
- package/dist/components/method.d.ts +2 -0
- package/dist/components/method.js +16 -0
- package/dist/components/overview.d.ts +2 -0
- package/dist/components/overview.js +16 -0
- package/dist/components/primitives.d.ts +2 -0
- package/dist/components/primitives.js +16 -0
- package/dist/components/properties.d.ts +2 -0
- package/dist/components/properties.js +16 -0
- package/dist/components/scripts/dropdown.d.ts +12 -0
- package/dist/components/scripts/dropdown.js +50 -0
- package/dist/components/sdk.d.ts +3 -0
- package/dist/components/sdk.js +16 -0
- package/dist/components/sidebar.d.ts +2 -0
- package/dist/components/sidebar.js +16 -0
- package/dist/components/snippets.d.ts +4 -0
- package/dist/components/snippets.js +16 -0
- package/dist/contexts/component-generics.d.ts +2 -0
- package/dist/contexts/component-generics.js +3 -0
- package/dist/contexts/component-types.d.ts +18 -0
- package/dist/contexts/component-types.js +1 -0
- package/dist/contexts/component.d.ts +31 -0
- package/dist/contexts/component.js +16 -0
- package/dist/contexts/docs.d.ts +2 -0
- package/dist/contexts/docs.js +3 -0
- package/dist/contexts/index.d.ts +20 -0
- package/dist/contexts/index.js +16 -0
- package/dist/contexts/markdown.d.ts +2 -0
- package/dist/contexts/markdown.js +4 -0
- package/dist/contexts/navigation.d.ts +3 -0
- package/dist/contexts/navigation.js +3 -0
- package/dist/contexts/search.d.ts +4 -0
- package/dist/contexts/search.js +16 -0
- package/dist/contexts/use-components.d.ts +16 -0
- package/dist/contexts/use-components.js +4 -0
- package/dist/contexts-DRxRO-xO.js +3747 -0
- package/dist/docs-Dh8kE1va.js +50 -0
- package/dist/docs-EUy-wfbA.d.ts +43 -0
- package/dist/dropdown-B7VyGMOw.d.ts +43 -0
- package/dist/dropdown-DtgAi6lb.js +62 -0
- package/dist/icons-DdKM-01E.js +753 -0
- package/dist/index-AicgPYKB.d.ts +239 -0
- package/dist/index-BhwLhiWk.d.ts +14 -0
- package/dist/index-YnpUtXLB.d.ts +16 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +5276 -5873
- package/dist/languages/go.d.ts +13 -0
- package/dist/languages/go.js +16 -0
- package/dist/languages/http.d.ts +13 -0
- package/dist/languages/http.js +16 -0
- package/dist/languages/index.d.ts +13 -0
- package/dist/languages/index.js +16 -0
- package/dist/languages/java.d.ts +13 -0
- package/dist/languages/java.js +16 -0
- package/dist/languages/python.d.ts +13 -0
- package/dist/languages/python.js +16 -0
- package/dist/languages/ruby.d.ts +13 -0
- package/dist/languages/ruby.js +16 -0
- package/dist/languages/typescript.d.ts +13 -0
- package/dist/languages/typescript.js +16 -0
- package/dist/markdown/index.d.ts +11 -0
- package/dist/markdown/index.js +16 -0
- package/dist/markdown/md.d.ts +15 -0
- package/dist/markdown/md.js +3 -0
- package/dist/markdown/utils.d.ts +4 -0
- package/dist/markdown/utils.js +3 -0
- package/dist/markdown-BXfX1D7C.js +42 -0
- package/dist/markdown-nFyAEX_K.d.ts +22 -0
- package/dist/mcp.js +1720 -2298
- package/dist/md-Dg8aOyMA.js +41 -0
- package/dist/method-DpsVuzZW.d.ts +71 -0
- package/dist/navigation-aoYZ_tl4.js +24 -0
- package/dist/navigation-nyXBY-75.d.ts +29 -0
- package/dist/overview-C8e-6jGr.d.ts +38 -0
- package/dist/pagefind-ChrPfuVv.js +15 -0
- package/dist/primitives-DWz23_Ub.d.ts +99 -0
- package/dist/properties-CF71V58d.d.ts +46 -0
- package/dist/routing-DQjbRxdJ.js +189 -0
- package/dist/routing-qc0V00-j.d.ts +51 -0
- package/dist/routing.d.ts +2 -0
- package/dist/sdk-Zg3Rggk3.d.ts +118 -0
- package/dist/search/index.d.ts +26 -0
- package/dist/search/index.js +332 -0
- package/dist/search/providers/algolia.d.ts +23 -0
- package/dist/search/providers/algolia.js +16 -0
- package/dist/search/providers/fuse.d.ts +17 -0
- package/dist/search/providers/fuse.js +31 -0
- package/dist/search/providers/pagefind.d.ts +7 -0
- package/dist/search/providers/pagefind.js +3 -0
- package/dist/search/providers/walker.d.ts +8 -0
- package/dist/search/providers/walker.js +32 -0
- package/dist/search/types.d.ts +3 -0
- package/dist/search/types.js +3 -0
- package/dist/search-B6loAGmB.d.ts +21 -0
- package/dist/sidebar-C8KirYjg.d.ts +35 -0
- package/dist/snippets-EUzM4fRO.d.ts +45 -0
- package/dist/style-pN9hCoec.d.ts +181 -0
- package/dist/style-rYbbxIR_.js +182 -0
- package/dist/style.d.ts +2 -0
- package/dist/style.js +3 -0
- package/dist/styles/main.css +742 -748
- package/dist/styles/primitives.css +435 -428
- package/dist/styles/resets.css +33 -41
- package/dist/styles/search.css +247 -248
- package/dist/styles/sidebar.css +58 -60
- package/dist/styles/snippets.css +86 -88
- package/dist/styles/variables.css +86 -90
- package/dist/types-CTBDtD34.d.ts +82 -0
- package/dist/types-DFN4M1Sp.js +34 -0
- package/dist/use-components-D9E85p5x.js +7 -0
- package/dist/utils-BHwvUDKn.js +30 -0
- package/dist/utils-CJfFBNgT.js +32 -0
- package/dist/utils-DQhEbvUC.d.ts +20 -0
- package/dist/utils-nDazhti8.d.ts +11 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +4 -0
- package/package.json +13 -7
- package/src/components/breadcrumbs.tsx +1 -1
- package/src/components/chat.tsx +18 -15
- package/src/components/method.tsx +8 -9
- package/src/components/overview.tsx +26 -12
- package/src/components/primitives.tsx +36 -19
- package/src/components/properties.tsx +4 -2
- package/src/components/scripts/dropdown.ts +1 -1
- package/src/components/sdk.tsx +25 -20
- package/src/components/sidebar.tsx +3 -3
- package/src/components/snippets.tsx +26 -9
- package/src/contexts/component-generics.tsx +10 -15
- package/src/contexts/docs.tsx +15 -4
- package/src/contexts/index.tsx +8 -5
- package/src/contexts/markdown.tsx +7 -6
- package/src/contexts/search.tsx +4 -5
- package/src/hooks/use-strict-context.tsx +16 -0
- package/src/languages/go.tsx +3 -3
- package/src/languages/http.tsx +31 -23
- package/src/languages/index.ts +7 -7
- package/src/languages/java.tsx +4 -4
- package/src/languages/python.tsx +12 -9
- package/src/languages/ruby.tsx +20 -13
- package/src/languages/typescript.tsx +18 -12
- package/src/markdown/index.ts +17 -12
- package/src/markdown/utils.ts +6 -3
- package/src/routing.ts +9 -9
- package/src/search/form.tsx +26 -24
- package/src/search/indexer.ts +17 -15
- package/src/search/mcp.ts +8 -8
- package/src/search/printer.tsx +1 -1
- package/src/search/providers/algolia.ts +5 -5
- package/src/search/providers/fuse.ts +4 -4
- package/src/search/providers/pagefind.ts +1 -1
- package/src/search/providers/walker.ts +5 -3
- package/src/search/results.tsx +7 -6
- package/src/search/types.ts +2 -2
- package/src/styles/main.css +2 -1
- package/src/utils.ts +9 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import { TSAST } from '@stainless/sdk-json';
|
|
3
3
|
import { useDeclaration, useLanguage, useLanguageComponents, useSpec } from '../contexts';
|
|
4
4
|
import { useComponents } from '../contexts/use-components';
|
|
5
5
|
import style from '../style';
|
|
@@ -13,7 +13,7 @@ const ComplexTypes: Record<string, string> = {
|
|
|
13
13
|
TSTypeArray: 'array',
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const constStyle = {
|
|
16
|
+
const constStyle: Record<string, string> = {
|
|
17
17
|
string: style.LiteralString,
|
|
18
18
|
number: style.LiteralNumeric,
|
|
19
19
|
boolean: style.LiteralBoolean,
|
|
@@ -66,17 +66,23 @@ function TypeParams({ params }: { params?: TSAST.TSTypeParameter[] }) {
|
|
|
66
66
|
function TypePreview({ path }: { path: string }) {
|
|
67
67
|
const spec = useSpec();
|
|
68
68
|
const language = useLanguage();
|
|
69
|
-
const decl = useDeclaration(path);
|
|
69
|
+
const decl = useDeclaration(path, false);
|
|
70
70
|
const { Join } = useComponents();
|
|
71
71
|
|
|
72
|
-
if (
|
|
72
|
+
if (
|
|
73
|
+
!(decl && 'children' in decl && decl.children && decl.children.length > 0) ||
|
|
74
|
+
(decl && 'type' in decl && 'kind' in decl['type'] && decl['type']['kind'] === 'TSTypeUnion')
|
|
75
|
+
)
|
|
73
76
|
return;
|
|
74
77
|
|
|
75
|
-
const items = decl.children.map((prop, key) =>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
const items = decl.children.map((prop, key) => {
|
|
79
|
+
const p = spec?.decls?.[language]?.[prop];
|
|
80
|
+
return (
|
|
81
|
+
<span key={key} className={style.TypePropertyName}>
|
|
82
|
+
<span className={style.TextIdentifier}>{p && 'key' in p ? p['key'] : null}</span>
|
|
83
|
+
</span>
|
|
84
|
+
);
|
|
85
|
+
});
|
|
80
86
|
|
|
81
87
|
return (
|
|
82
88
|
<span className={style.TypePreview} data-stldocs-type-preview="properties">
|
|
@@ -146,7 +152,7 @@ export function Type({ type }: TypeProps) {
|
|
|
146
152
|
|
|
147
153
|
return (
|
|
148
154
|
<span className={style.Type}>
|
|
149
|
-
<SDKReference stainlessPath={type.$ref}>{name}</SDKReference>
|
|
155
|
+
<SDKReference stainlessPath={type.$ref!}>{name}</SDKReference>
|
|
150
156
|
{params && params.length > 0 && (
|
|
151
157
|
<>
|
|
152
158
|
<span className={style.TypeBracket}>{'<'}</span>
|
|
@@ -156,7 +162,7 @@ export function Type({ type }: TypeProps) {
|
|
|
156
162
|
<span className={style.TypeBracket}>{'>'}</span>
|
|
157
163
|
</>
|
|
158
164
|
)}
|
|
159
|
-
<TypePreview path={type.$ref} />
|
|
165
|
+
<TypePreview path={type.$ref!} />
|
|
160
166
|
</span>
|
|
161
167
|
);
|
|
162
168
|
}
|
|
@@ -274,7 +280,7 @@ export function MethodSignature({ decl }: MethodSignatureProps) {
|
|
|
274
280
|
|
|
275
281
|
export type PropertyProps = {
|
|
276
282
|
decl: TSAST.TSDeclaration;
|
|
277
|
-
children
|
|
283
|
+
children: PropertyFn;
|
|
278
284
|
};
|
|
279
285
|
|
|
280
286
|
export function Property({ decl, children }: PropertyProps) {
|
package/src/markdown/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import Markdoc from '@markdoc/markdoc';
|
|
|
2
2
|
import * as md from './md';
|
|
3
3
|
import { EnvironmentType, getDecl, getSnippet, stripMarkup } from './utils';
|
|
4
4
|
import * as printer from '../search/printer';
|
|
5
|
-
import type * as SDKJSON from '
|
|
5
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
6
6
|
import type { Node } from '@markdoc/markdoc';
|
|
7
7
|
|
|
8
8
|
export function declaration(env: EnvironmentType, decl: SDKJSON.DeclarationNode) {
|
|
@@ -15,20 +15,20 @@ function renderChildren(env: EnvironmentType, children: SDKJSON.ID[], nesting: s
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function renderDecl(env: EnvironmentType, path: string, nesting: string[] = []) {
|
|
18
|
-
const decl = getDecl(env, path)
|
|
18
|
+
const decl = getDecl(env, path)!;
|
|
19
19
|
const item = md.item(declaration(env, decl));
|
|
20
20
|
|
|
21
|
-
const hasChildren = 'children' in decl && decl.children.length > 0;
|
|
22
|
-
const showModelProps = !decl['modelPath'] || env.options.includeModelProperties;
|
|
21
|
+
const hasChildren = 'children' in decl && decl.children && decl.children.length > 0;
|
|
22
|
+
const showModelProps = !('modelPath' in decl && decl['modelPath']) || env.options.includeModelProperties;
|
|
23
23
|
|
|
24
24
|
if ('docstring' in decl && decl.docstring) item.children.push(...md.parse(decl.docstring));
|
|
25
25
|
if (hasChildren && showModelProps && !nesting.includes(path))
|
|
26
|
-
item.push(renderChildren(env, decl.children, [...nesting, path]));
|
|
26
|
+
item.push(renderChildren(env, decl.children ?? [], [...nesting, path]));
|
|
27
27
|
|
|
28
28
|
return item;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function renderMethod(env: EnvironmentType, method: SDKJSON.Method) {
|
|
31
|
+
function renderMethod(env: EnvironmentType, method: SDKJSON.Method): Node[] {
|
|
32
32
|
const decl = getDecl(env, method.stainlessPath);
|
|
33
33
|
|
|
34
34
|
if (!decl)
|
|
@@ -41,11 +41,11 @@ function renderMethod(env: EnvironmentType, method: SDKJSON.Method) {
|
|
|
41
41
|
];
|
|
42
42
|
|
|
43
43
|
const signature = printer.methodSignature(env.language, decl);
|
|
44
|
-
const [httpMethod, endpoint] = method.endpoint.split(' ');
|
|
44
|
+
const [httpMethod, endpoint] = method.endpoint.split(' ') as [string, string];
|
|
45
45
|
|
|
46
46
|
const output = [
|
|
47
47
|
md.heading(2, method.title),
|
|
48
|
-
env.language === 'http' ?
|
|
48
|
+
...(env.language === 'http' ? [] : [md.paragraph(md.code(stripMarkup(signature)))]),
|
|
49
49
|
md.paragraph(md.strong(md.text(httpMethod)), md.text(' '), md.code(endpoint)),
|
|
50
50
|
];
|
|
51
51
|
|
|
@@ -54,7 +54,7 @@ function renderMethod(env: EnvironmentType, method: SDKJSON.Method) {
|
|
|
54
54
|
if ('paramsChildren' in decl && Array.isArray(decl.paramsChildren) && decl.paramsChildren.length > 0)
|
|
55
55
|
output.push(md.heading(3, 'Parameters'), renderChildren(env, decl.paramsChildren));
|
|
56
56
|
|
|
57
|
-
if ('responseChildren' in decl && decl.responseChildren.length > 0)
|
|
57
|
+
if ('responseChildren' in decl && decl.responseChildren && decl.responseChildren.length > 0)
|
|
58
58
|
output.push(md.heading(3, 'Returns'), renderChildren(env, decl.responseChildren));
|
|
59
59
|
|
|
60
60
|
const snippet = getSnippet(env, method.stainlessPath);
|
|
@@ -67,7 +67,7 @@ function renderModel(env: EnvironmentType, model: SDKJSON.Model) {
|
|
|
67
67
|
return [md.heading(3, model.title), md.list(renderDecl(env, `${model.stainlessPath} > (schema)`))];
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
function renderResource(env: EnvironmentType, resource: SDKJSON.Resource) {
|
|
70
|
+
function renderResource(env: EnvironmentType, resource: SDKJSON.Resource): Node[] {
|
|
71
71
|
const methods = Object.values(resource.methods)
|
|
72
72
|
.filter((method) => getDecl(env, method.stainlessPath))
|
|
73
73
|
.flatMap((method) => renderMethod(env, method));
|
|
@@ -82,11 +82,16 @@ function renderResource(env: EnvironmentType, resource: SDKJSON.Resource) {
|
|
|
82
82
|
|
|
83
83
|
if (!env.options.renderNestedResources) return doc;
|
|
84
84
|
|
|
85
|
-
const children = Object.values(resource.subresources).
|
|
85
|
+
const children = Object.values(resource.subresources ?? {}).flatMap((resource) =>
|
|
86
|
+
renderResource(env, resource),
|
|
87
|
+
);
|
|
86
88
|
return [...doc, ...children];
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
export function render(
|
|
91
|
+
export function render(
|
|
92
|
+
env: EnvironmentType,
|
|
93
|
+
node: SDKJSON.Resource | SDKJSON.Method | SDKJSON.Model,
|
|
94
|
+
): Node[] {
|
|
90
95
|
switch (node.kind) {
|
|
91
96
|
case 'resource':
|
|
92
97
|
return renderResource(env, node);
|
package/src/markdown/utils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser } from 'htmlparser2';
|
|
2
2
|
import type { DocsLanguage } from '../routing';
|
|
3
|
-
import type * as SDKJSON from '
|
|
3
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
4
4
|
import type { TransformRequestSnippetFn } from '../components/sdk';
|
|
5
5
|
|
|
6
6
|
export type EnvironmentType = {
|
|
@@ -19,7 +19,10 @@ export function getDecl(env: EnvironmentType, path: string) {
|
|
|
19
19
|
const decl = env.spec?.decls?.[env.language]?.[path];
|
|
20
20
|
|
|
21
21
|
if (decl?.kind?.endsWith('Reference')) {
|
|
22
|
-
const refId =
|
|
22
|
+
const refId =
|
|
23
|
+
'type' in decl && typeof decl['type'] === 'object' && '$ref' in decl['type']
|
|
24
|
+
? decl['type']['$ref']
|
|
25
|
+
: null;
|
|
23
26
|
if (refId === path) return decl;
|
|
24
27
|
if (refId) return getDecl(env, refId);
|
|
25
28
|
}
|
|
@@ -28,7 +31,7 @@ export function getDecl(env: EnvironmentType, path: string) {
|
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
export function getSnippet(env: EnvironmentType, path: string) {
|
|
31
|
-
let snippet = env.spec?.snippets?.[`${env.language}.default`]?.[path];
|
|
34
|
+
let snippet = env.spec?.snippets?.[`${env.language}.default` as SDKJSON.SnippetLanguage]?.[path];
|
|
32
35
|
if (typeof snippet === 'string' && env.transforms?.transformRequestSnippet) {
|
|
33
36
|
snippet = env.transforms.transformRequestSnippet({ snippet, language: env.language });
|
|
34
37
|
}
|
package/src/routing.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type * as SDKJSON from '
|
|
1
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
2
2
|
|
|
3
3
|
export const Languages = [
|
|
4
4
|
'http',
|
|
@@ -56,10 +56,10 @@ export type ParsedStainlessPath = ReturnType<typeof parseStainlessPath>;
|
|
|
56
56
|
export function parseStainlessPath(stainlessPath: string) {
|
|
57
57
|
const match = stainlessPath.match(StainlessPathPattern);
|
|
58
58
|
|
|
59
|
-
if (!match) return null;
|
|
59
|
+
if (!match?.groups) return null;
|
|
60
60
|
|
|
61
61
|
return {
|
|
62
|
-
resource: match.groups.resource
|
|
62
|
+
resource: match.groups.resource?.split('.') ?? null,
|
|
63
63
|
method: match.groups.method ?? null,
|
|
64
64
|
model: match.groups.model ?? null,
|
|
65
65
|
routable: match.groups.model ? match[1] : match[0],
|
|
@@ -72,7 +72,7 @@ export function trimStainlessPath(stainlessPath: string) {
|
|
|
72
72
|
|
|
73
73
|
export function getResource(stainlessPath: string) {
|
|
74
74
|
const parsed = parseStainlessPath(stainlessPath);
|
|
75
|
-
return parsed?.resource[0];
|
|
75
|
+
return parsed?.resource?.[0];
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
export function parseRoute(
|
|
@@ -119,7 +119,7 @@ export function generateRoute(basePath: string, language: string, stainlessPath:
|
|
|
119
119
|
const path = [basePath.endsWith('/') ? basePath.slice(0, -1) : basePath];
|
|
120
120
|
if (language && language !== DefaultLanguage) path.push(language);
|
|
121
121
|
|
|
122
|
-
const resources = parsedPath.resource
|
|
122
|
+
const resources = parsedPath.resource!.flatMap((name, index) => [
|
|
123
123
|
index > 0 ? 'subresources' : 'resources',
|
|
124
124
|
name,
|
|
125
125
|
]);
|
|
@@ -130,7 +130,7 @@ export function generateRoute(basePath: string, language: string, stainlessPath:
|
|
|
130
130
|
|
|
131
131
|
if (parsedPath.method) path.push('methods', parsedPath.method);
|
|
132
132
|
|
|
133
|
-
return stainlessPath.length > parsedPath.routable
|
|
133
|
+
return stainlessPath.length > parsedPath.routable!.length
|
|
134
134
|
? `${path.join('/')}#${encodeURIComponent(stainlessPath)}`
|
|
135
135
|
: path.join('/');
|
|
136
136
|
}
|
|
@@ -203,7 +203,7 @@ export function generateRouteList({
|
|
|
203
203
|
|
|
204
204
|
type ResourceOrMethod = SDKJSON.Resource | SDKJSON.Method;
|
|
205
205
|
|
|
206
|
-
export function findNavigationPath(items: ResourceOrMethod[], target: string) {
|
|
206
|
+
export function findNavigationPath(items: ResourceOrMethod[], target: string): string[] | undefined {
|
|
207
207
|
for (const item of Object.values(items)) {
|
|
208
208
|
if (item.stainlessPath === target) return [item.stainlessPath];
|
|
209
209
|
if (item.kind === 'http_method') continue;
|
|
@@ -217,9 +217,9 @@ export function findNavigationPath(items: ResourceOrMethod[], target: string) {
|
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
export function expandToElement(el: HTMLElement) {
|
|
220
|
+
export function expandToElement(el: HTMLElement | null) {
|
|
221
221
|
while (el) {
|
|
222
|
-
if (el
|
|
222
|
+
if (el instanceof HTMLDetailsElement) el.open = true;
|
|
223
223
|
el = el.parentElement;
|
|
224
224
|
}
|
|
225
225
|
}
|
package/src/search/form.tsx
CHANGED
|
@@ -14,36 +14,36 @@ export function SearchForm() {
|
|
|
14
14
|
const language = useLanguage();
|
|
15
15
|
const { onSelect, pageFind } = useSearchContext();
|
|
16
16
|
|
|
17
|
-
const [results, setResults] = React.useState<ResultData>(null);
|
|
17
|
+
const [results, setResults] = React.useState<ResultData>(null!);
|
|
18
18
|
const [filterKind, setFilterKind] = React.useState<QueryKindsType>('all');
|
|
19
19
|
const [searchQuery, setSearchQuery] = React.useState<string>('');
|
|
20
20
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
21
21
|
|
|
22
|
-
async function performSearch() {
|
|
23
|
-
const guideLimit = filterKind === 'guide' ? 25 : 5;
|
|
24
|
-
const kind = ['all', 'guide'].includes(filterKind) ? undefined : filterKind;
|
|
25
|
-
|
|
26
|
-
const [guideResults, apiResults] = await Promise.all([
|
|
27
|
-
pageFind ? guideSearch(pageFind, searchQuery, guideLimit) : [],
|
|
28
|
-
search({ query: searchQuery, kind, language }),
|
|
29
|
-
]);
|
|
30
|
-
|
|
31
|
-
setResults({
|
|
32
|
-
items: filterKind === 'guide' ? guideResults : [...guideResults, ...apiResults.hits],
|
|
33
|
-
counts: {
|
|
34
|
-
...apiResults.facets?.['kind'],
|
|
35
|
-
guide: guideResults.length,
|
|
36
|
-
all: apiResults.nbHits,
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
22
|
function clearInput() {
|
|
42
23
|
setSearchQuery('');
|
|
43
24
|
inputRef?.current?.focus();
|
|
44
25
|
}
|
|
45
26
|
|
|
46
|
-
React.useEffect(() =>
|
|
27
|
+
React.useEffect(() => {
|
|
28
|
+
(async function performSearch() {
|
|
29
|
+
const guideLimit = filterKind === 'guide' ? 25 : 5;
|
|
30
|
+
const kind = ['all', 'guide'].includes(filterKind) ? undefined : filterKind;
|
|
31
|
+
|
|
32
|
+
const [guideResults, apiResults] = await Promise.all([
|
|
33
|
+
pageFind ? guideSearch(pageFind, searchQuery, guideLimit) : [],
|
|
34
|
+
search({ query: searchQuery, kind, language }),
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
setResults({
|
|
38
|
+
items: filterKind === 'guide' ? guideResults : [...guideResults, ...(apiResults?.hits ?? [])],
|
|
39
|
+
counts: {
|
|
40
|
+
...apiResults?.facets?.['kind'],
|
|
41
|
+
guide: guideResults.length,
|
|
42
|
+
all: apiResults?.nbHits,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
})();
|
|
46
|
+
}, [searchQuery, filterKind, language, pageFind, search]);
|
|
47
47
|
|
|
48
48
|
return (
|
|
49
49
|
<div className={style.SearchForm}>
|
|
@@ -72,7 +72,9 @@ export function SearchForm() {
|
|
|
72
72
|
itemDelegate={(item) =>
|
|
73
73
|
'kind' in item ? <SearchResult result={item} /> : <GuideResult result={item} />
|
|
74
74
|
}
|
|
75
|
-
onSelectListItem={(item) =>
|
|
75
|
+
onSelectListItem={(item) =>
|
|
76
|
+
onSelect?.((item as any)['data']?.['url'] ?? (item as any)['stainlessPath'])
|
|
77
|
+
}
|
|
76
78
|
/>
|
|
77
79
|
</div>
|
|
78
80
|
);
|
|
@@ -81,7 +83,7 @@ export function SearchForm() {
|
|
|
81
83
|
export type SearchFilterProps = {
|
|
82
84
|
results: ResultData;
|
|
83
85
|
filterKind: QueryKindsType;
|
|
84
|
-
onChange: (filterKind
|
|
86
|
+
onChange: (filterKind: QueryKindsType) => void;
|
|
85
87
|
};
|
|
86
88
|
|
|
87
89
|
export function SearchFilter({ results, filterKind, onChange }: SearchFilterProps) {
|
|
@@ -111,7 +113,7 @@ export type SearchModalProps = {
|
|
|
111
113
|
};
|
|
112
114
|
|
|
113
115
|
export function SearchModal({ id, open: isOpen }: SearchModalProps) {
|
|
114
|
-
const [open, setOpen] = React.useState<boolean>(isOpen);
|
|
116
|
+
const [open, setOpen] = React.useState<boolean>(isOpen ?? false);
|
|
115
117
|
|
|
116
118
|
return (
|
|
117
119
|
<div
|
package/src/search/indexer.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { generateRoute, Languages, parseStainlessPath, walkTree } from '../routing';
|
|
2
2
|
import * as printer from './printer';
|
|
3
|
-
import type * as SDKJSON from '
|
|
3
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
4
4
|
import type { IndexEntry } from './types';
|
|
5
5
|
import { renderMarkdown } from '../markdown';
|
|
6
6
|
|
|
@@ -93,8 +93,8 @@ export function* generateChatIndex(spec: SDKJSON.Spec) {
|
|
|
93
93
|
summary,
|
|
94
94
|
description,
|
|
95
95
|
stainlessPath,
|
|
96
|
-
qualified: decl['qualified'],
|
|
97
|
-
ident: decl['ident'],
|
|
96
|
+
qualified: 'qualified' in decl ? decl['qualified'] : undefined,
|
|
97
|
+
ident: 'ident' in decl ? decl['ident'] : undefined,
|
|
98
98
|
content: chunk,
|
|
99
99
|
url: generateRoute('docs://BASE_PATH', language, stainlessPath),
|
|
100
100
|
};
|
|
@@ -105,7 +105,7 @@ export function* generateChatIndex(spec: SDKJSON.Spec) {
|
|
|
105
105
|
|
|
106
106
|
export function* generateIndex(
|
|
107
107
|
spec: SDKJSON.Spec,
|
|
108
|
-
renderMarkdownFn?: (string
|
|
108
|
+
renderMarkdownFn?: (_: string) => string | null,
|
|
109
109
|
includeTypes?: boolean,
|
|
110
110
|
): Generator<IndexEntry> {
|
|
111
111
|
const parentCrumbs: Record<string, string[]> = {};
|
|
@@ -113,8 +113,8 @@ export function* generateIndex(
|
|
|
113
113
|
const { kind, name, title, stainlessPath } = data;
|
|
114
114
|
const common = { name, title, stainlessPath };
|
|
115
115
|
|
|
116
|
-
const parsedPath = parseStainlessPath(stainlessPath)
|
|
117
|
-
const crumbs = getResourceNames(parsedPath.resource
|
|
116
|
+
const parsedPath = parseStainlessPath(stainlessPath)!;
|
|
117
|
+
const crumbs = getResourceNames(parsedPath.resource!, spec.resources);
|
|
118
118
|
|
|
119
119
|
switch (kind) {
|
|
120
120
|
case 'resource':
|
|
@@ -144,7 +144,7 @@ export function* generateIndex(
|
|
|
144
144
|
if (!found) continue;
|
|
145
145
|
|
|
146
146
|
parentCrumbs[stainlessPath] = [...crumbs, title];
|
|
147
|
-
const qualified = found['qualified'];
|
|
147
|
+
const qualified = 'qualified' in found ? found['qualified'] : undefined;
|
|
148
148
|
const ident = qualified?.split('.')?.at(-1);
|
|
149
149
|
|
|
150
150
|
yield {
|
|
@@ -153,7 +153,9 @@ export function* generateIndex(
|
|
|
153
153
|
ident,
|
|
154
154
|
qualified,
|
|
155
155
|
language,
|
|
156
|
-
description:
|
|
156
|
+
description: data.description
|
|
157
|
+
? (renderMarkdownFn?.(data.description) ?? data.description)
|
|
158
|
+
: undefined,
|
|
157
159
|
endpoint: endpoint.slice(httpMethod.length).trim(),
|
|
158
160
|
httpMethod,
|
|
159
161
|
summary,
|
|
@@ -172,9 +174,9 @@ export function* generateIndex(
|
|
|
172
174
|
parentCrumbs[stainlessPath] = [...crumbs, title];
|
|
173
175
|
const schema = spec.decls[language]?.[`${stainlessPath} > (schema)`];
|
|
174
176
|
const children =
|
|
175
|
-
schema?.['children']
|
|
177
|
+
(schema && 'children' in schema ? schema?.['children'] : undefined)
|
|
176
178
|
?.map((childPath) => {
|
|
177
|
-
const child = spec.decls?.[language]?.[childPath];
|
|
179
|
+
const child = spec.decls?.[language]?.[childPath] as any;
|
|
178
180
|
return (
|
|
179
181
|
child?.['ident'] ??
|
|
180
182
|
child?.['name'] ??
|
|
@@ -192,7 +194,7 @@ export function* generateIndex(
|
|
|
192
194
|
children,
|
|
193
195
|
language,
|
|
194
196
|
priority: 2,
|
|
195
|
-
ident: schema?.['ident'],
|
|
197
|
+
ident: schema && 'ident' in schema ? schema?.['ident'] : undefined,
|
|
196
198
|
...common,
|
|
197
199
|
};
|
|
198
200
|
}
|
|
@@ -213,11 +215,11 @@ export function* generateIndex(
|
|
|
213
215
|
case 'HttpDeclProperty':
|
|
214
216
|
case 'TSDeclProperty':
|
|
215
217
|
{
|
|
216
|
-
const parsedPath = parseStainlessPath(decl.stainlessPath)
|
|
218
|
+
const parsedPath = parseStainlessPath(decl.stainlessPath)!;
|
|
217
219
|
const type = includeTypes === false ? undefined : printer.typeName(language, decl.type);
|
|
218
|
-
const name = decl['ident'] ?? decl['name'] ?? decl['key'];
|
|
220
|
+
const name: string = (decl as any)['ident'] ?? (decl as any)['name'] ?? (decl as any)['key'];
|
|
219
221
|
|
|
220
|
-
const parent = parentCrumbs[parsedPath.routable];
|
|
222
|
+
const parent = parentCrumbs[parsedPath.routable!];
|
|
221
223
|
// Filter out properties of non-routable response types
|
|
222
224
|
if (parent === undefined) continue;
|
|
223
225
|
|
|
@@ -232,7 +234,7 @@ export function* generateIndex(
|
|
|
232
234
|
name,
|
|
233
235
|
stainlessPath: decl.stainlessPath,
|
|
234
236
|
crumbs: [...parent, ...props],
|
|
235
|
-
docstring: renderMarkdownFn?.(decl.docstring) ?? decl.docstring,
|
|
237
|
+
docstring: decl.docstring ? (renderMarkdownFn?.(decl.docstring) ?? decl.docstring) : undefined,
|
|
236
238
|
type,
|
|
237
239
|
language,
|
|
238
240
|
priority: 3,
|
package/src/search/mcp.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { getResourceFromSpec } from '../utils';
|
|
|
5
5
|
import { buildIndex, search as fuseSearch } from './providers/fuse';
|
|
6
6
|
import type { IndexEntry, IndexMethod } from './types';
|
|
7
7
|
import natural from 'natural';
|
|
8
|
-
import type * as SDKJSON from '
|
|
8
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
9
9
|
|
|
10
10
|
type Item = IndexEntry & IndexMethod;
|
|
11
11
|
|
|
@@ -20,12 +20,12 @@ export function consolidate(results: IndexEntry[]) {
|
|
|
20
20
|
const methods = new Set<string>();
|
|
21
21
|
|
|
22
22
|
for (const entry of results) {
|
|
23
|
-
const parsed = parseStainlessPath(entry.stainlessPath)
|
|
24
|
-
if (parsed.method) methods.add(parsed.routable);
|
|
25
|
-
else resources.add(parsed.routable);
|
|
23
|
+
const parsed = parseStainlessPath(entry.stainlessPath)!;
|
|
24
|
+
if (parsed.method) methods.add(parsed.routable!);
|
|
25
|
+
else resources.add(parsed.routable!);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const filtered = Array.from(methods).filter((path) => !resources.has(path.split(' >').at(0)));
|
|
28
|
+
const filtered = Array.from(methods).filter((path) => !resources.has(path.split(' >').at(0)!));
|
|
29
29
|
return [...resources, ...filtered];
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -46,9 +46,9 @@ export function render(
|
|
|
46
46
|
|
|
47
47
|
const paths = consolidate(items);
|
|
48
48
|
const output = paths.map((entry) => {
|
|
49
|
-
const parsed = parseStainlessPath(entry)
|
|
50
|
-
const resource = getResourceFromSpec(parsed.resource
|
|
51
|
-
const target = parsed.method ? resource.methods[parsed.method] : resource;
|
|
49
|
+
const parsed = parseStainlessPath(entry)!;
|
|
50
|
+
const resource = getResourceFromSpec(parsed.resource!, spec)!;
|
|
51
|
+
const target = parsed.method ? resource.methods[parsed.method]! : resource;
|
|
52
52
|
const content = renderMarkdown(env, target);
|
|
53
53
|
return [entry, content];
|
|
54
54
|
});
|
package/src/search/printer.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
3
|
-
import type * as SDKJSON from '
|
|
3
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
4
4
|
import type { DocsLanguage } from '../routing';
|
|
5
5
|
|
|
6
6
|
import { DocsProvider, useLanguageComponents } from '../contexts';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { searchClient } from '@algolia/client-search';
|
|
2
2
|
import { generateChatIndex, generateIndex } from '../indexer';
|
|
3
3
|
import { SearchableAttributes, SearchableAttributesChat } from '../types';
|
|
4
|
-
import type * as SDKJSON from '
|
|
4
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
5
5
|
import type { ResultRecordType, SearchSettings, SearchParams, ResultType } from '../types';
|
|
6
6
|
|
|
7
7
|
export async function buildIndex(
|
|
@@ -9,7 +9,7 @@ export async function buildIndex(
|
|
|
9
9
|
indexName: string,
|
|
10
10
|
writeKey: string,
|
|
11
11
|
spec: SDKJSON.Spec,
|
|
12
|
-
renderMarkdown: (string
|
|
12
|
+
renderMarkdown: (_: string) => string | null,
|
|
13
13
|
): Promise<void> {
|
|
14
14
|
if (!appId || !indexName || !writeKey) return;
|
|
15
15
|
const objects = Array.from(generateIndex(spec, renderMarkdown));
|
|
@@ -22,7 +22,7 @@ export async function buildIndex(
|
|
|
22
22
|
highlightPostTag: '</mark>',
|
|
23
23
|
customRanking: ['asc(priority)'],
|
|
24
24
|
attributesForFaceting: ['language', 'kind'],
|
|
25
|
-
searchableAttributes: SearchableAttributes,
|
|
25
|
+
searchableAttributes: [...SearchableAttributes],
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
28
|
|
|
@@ -81,8 +81,8 @@ export async function search({
|
|
|
81
81
|
],
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
if ('hits' in results[0] && 'hits' in results[1]) {
|
|
84
|
+
if ('hits' in results[0]! && 'hits' in results[1]!) {
|
|
85
85
|
const [{ nbHits, facets }, { hits }] = results;
|
|
86
|
-
return { hits, nbHits, facets };
|
|
86
|
+
return { hits, nbHits: nbHits ?? 0, facets };
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -2,18 +2,18 @@ import Fuse, { FuseIndex } from 'fuse.js';
|
|
|
2
2
|
import { DocsLanguage } from '../../routing';
|
|
3
3
|
import { generateIndex } from '../indexer';
|
|
4
4
|
import { IndexEntry, SearchableAttributes } from '../types';
|
|
5
|
-
import type * as SDKJSON from '
|
|
5
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
6
6
|
|
|
7
7
|
export type FuseIndexData = { content: IndexEntry[]; index: FuseIndex<IndexEntry> };
|
|
8
8
|
|
|
9
9
|
export function buildIndex(spec: SDKJSON.Spec, language?: DocsLanguage): FuseIndexData {
|
|
10
|
-
const idx = Array.from(generateIndex(spec,
|
|
10
|
+
const idx = Array.from(generateIndex(spec, undefined, false));
|
|
11
11
|
const content = language ? idx.filter((entry) => entry.language === language) : idx;
|
|
12
|
-
const index = Fuse.createIndex(SearchableAttributes, content);
|
|
12
|
+
const index = Fuse.createIndex([...SearchableAttributes], content);
|
|
13
13
|
return { content, index };
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export function search({ content, index }: FuseIndexData, query: string, limit: number = 100) {
|
|
17
|
-
const fuse = new Fuse(content, { keys: SearchableAttributes }, index);
|
|
17
|
+
const fuse = new Fuse(content, { keys: [...SearchableAttributes] }, index);
|
|
18
18
|
return fuse.search(query).slice(0, limit);
|
|
19
19
|
}
|
|
@@ -13,5 +13,5 @@ export async function guideSearch(
|
|
|
13
13
|
const index = await loadPagefind(loadPath);
|
|
14
14
|
const response = await index.search(query);
|
|
15
15
|
const items = limit ? response.results.slice(0, limit) : response.results;
|
|
16
|
-
return Promise.all(items.map((result) => result.data().then((data) => ({ ...result, data }))));
|
|
16
|
+
return Promise.all(items.map((result: any) => result.data().then((data: any) => ({ ...result, data }))));
|
|
17
17
|
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import { DocsLanguage } from '../../routing';
|
|
2
2
|
import { generateIndex } from '../indexer';
|
|
3
3
|
import { IndexEntry, SearchableAttributes } from '../types';
|
|
4
|
-
import type * as SDKJSON from '
|
|
4
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
5
5
|
|
|
6
6
|
export function buildIndex(spec: SDKJSON.Spec) {
|
|
7
|
-
return generateIndex(spec,
|
|
7
|
+
return generateIndex(spec, undefined, false);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
function* findEntryInIndex(index: Generator<IndexEntry>, language: string, query: string) {
|
|
11
11
|
for (const entry of index) {
|
|
12
12
|
if (entry.language !== language) continue;
|
|
13
13
|
for (const attr of SearchableAttributes) {
|
|
14
|
-
|
|
14
|
+
const attr_ = attr in entry ? (attr as keyof typeof entry) : null;
|
|
15
|
+
if (attr_ && entry[attr_] && typeof entry[attr_] === 'string' && entry[attr_].includes(query))
|
|
16
|
+
yield entry;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
17
19
|
}
|
package/src/search/results.tsx
CHANGED
|
@@ -125,11 +125,12 @@ export function SearchResultContent({ result }: SearchResultProps) {
|
|
|
125
125
|
);
|
|
126
126
|
|
|
127
127
|
case 'model': {
|
|
128
|
-
const properties =
|
|
129
|
-
|
|
130
|
-
{
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
const properties =
|
|
129
|
+
result.children?.map((child, index) => (
|
|
130
|
+
<span key={index} className={style.TextIdentifier}>
|
|
131
|
+
{child}
|
|
132
|
+
</span>
|
|
133
|
+
)) ?? [];
|
|
133
134
|
|
|
134
135
|
return (
|
|
135
136
|
<div className={style.Property} data-stldocs-language={language}>
|
|
@@ -168,7 +169,7 @@ export function SearchResultContent({ result }: SearchResultProps) {
|
|
|
168
169
|
<Highlight result={result} name="name" />
|
|
169
170
|
</span>
|
|
170
171
|
<span className={style.PropertyTypeName}>
|
|
171
|
-
<span dangerouslySetInnerHTML={{ __html: result.type }} />
|
|
172
|
+
<span dangerouslySetInnerHTML={{ __html: result.type ?? '' }} />
|
|
172
173
|
</span>
|
|
173
174
|
</div>
|
|
174
175
|
{result.docstring && (
|
package/src/search/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type * as SDKJSON from '
|
|
1
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
2
2
|
import { DocsLanguage } from '../routing';
|
|
3
3
|
|
|
4
4
|
export type SearchSettings = {
|
|
@@ -58,7 +58,7 @@ export const SearchableAttributes = [
|
|
|
58
58
|
'summary',
|
|
59
59
|
'description',
|
|
60
60
|
'docstring',
|
|
61
|
-
];
|
|
61
|
+
] as const;
|
|
62
62
|
|
|
63
63
|
export const SearchableAttributesChat = [
|
|
64
64
|
'title',
|
package/src/styles/main.css
CHANGED