Skip to content

Commit 28ad795

Browse files
mydeaLms24inventarSarah
authored
feat: Add APIs page for JavaScript (#12605)
--------- Co-authored-by: Lukas Stracke <[email protected]> Co-authored-by: Sarah Mischinger <[email protected]>
1 parent 80c4df2 commit 28ad795

File tree

14 files changed

+1343
-152
lines changed

14 files changed

+1343
-152
lines changed

docs/platforms/javascript/common/apis.mdx

Lines changed: 993 additions & 0 deletions
Large diffs are not rendered by default.

docs/platforms/javascript/common/enriching-events/scopes/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Sentry.withScope((scope) => {
7777
Sentry.captureException(new Error("my other error"));
7878
```
7979

80-
You can access the current scope via `Sentry.getCurrentScope()`, but usually you should use `Sentry.withScope()` to interact with local scopes instead.
80+
You can access the current scope via `Sentry.getCurrentScope()`, but in most cases you should not use this API, but instead use `withScope` to generate and access a local scope. There are no guarantees about the consistency of `getCurrentScope` across different parts of your application, as scope forking may happen under the hood at various points.
8181

8282
## How Scope Data is Applied to Events
8383

docs/platforms/javascript/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ platformTitle: JavaScript
33
caseStyle: camelCase
44
supportLevel: production
55
sdk: 'sentry.javascript.browser'
6+
language: typescript
67
categories:
78
- javascript
89
- browser

src/components/apiExamples/apiExamples.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
'use client';
22

33
import {Fragment, useEffect, useState} from 'react';
4-
import {jsx, jsxs} from 'react/jsx-runtime';
54
import {Clipboard} from 'react-feather';
6-
import {toJsxRuntime} from 'hast-util-to-jsx-runtime';
7-
import {Nodes} from 'hastscript/lib/create-h';
8-
import bash from 'refractor/lang/bash.js';
9-
import json from 'refractor/lang/json.js';
10-
import {refractor} from 'refractor/lib/core.js';
115

126
import {type API} from 'sentry-docs/build/resolveOpenAPI';
137

@@ -16,9 +10,7 @@ import styles from './apiExamples.module.scss';
1610

1711
import {CodeBlock} from '../codeBlock';
1812
import {CodeTabs} from '../codeTabs';
19-
20-
refractor.register(bash);
21-
refractor.register(json);
13+
import {codeToJsx} from '../highlightCode';
2214

2315
const strFormat = (str: string) => {
2416
const s = str.trim();
@@ -32,10 +24,6 @@ type Props = {
3224
api: API;
3325
};
3426

35-
const codeToJsx = (code: string, lang = 'json') => {
36-
return toJsxRuntime(refractor.highlight(code, lang) as Nodes, {Fragment, jsx, jsxs});
37-
};
38-
3927
export function ApiExamples({api}: Props) {
4028
const apiExample = [
4129
`curl ${api.server}${api.apiPath}`,

src/components/callout/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555

5656
.callout-content {
5757
min-width: 0;
58+
flex-grow: 1;
5859
}
5960

6061
.callout-info {

src/components/highlightCode.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {Fragment} from 'react';
2+
import {jsx, jsxs} from 'react/jsx-runtime';
3+
import {toJsxRuntime} from 'hast-util-to-jsx-runtime';
4+
import {Nodes} from 'hastscript/lib/create-h';
5+
import bash from 'refractor/lang/bash.js';
6+
import json from 'refractor/lang/json.js';
7+
import typescript from 'refractor/lang/typescript.js';
8+
import {refractor} from 'refractor/lib/core.js';
9+
10+
refractor.register(bash);
11+
refractor.register(json);
12+
refractor.register(typescript);
13+
14+
// If a new language should be supported, add it here and register it in refractor above
15+
export const SUPPORTED_LANGUAGES = ['bash', 'json', 'typescript'];
16+
17+
export function codeToJsx(code: string, lang = 'json') {
18+
if (!SUPPORTED_LANGUAGES.includes(lang)) {
19+
// eslint-disable-next-line no-console
20+
console.error(`Unsupported language for syntax highlighting: ${lang}`);
21+
}
22+
return toJsxRuntime(refractor.highlight(code, lang) as Nodes, {Fragment, jsx, jsxs});
23+
}

src/components/sdkApi.tsx

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import {Fragment} from 'react';
2+
3+
import {getCurrentPlatform} from 'sentry-docs/docTree';
4+
import {serverContext} from 'sentry-docs/serverContext';
5+
import {PlatformCategory} from 'sentry-docs/types';
6+
7+
import {Expandable} from './expandable';
8+
import {codeToJsx} from './highlightCode';
9+
import {SdkDefinition} from './sdkDefinition';
10+
import {getPlatformHints} from './sdkOption';
11+
12+
export interface ParameterDef {
13+
name: string;
14+
type: string | ObjectParameterDef;
15+
defaultValue?: string;
16+
description?: string;
17+
required?: boolean;
18+
}
19+
20+
type ObjectParameterDef = {
21+
properties: ParameterDef[];
22+
name?: string;
23+
};
24+
25+
type Props = {
26+
name: string;
27+
parameters: ParameterDef[];
28+
signature: string;
29+
categorySupported?: PlatformCategory[];
30+
children?: React.ReactNode;
31+
language?: string;
32+
};
33+
34+
export function SdkApi({
35+
name,
36+
children,
37+
signature,
38+
parameters = [],
39+
language,
40+
categorySupported = [],
41+
}: Props) {
42+
const {rootNode, path} = serverContext();
43+
const platform = getCurrentPlatform(rootNode, path);
44+
const lang = language || platform?.language || 'typescript';
45+
46+
const {showBrowserOnly, showServerLikeOnly} = getPlatformHints(categorySupported);
47+
48+
return (
49+
<SdkDefinition name={name} categorySupported={categorySupported}>
50+
{showBrowserOnly && <div className="italic text-sm">Only available on Client</div>}
51+
{showServerLikeOnly && (
52+
<div className="italic text-sm">Only available on Server</div>
53+
)}
54+
55+
<pre className="mt-2 mb-2 text-sm">{codeToJsx(signature, lang)}</pre>
56+
57+
{parameters.length ? (
58+
<Expandable title="Parameters">
59+
<div className="space-y-3">
60+
{parameters.map(param => (
61+
<ApiParameterDef key={param.name} language={lang} {...param} />
62+
))}
63+
</div>
64+
</Expandable>
65+
) : null}
66+
67+
{children}
68+
</SdkDefinition>
69+
);
70+
}
71+
72+
function ApiParameterDef({
73+
name,
74+
type,
75+
description,
76+
required,
77+
language,
78+
}: ParameterDef & {language: string}) {
79+
return (
80+
<div className="space-y-1">
81+
<div className="font-bold m-0">
82+
{name}
83+
{required ? <span className="text-red">*</span> : null}
84+
</div>
85+
<div className="space-y-1">
86+
<div className="flex">
87+
{typeof type === 'string' ? (
88+
<pre className="m-0 pt-1 pb-1 text-sm">
89+
<code>{codeToJsx(type, language)}</code>
90+
</pre>
91+
) : (
92+
<pre className="m-0 pt-1 pb-1 text-sm">
93+
<NestedObject
94+
name={type.name}
95+
objProps={type.properties}
96+
language={language}
97+
/>
98+
</pre>
99+
)}
100+
</div>
101+
102+
{description ? <p className="m-0">{description}</p> : null}
103+
</div>
104+
</div>
105+
);
106+
}
107+
108+
function NestedObject({
109+
name,
110+
objProps,
111+
language,
112+
}: {
113+
language: string;
114+
objProps: ParameterDef[];
115+
name?: string;
116+
}) {
117+
// NOTE: For now, we always render the nested object in typescript
118+
119+
return (
120+
<div>
121+
<div>
122+
<code>
123+
{name ? name : 'Object'} {'{'}
124+
</code>
125+
</div>
126+
127+
<div className="flex flex-col gap-2 pl-4">
128+
{objProps.map(prop => (
129+
<div key={prop.name}>
130+
{prop.description && (
131+
<div>
132+
<code>{codeToJsx(`// ${prop.description}`, 'typescript')}</code>
133+
</div>
134+
)}
135+
<div>
136+
{typeof prop.type === 'string' ? (
137+
<Fragment>
138+
<code>
139+
{prop.name}
140+
{!prop.required ? '?' : ''}:{' '}
141+
</code>
142+
<code>{codeToJsx(prop.type, 'typescript')},</code>
143+
</Fragment>
144+
) : (
145+
<NestedObject
146+
name={`${prop.name}${!prop.required ? '?' : ''}: ${prop.type.name || 'Object'}`}
147+
objProps={prop.type.properties}
148+
language={language}
149+
/>
150+
)}
151+
</div>
152+
</div>
153+
))}
154+
</div>
155+
<div>{'}'}</div>
156+
</div>
157+
);
158+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {PlatformCategory} from 'sentry-docs/types';
2+
3+
import styles from './style.module.scss';
4+
5+
import {PlatformCategorySection} from '../platformCategorySection';
6+
7+
type Props = {
8+
name: string;
9+
categorySupported?: PlatformCategory[];
10+
children?: React.ReactNode;
11+
};
12+
13+
export function SdkDefinition({name, children, categorySupported = []}: Props) {
14+
return (
15+
<PlatformCategorySection supported={categorySupported}>
16+
<div className={styles['sdk-config-option']}>
17+
<h3 id={name} aria-label={name} data-sdk-option>
18+
<a href={`#${name}`}>
19+
<svg
20+
className="anchorlink before"
21+
viewBox="0 0 24 24"
22+
xmlns="http://www.w3.org/2000/svg"
23+
width="16"
24+
height="16"
25+
>
26+
<path
27+
d="M9.199 13.599a5.99 5.99 0 0 0 3.949 2.345 5.987 5.987 0 0 0 5.105-1.702l2.995-2.994a5.992 5.992 0 0 0 1.695-4.285 5.976 5.976 0 0 0-1.831-4.211 5.99 5.99 0 0 0-6.431-1.242 6.003 6.003 0 0 0-1.905 1.24l-1.731 1.721a.999.999 0 1 0 1.41 1.418l1.709-1.699a3.985 3.985 0 0 1 2.761-1.123 3.975 3.975 0 0 1 2.799 1.122 3.997 3.997 0 0 1 .111 5.644l-3.005 3.006a3.982 3.982 0 0 1-3.395 1.126 3.987 3.987 0 0 1-2.632-1.563A1 1 0 0 0 9.201 13.6zm5.602-3.198a5.99 5.99 0 0 0-3.949-2.345 5.987 5.987 0 0 0-5.105 1.702l-2.995 2.994a5.992 5.992 0 0 0-1.695 4.285 5.976 5.976 0 0 0 1.831 4.211 5.99 5.99 0 0 0 6.431 1.242 6.003 6.003 0 0 0 1.905-1.24l1.723-1.723a.999.999 0 1 0-1.414-1.414L9.836 19.81a3.985 3.985 0 0 1-2.761 1.123 3.975 3.975 0 0 1-2.799-1.122 3.997 3.997 0 0 1-.111-5.644l3.005-3.006a3.982 3.982 0 0 1 3.395-1.126 3.987 3.987 0 0 1 2.632 1.563 1 1 0 0 0 1.602-1.198z"
28+
fill="currentColor"
29+
/>
30+
</svg>
31+
{name}
32+
</a>
33+
</h3>
34+
35+
<div className={styles['sdk-config-option-details']}>{children}</div>
36+
</div>
37+
</PlatformCategorySection>
38+
);
39+
}
40+
41+
export function SdkDefinitionTable({
42+
children,
43+
className,
44+
}: {
45+
children?: React.ReactNode;
46+
className?: string;
47+
}) {
48+
return (
49+
<table className={styles['sdk-option-table'] + (className ? ` ${className}` : '')}>
50+
<tbody>{children}</tbody>
51+
</table>
52+
);
53+
}

