feat(docs): code samples with ts type stripping (#37695)

* feat(docs): code samples with ts type stripping

Introduce a new option to `$CodeSample`, `convertToJs`, which takes a
code sample written in TypeScript and strips the types to produce a
JavaScript version.

Adds tests for type stripping.

* Clarify instructions

---------

Co-authored-by: Chris Chinchilla <chris@chrischinchilla.com>
This commit is contained in:
CharisandChris Chinchilla authored and GitHub committed 2025-08-06 10:21:51 -04:00
1 parent f5f0876b4e
commit ef93da79b0
6 files changed
+344 -25

No files matched your search

+22
View File
@@ -181,6 +181,8 @@ Line numbers are 1-indexed and inclusive.
lines={[[1, 3], [5, -1]]}
{/* Optional, displays as a file name on the code block */}
meta="name=display/path.js"
{/* Optional, strips TypeScript types to produce JavaScript, which you also include with another <CodeSample /> */}
convertToJs={true}
/>
```
@@ -195,11 +197,31 @@ commit="1623aa9b95ec90e21c5bae5a0d50dcf272abe92f"
path="/relative/path/from/root.js"
lines={[[1, 3], [5, -1]]}
meta="name=display/path.js"
convertToJs={true}
/>
```
The repo must be public, the org must be on the allow list, and the commit must be an immutable SHA (not a mutable tag or branch name).
#### Converting TypeScript to JavaScript
You can automatically strip TypeScript types from code samples to produce JavaScript using the `convertToJs` option:
```mdx
<$CodeSample
path="/path/to/typescript-file.ts"
lines={[[1, -1]]}
convertToJs={true}
/>
```
This is useful when you want to show JavaScript examples from TypeScript source files. The conversion:
- Removes all TypeScript type annotations, interfaces, and type definitions
- Converts the language identifier from `typescript` to `javascript` (or `tsx` to `jsx`)
- Happens before any line selection or elision processing
- Defaults to `false` to preserve TypeScript code when not specified
#### Multi-file code samples
Multi-file code samples use the `<$CodeTabs>` annotation:
@@ -1,5 +1,6 @@
import { afterAll, beforeAll, describe, it, expect, vi } from 'vitest'
import { stripIndent } from 'common-tags'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { mdxFromMarkdown, mdxToMarkdown } from 'mdast-util-mdx'
import { toMarkdown } from 'mdast-util-to-markdown'
@@ -18,6 +19,42 @@ vi.mock('~/lib/constants', () => ({
IS_PLATFORM: true,
}))
/**
* Checks if str1 contains str2, ignoring leading whitespace on each line.
* Lines are matched if they have the same content after trimming leading whitespace.
*
* @param str1 - The string to search in
* @param str2 - The string to search for
* @returns true if str1 contains str2 modulo leading whitespace, false otherwise
*/
export function containsStringIgnoringLeadingWhitespace(str1: string, str2: string): boolean {
const lines1 = str1.split('\n').map((line) => line.trimStart())
const lines2 = str2.split('\n').map((line) => line.trimStart())
if (lines2.length === 0) {
return true
}
if (lines2.length > lines1.length) {
return false
}
for (let i = 0; i <= lines1.length - lines2.length; i++) {
let matches = true
for (let j = 0; j < lines2.length; j++) {
if (lines1[i + j] !== lines2[j]) {
matches = false
break
}
}
if (matches) {
return true
}
}
return false
}
describe('$CodeSample', () => {
beforeAll(() => {
env = process.env
@@ -533,6 +570,169 @@ Some more text.
expect(output).toEqual(expected)
})
describe('convertToJs option', () => {
it('should convert TypeScript to JavaScript when convertToJs is true', async () => {
const markdown = `
# Embed code sample
<$CodeSample path="/_internal/fixtures/typescript.ts" lines={[[1, -1]]} convertToJs={true} />
Some more text.
`.trim()
const mdast = fromMarkdown(markdown, {
mdastExtensions: [mdxFromMarkdown()],
extensions: [mdxjs()],
})
const transformed = await transformWithMock(mdast)
const output = toMarkdown(transformed, { extensions: [mdxToMarkdown()] })
const expected = stripIndent`
\`\`\`javascript
const users = [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane' },
];
function getUserById(id) {
return users.find((user) => user.id === id);
}
function createUser(name, email) {
const newId = Math.max(...users.map((u) => u.id)) + 1;
const newUser = { id: newId, name };
if (email) {
newUser.email = email;
}
users.push(newUser);
return newUser;
}
class UserManager {
users = [];
constructor(initialUsers = []) {
this.users = initialUsers;
}
addUser(user) {
this.users.push(user);
}
getUsers() {
return [...this.users];
}
}
\`\`\`
`.trim()
expect(containsStringIgnoringLeadingWhitespace(output, expected)).toBe(true)
})
it('should preserve TypeScript when convertToJs is false', async () => {
const markdown = `
# Embed code sample
<$CodeSample path="/_internal/fixtures/typescript.ts" lines={[[1, -1]]} convertToJs={false} />
Some more text.
`.trim()
const mdast = fromMarkdown(markdown, {
mdastExtensions: [mdxFromMarkdown()],
extensions: [mdxjs()],
})
const transformed = await transformWithMock(mdast)
const output = toMarkdown(transformed, { extensions: [mdxToMarkdown()] })
// The output should contain TypeScript types
expect(output).toContain('```typescript')
expect(output).toContain('interface User')
expect(output).toContain('type Status')
expect(output).toContain(': User')
expect(output).toContain(': number')
expect(output).toContain(': string')
})
it('should preserve TypeScript when convertToJs is not specified (default)', async () => {
const markdown = `
# Embed code sample
<$CodeSample path="/_internal/fixtures/typescript.ts" lines={[[1, -1]]} />
Some more text.
`.trim()
const mdast = fromMarkdown(markdown, {
mdastExtensions: [mdxFromMarkdown()],
extensions: [mdxjs()],
})
const transformed = await transformWithMock(mdast)
const output = toMarkdown(transformed, { extensions: [mdxToMarkdown()] })
// The output should contain TypeScript types by default
expect(output).toContain('```typescript')
expect(output).toContain('interface User')
expect(output).toContain('type Status')
})
it('should convert types but preserve line selection and elision', async () => {
const markdown = `
# Embed code sample
<$CodeSample path="/_internal/fixtures/typescript.ts" lines={[[1, 4], [10, -1]]} convertToJs={true} />
Some more text.
`.trim()
const mdast = fromMarkdown(markdown, {
mdastExtensions: [mdxFromMarkdown()],
extensions: [mdxjs()],
})
const transformed = await transformWithMock(mdast)
const output = toMarkdown(transformed, { extensions: [mdxToMarkdown()] })
const expected = `
\`\`\`javascript
const users = [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane' },
];
// ...
function createUser(name, email) {
const newId = Math.max(...users.map((u) => u.id)) + 1;
const newUser = { id: newId, name };
if (email) {
newUser.email = email;
}
users.push(newUser);
return newUser;
}
class UserManager {
users = [];
constructor(initialUsers = []) {
this.users = initialUsers;
}
addUser(user) {
this.users.push(user);
}
getUsers() {
return [...this.users];
}
}
\`\`\`
`.trim()
expect(containsStringIgnoringLeadingWhitespace(output, expected)).toBe(true)
})
})
})
describe('_createElidedLine', () => {
+35 -4
View File
@@ -11,6 +11,7 @@
* lines={[1, 2], [5, 7]} // -1 may be used in end position as an alias for the last line, e.g., [1, -1]
* meta="utils/client.ts" // Optional, for displaying a file path on the code block
* hideElidedLines={true} // Optional, for hiding elided lines in the code block
* convertToJs={true} // Optional, strips TypeScript types to produce JavaScript
* />
* ```
*
@@ -26,6 +27,7 @@
* lines={[1, 2], [5, 7]} // -1 may be used in end position as an alias for the last line, e.g., [1, -1]
* meta="utils/client.ts" // Optional, for displaying a file path on the code block
* hideElidedLines={true} // Optional, for hiding elided lines in the code block
* convertToJs={true} // Optional, strips TypeScript types to produce JavaScript
* />
*/
@@ -33,8 +35,10 @@ import * as acorn from 'acorn'
import tsPlugin from 'acorn-typescript'
import { type DefinitionContent, type BlockContent, type Code, type Root } from 'mdast'
import type { MdxJsxAttributeValueExpression, MdxJsxFlowElement } from 'mdast-util-mdx-jsx'
import assert from 'node:assert'
import { readFile } from 'node:fs/promises'
import { join } from 'node:path'
import { removeTypes } from 'remove-types'
import { type Parent } from 'unist'
import { visitParents } from 'unist-util-visit-parents'
import { z, type SafeParseError } from 'zod'
@@ -69,6 +73,12 @@ type AdditionalMeta = {
codeHikeAncestorParent: Parent | null
}
const booleanValidator = z.union([z.boolean(), z.string(), z.undefined()]).transform((v) => {
if (typeof v === 'boolean') return v
if (typeof v === 'string') return v === 'true'
return false
})
const codeSampleExternalSchema = z.object({
external: z.coerce.boolean().refine((v) => v === true),
org: z.enum(ALLOW_LISTED_GITHUB_ORGS, {
@@ -80,6 +90,7 @@ const codeSampleExternalSchema = z.object({
lines: linesValidator,
meta: z.string().optional(),
hideElidedLines: z.coerce.boolean().default(false),
convertToJs: booleanValidator,
})
type ICodeSampleExternal = z.infer<typeof codeSampleExternalSchema> & AdditionalMeta
@@ -92,6 +103,7 @@ const codeSampleInternalSchema = z.object({
lines: linesValidator,
meta: z.string().optional(),
hideElidedLines: z.coerce.boolean().default(false),
convertToJs: booleanValidator,
})
type ICodeSampleInternal = z.infer<typeof codeSampleInternalSchema> & AdditionalMeta
@@ -114,7 +126,7 @@ interface Dependencies {
export function codeSampleRemark(deps: Dependencies) {
return async function transform(tree: Root) {
const contentMap = await fetchSourceCodeContent(tree, deps)
rewriteNodes(contentMap)
await rewriteNodes(contentMap)
return tree
}
@@ -154,6 +166,7 @@ async function fetchSourceCodeContent(tree: Root, deps: Dependencies) {
const hideElidedLines = getAttributeValueExpression(
getAttributeValue(node, 'hideElidedLines')
)
const convertToJs = getAttributeValueExpression(getAttributeValue(node, 'convertToJs'))
const result = codeSampleExternalSchema.safeParse({
external: isExternal,
@@ -164,6 +177,7 @@ async function fetchSourceCodeContent(tree: Root, deps: Dependencies) {
lines,
meta,
hideElidedLines,
convertToJs,
})
if (!result.success) {
@@ -197,6 +211,7 @@ async function fetchSourceCodeContent(tree: Root, deps: Dependencies) {
const hideElidedLines = getAttributeValueExpression(
getAttributeValue(node, 'hideElidedLines')
)
const convertToJs = getAttributeValueExpression(getAttributeValue(node, 'convertToJs'))
const result = codeSampleInternalSchema.safeParse({
external: isExternal,
@@ -204,6 +219,7 @@ async function fetchSourceCodeContent(tree: Root, deps: Dependencies) {
lines,
meta,
hideElidedLines,
convertToJs,
})
if (!result.success) {
@@ -234,15 +250,30 @@ async function fetchSourceCodeContent(tree: Root, deps: Dependencies) {
return nodeContentMap
}
function rewriteNodes(contentMap: Map<MdxJsxFlowElement, [CodeSampleMeta, string]>) {
async function rewriteNodes(contentMap: Map<MdxJsxFlowElement, [CodeSampleMeta, string]>) {
for (const [node, [meta, content]] of contentMap) {
const lang = matchLang(meta.path.split('.').pop() || '')
let lang = matchLang(meta.path.split('.').pop() || '')
const source = isExternalSource(meta)
? `https://github.com/${meta.org}/${meta.repo}/blob/${meta.commit}${meta.path}`
: `https://github.com/supabase/supabase/blob/${process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA ?? 'master'}/examples${meta.path}`
const elidedContent = redactLines(content, meta.lines, lang, meta.hideElidedLines)
let processedContent = content
if (meta.convertToJs) {
processedContent = await removeTypes(content)
// Convert TypeScript/TSX language to JavaScript/JSX when converting types
assert(
lang === 'typescript' || lang === 'tsx',
'Type stripping to JS is only supported for TypeScript and TSX'
)
if (lang === 'typescript') {
lang = 'javascript'
} else if (lang === 'tsx') {
lang = 'jsx'
}
}
const elidedContent = redactLines(processedContent, meta.lines, lang, meta.hideElidedLines)
const replacementContent: MdxJsxFlowElement | Code = meta.codeHikeAncestor
? {
+1
View File
@@ -107,6 +107,7 @@
"remark-emoji": "^3.1.2",
"remark-gfm": "^3.0.1",
"remark-math": "^6.0.0",
"remove-types": "1.0.0",
"server-only": "^0.0.1",
"shared-data": "workspace:*",
"ui": "workspace:*",
+43
View File
@@ -0,0 +1,43 @@
type Status = 'active' | 'inactive'
interface User {
id: number
name: string
email?: string
status?: Status
}
const users: Array<User> = [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane' },
]
function getUserById(id: number): User | undefined {
return users.find((user) => user.id === id)
}
function createUser(name: string, email: string): User {
const newId = Math.max(...users.map((u) => u.id)) + 1
const newUser: User = { id: newId, name }
if (email) {
newUser.email = email
}
users.push(newUser)
return newUser
}
class UserManager {
users: Array<User> = []
constructor(initialUsers = []) {
this.users = initialUsers
}
addUser(user: User) {
this.users.push(user)
}
getUsers() {
return [...this.users]
}
}
+43 -21
View File
@@ -332,7 +332,7 @@ importers:
version: 1.0.3(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@sentry/nextjs':
specifier: ^9.15.0
version: 9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)
version: 9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)
'@supabase/supabase-js':
specifier: 'catalog:'
version: 2.49.3
@@ -452,7 +452,7 @@ importers:
version: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
nuqs:
specifier: ^1.19.1
version: 1.19.1(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))
version: 1.19.1(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))
openai:
specifier: ^4.20.1
version: 4.71.1(encoding@0.1.13)(zod@3.23.8)
@@ -498,6 +498,9 @@ importers:
remark-math:
specifier: ^6.0.0
version: 6.0.0(supports-color@8.1.1)
remove-types:
specifier: 1.0.0
version: 1.0.0(supports-color@8.1.1)
server-only:
specifier: ^0.0.1
version: 0.0.1
@@ -534,7 +537,7 @@ importers:
devDependencies:
'@graphiql/toolkit':
specifier: ^0.9.1
version: 0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)
version: 0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)
'@graphql-codegen/cli':
specifier: 5.0.5
version: 5.0.5(@parcel/watcher@2.5.1)(@types/node@22.13.14)(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(supports-color@8.1.1)(typescript@5.5.2)
@@ -606,7 +609,7 @@ importers:
version: 13.2.2
graphiql:
specifier: ^4.0.2
version: 4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
openapi-types:
specifier: ^12.1.3
version: 12.1.3
@@ -16047,6 +16050,9 @@ packages:
remove-trailing-spaces@1.0.9:
resolution: {integrity: sha512-xzG7w5IRijvIkHIjDk65URsJJ7k4J95wmcArY5PRcmjldIOl7oTvG8+X2Ag690R7SfwiOcHrWZKVc1Pp5WIOzA==}
remove-types@1.0.0:
resolution: {integrity: sha512-G7Hk1Q+UJ5DvlNAoJZObxANkBZGiGdp589rVcTW/tYqJWJ5rwfraSnKSQaETN8Epaytw8J40nS/zC7bcHGv36w==}
rename-keys@1.2.0:
resolution: {integrity: sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg==}
engines: {node: '>= 0.8.0'}
@@ -20841,9 +20847,9 @@ snapshots:
'@gar/promisify@1.1.3': {}
'@graphiql/plugin-doc-explorer@0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@graphiql/plugin-doc-explorer@0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@headlessui/react': 2.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
graphql: 16.11.0
react: 18.3.1
@@ -20857,10 +20863,10 @@ snapshots:
- '@types/react-dom'
- graphql-ws
'@graphiql/plugin-history@0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@graphiql/plugin-history@0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)
react: 18.3.1
react-compiler-runtime: 19.1.0-rc.1(react@18.3.1)
react-dom: 18.3.1(react@18.3.1)
@@ -20900,9 +20906,9 @@ snapshots:
- '@types/react-dom'
- graphql-ws
'@graphiql/react@0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@graphiql/react@0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)
'@graphiql/toolkit': 0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)
'@radix-ui/react-dialog': 1.1.11(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-dropdown-menu': 2.1.12(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-tooltip': 1.2.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -20929,13 +20935,13 @@ snapshots:
- '@types/react-dom'
- graphql-ws
'@graphiql/toolkit@0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)':
'@graphiql/toolkit@0.11.2(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)':
dependencies:
'@n1ru4l/push-pull-async-iterable-iterator': 3.2.0
graphql: 16.11.0
meros: 1.3.0(@types/node@22.13.14)
optionalDependencies:
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.18.3)
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.18.1)
transitivePeerDependencies:
- '@types/node'
@@ -20949,13 +20955,13 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
'@graphiql/toolkit@0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)':
'@graphiql/toolkit@0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)':
dependencies:
'@n1ru4l/push-pull-async-iterable-iterator': 3.2.0
graphql: 16.11.0
meros: 1.3.0(@types/node@22.13.14)
optionalDependencies:
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.18.3)
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.18.1)
transitivePeerDependencies:
- '@types/node'
@@ -25661,7 +25667,7 @@ snapshots:
- supports-color
- webpack
'@sentry/nextjs@9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)':
'@sentry/nextjs@9.15.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)(supports-color@8.1.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4))(react@18.3.1)(supports-color@8.1.1)(webpack@5.94.0)':
dependencies:
'@opentelemetry/api': 1.9.0
'@opentelemetry/semantic-conventions': 1.32.0
@@ -31516,11 +31522,11 @@ snapshots:
graphemer@1.4.0: {}
graphiql@4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
graphiql@4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@graphiql/plugin-doc-explorer': 0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/plugin-history': 0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/plugin-doc-explorer': 0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/plugin-history': 0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.2.1)(@types/node@22.13.14)(@types/react-dom@18.3.0)(@types/react@18.3.3)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1))(graphql@16.11.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
graphql: 16.11.0
react: 18.3.1
react-compiler-runtime: 19.1.0-rc.1(react@18.3.1)
@@ -31607,6 +31613,13 @@ snapshots:
dependencies:
graphql: 16.11.0
graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.1):
dependencies:
graphql: 16.11.0
optionalDependencies:
ws: 8.18.1
optional: true
graphql-ws@6.0.4(graphql@16.11.0)(ws@8.18.3):
dependencies:
graphql: 16.11.0
@@ -34915,7 +34928,7 @@ snapshots:
number-flow@0.3.7: {}
nuqs@1.19.1(next@15.3.3(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)):
nuqs@1.19.1(next@15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)):
dependencies:
mitt: 3.0.1
next: 15.3.3(@babel/core@7.26.10(supports-color@8.1.1))(@opentelemetry/api@1.9.0)(@playwright/test@1.53.0)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.4)
@@ -36831,6 +36844,15 @@ snapshots:
remove-trailing-spaces@1.0.9: {}
remove-types@1.0.0(supports-color@8.1.1):
dependencies:
'@babel/core': 7.26.10(supports-color@8.1.1)
'@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.10(supports-color@8.1.1))
'@babel/plugin-transform-typescript': 7.27.0(@babel/core@7.26.10(supports-color@8.1.1))(supports-color@8.1.1)
prettier: 2.8.8
transitivePeerDependencies:
- supports-color
rename-keys@1.2.0: {}
repeat-element@1.1.4: {}