From ef93da79b015c244225d3a855db29254d08a62e8 Mon Sep 17 00:00:00 2001 From: Charis <26616127+charislam@users.noreply.github.com> Date: Wed, 6 Aug 2025 10:21:51 -0400 Subject: [PATCH] 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 --- apps/docs/app/contributing/content.mdx | 22 ++ .../features/directives/CodeSample.test.ts | 200 ++++++++++++++++++ apps/docs/features/directives/CodeSample.ts | 39 +++- apps/docs/package.json | 1 + examples/_internal/fixtures/typescript.ts | 43 ++++ pnpm-lock.yaml | 64 ++++-- 6 files changed, 344 insertions(+), 25 deletions(-) create mode 100644 examples/_internal/fixtures/typescript.ts diff --git a/apps/docs/app/contributing/content.mdx b/apps/docs/app/contributing/content.mdx index d56648eb1f..2a5086cd2d 100644 --- a/apps/docs/app/contributing/content.mdx +++ b/apps/docs/app/contributing/content.mdx @@ -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 */} +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: diff --git a/apps/docs/features/directives/CodeSample.test.ts b/apps/docs/features/directives/CodeSample.test.ts index a3ae68b0e1..3c8e83df2f 100644 --- a/apps/docs/features/directives/CodeSample.test.ts +++ b/apps/docs/features/directives/CodeSample.test.ts @@ -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', () => { diff --git a/apps/docs/features/directives/CodeSample.ts b/apps/docs/features/directives/CodeSample.ts index d962ca8486..dc505c0bda 100644 --- a/apps/docs/features/directives/CodeSample.ts +++ b/apps/docs/features/directives/CodeSample.ts @@ -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 & 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 & 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) { +async function rewriteNodes(contentMap: Map) { 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 ? { diff --git a/apps/docs/package.json b/apps/docs/package.json index 96c1cdb065..c3a310ff02 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -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:*", diff --git a/examples/_internal/fixtures/typescript.ts b/examples/_internal/fixtures/typescript.ts new file mode 100644 index 0000000000..ef841da6e6 --- /dev/null +++ b/examples/_internal/fixtures/typescript.ts @@ -0,0 +1,43 @@ +type Status = 'active' | 'inactive' + +interface User { + id: number + name: string + email?: string + status?: Status +} + +const users: Array = [ + { 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 = [] + + constructor(initialUsers = []) { + this.users = initialUsers + } + + addUser(user: User) { + this.users.push(user) + } + + getUsers() { + return [...this.users] + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f53cdb760..6cbe691064 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: {}