src/components/sdkOption/style.module.scss renamed to src/components/sdkDefinition/style.module.scss

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
1-
.sdk-config-option {
2-
padding-top: 10px;
1+
.sdk-config-option:not(:last-child) {
2+
margin-bottom: 2rem;
33
}
44

55
.sdk-config-option-details {
6-
padding-left: 20px;
6+
padding-left: 0;
77
}
88

99
.sdk-option-table {
1010
--border-radius: 6px;
11+
font-size: 1rem;
1112
margin-top: 1rem;
12-
13-
width: auto !important;
13+
width: auto;
1414

1515
// This is necessary to make rounded borders work :(
1616
border-collapse: separate !important;
1717
border-spacing: 0;
1818

19-
& tr th, & tr td {
19+
&:first-child {
20+
margin-top: 0;
21+
}
22+
23+
&:last-child {
24+
margin-bottom: 0;
25+
}
26+
27+
& tr th,
28+
& tr td {
2029
border-bottom-width: 0;
2130
border-right-width: 0;
22-
padding: .5rem .75rem
31+
padding: 0.5rem 0.75rem;
2332
}
2433

2534
& tr:last-child > * {
@@ -46,3 +55,8 @@
4655
border-bottom-right-radius: var(--border-radius);
4756
}
4857
}
58+
59+
// This is to ensure specificity beats .prose table :(
60+
.sdk-config-option .sdk-option-table {
61+
width: auto;
62+
}

0 commit comments

Comments
 (0)