diff --git a/packages/libraries/laboratory/package.json b/packages/libraries/laboratory/package.json index 8857c58d9e3..a03431fa67e 100644 --- a/packages/libraries/laboratory/package.json +++ b/packages/libraries/laboratory/package.json @@ -29,16 +29,17 @@ "peerDependencies": { "@tanstack/react-form": "^1.23.8", "date-fns": "^4.1.0", - "graphql-ws": "^6.0.6", "lucide-react": "^0.548.0", "lz-string": "^1.5.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", + "subscriptions-transport-ws": "^0.11.0", "tslib": "^2.8.1", "zod": "^4.1.12" }, "dependencies": { "@base-ui/react": "^1.1.0", + "@graphql-tools/url-loader": "^9.1.0", "radix-ui": "^1.4.3", "react-zoom-pan-pinch": "^3.7.0", "uuid": "^13.0.0" @@ -98,7 +99,6 @@ "eslint-plugin-react-refresh": "^0.4.26", "globals": "^16.5.0", "graphql": "^16.12.0", - "graphql-ws": "^6.0.6", "lodash": "^4.18.1", "lucide-react": "^0.548.0", "lz-string": "^1.5.0", @@ -114,6 +114,7 @@ "react-shadow": "^20.6.0", "rollup-plugin-typescript2": "^0.36.0", "sonner": "^2.0.7", + "subscriptions-transport-ws": "^0.11.0", "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "tailwindcss-scoped-preflight": "^3.5.7", diff --git a/packages/libraries/laboratory/src/components/laboratory/laboratory.tsx b/packages/libraries/laboratory/src/components/laboratory/laboratory.tsx index 1194532881e..5170d8fab75 100644 --- a/packages/libraries/laboratory/src/components/laboratory/laboratory.tsx +++ b/packages/libraries/laboratory/src/components/laboratory/laboratory.tsx @@ -402,7 +402,7 @@ const LaboratoryContent = () => { > Preflight Script - {/* + { const tab = @@ -416,7 +416,7 @@ const LaboratoryContent = () => { }} > Settings - */} + Settings @@ -514,7 +514,10 @@ export const Laboratory = ( const pluginsApi = usePlugins(props); const testsApi = useTests(props); const tabsApi = useTabs(props); - const endpointApi = useEndpoint(props); + const endpointApi = useEndpoint({ + ...props, + settingsApi, + }); const collectionsApi = useCollections({ ...props, tabsApi, diff --git a/packages/libraries/laboratory/src/components/laboratory/operation.tsx b/packages/libraries/laboratory/src/components/laboratory/operation.tsx index f9ec9a3b9b5..1cbf408c776 100644 --- a/packages/libraries/laboratory/src/components/laboratory/operation.tsx +++ b/packages/libraries/laboratory/src/components/laboratory/operation.tsx @@ -392,7 +392,7 @@ export const Response = ({ historyItem }: { historyItem?: LaboratoryHistoryReque )} {historyItem ? (
- {historyItem?.status && ( + {!!historyItem?.status && ( ; + }) ?? { + status: 0, + headers: {}, + }; + + delete response.extensions?.request; + delete response.extensions?.response; + + if (Object.keys(response.extensions ?? {}).length === 0) { + delete response.extensions; + } + + const status = extensionsResponse.status; const duration = performance.now() - startTime; - const responseText = await response.text(); + const responseText = JSON.stringify(response, null, 2); const size = responseText.length; const newItemHistory = addHistory({ status, duration, size, - headers: JSON.stringify(Object.fromEntries(response.headers.entries()), null, 2), + headers: JSON.stringify(extensionsResponse.headers, null, 2), operation, preflightLogs: result?.logs ?? [], response: responseText, diff --git a/packages/libraries/laboratory/src/components/laboratory/settings.tsx b/packages/libraries/laboratory/src/components/laboratory/settings.tsx index 020297ac586..92f6a9802f2 100644 --- a/packages/libraries/laboratory/src/components/laboratory/settings.tsx +++ b/packages/libraries/laboratory/src/components/laboratory/settings.tsx @@ -18,7 +18,6 @@ const settingsFormSchema = z.object({ protocol: z.enum(['SSE', 'GRAPHQL_SSE', 'WS', 'LEGACY_WS']), }), introspection: z.object({ - queryName: z.string().optional(), method: z.enum(['GET', 'POST']).optional(), schemaDescription: z.boolean().optional(), }), @@ -87,8 +86,12 @@ export const Settings = () => { field.handleChange(Number(e.target.value))} + value={field.state.value ?? ''} + onChange={e => + field.handleChange( + e.target.value === '' ? undefined : Number(e.target.value), + ) + } /> ); @@ -102,8 +105,12 @@ export const Settings = () => { field.handleChange(Number(e.target.value))} + value={field.state.value ?? ''} + onChange={e => + field.handleChange( + e.target.value === '' ? undefined : Number(e.target.value), + ) + } /> ); @@ -115,7 +122,7 @@ export const Settings = () => { Use GET for queries @@ -175,20 +182,6 @@ export const Settings = () => { - - {field => { - return ( - - Query name - field.handleChange(e.target.value)} - /> - - ); - }} - {field => { const isInvalid = field.state.meta.isTouched && !field.state.meta.isValid; @@ -219,7 +212,7 @@ export const Settings = () => { Schema description diff --git a/packages/libraries/laboratory/src/lib/endpoint.ts b/packages/libraries/laboratory/src/lib/endpoint.ts index f2daa3681b6..2e653ff3fe6 100644 --- a/packages/libraries/laboratory/src/lib/endpoint.ts +++ b/packages/libraries/laboratory/src/lib/endpoint.ts @@ -1,13 +1,15 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { buildClientSchema, - getIntrospectionQuery, GraphQLSchema, + introspectionFromSchema, type IntrospectionQuery, } from 'graphql'; import { toast } from 'sonner'; -import z from 'zod'; +// import z from 'zod'; import { asyncInterval } from '@/lib/utils'; +import { SubscriptionProtocol, UrlLoader } from '@graphql-tools/url-loader'; +import type { LaboratorySettingsActions, LaboratorySettingsState } from './settings'; export interface LaboratoryEndpointState { endpoint: string | null; @@ -22,20 +24,11 @@ export interface LaboratoryEndpointActions { restoreDefaultEndpoint: () => void; } -const GraphQLResponseErrorSchema = z - .object({ - errors: z.array( - z.object({ - message: z.string(), - }), - ), - }) - .strict(); - export const useEndpoint = (props: { defaultEndpoint?: string | null; onEndpointChange?: (endpoint: string | null) => void; defaultSchemaIntrospection?: IntrospectionQuery | null; + settingsApi?: LaboratorySettingsState & LaboratorySettingsActions; }): LaboratoryEndpointState & LaboratoryEndpointActions => { const [endpoint, _setEndpoint] = useState(props.defaultEndpoint ?? null); const [introspection, setIntrospection] = useState(null); @@ -52,6 +45,8 @@ export const useEndpoint = (props: { return introspection ? buildClientSchema(introspection) : null; }, [introspection]); + const loader = useMemo(() => new UrlLoader(), []); + const fetchSchema = useCallback( async (signal?: AbortSignal) => { if (endpoint === props.defaultEndpoint && props.defaultSchemaIntrospection) { @@ -65,28 +60,37 @@ export const useEndpoint = (props: { } try { - const response = await fetch(endpoint, { - signal, - method: 'POST', - body: JSON.stringify({ - query: getIntrospectionQuery(), - }), - headers: { - 'Content-Type': 'application/json', - }, - }).then(r => r.json()); - - const parsedResponse = GraphQLResponseErrorSchema.safeParse(response); - - if (parsedResponse.success) { - throw new Error(parsedResponse.data.errors.map(e => e.message).join('\n')); + const result = await loader.load(endpoint, { + subscriptionsEndpoint: endpoint, + subscriptionsProtocol: + (props.settingsApi?.settings.subscriptions.protocol as SubscriptionProtocol) ?? + SubscriptionProtocol.GRAPHQL_SSE, + credentials: props.settingsApi?.settings.fetch.credentials, + specifiedByUrl: true, + directiveIsRepeatable: true, + inputValueDeprecation: true, + retry: props.settingsApi?.settings.fetch.retry, + timeout: props.settingsApi?.settings.fetch.timeout, + useGETForQueries: props.settingsApi?.settings.fetch.useGETForQueries, + exposeHTTPDetailsInExtensions: true, + descriptions: props.settingsApi?.settings.introspection.schemaDescription ?? false, + method: props.settingsApi?.settings.introspection.method ?? 'POST', + fetch: (input: string | URL | Request, init?: RequestInit) => + fetch(input, { + ...init, + signal, + }), + }); + + if (result.length === 0) { + throw new Error('Failed to fetch schema'); } - if (response.error && typeof response.error === 'string') { - throw new Error(response.error); + if (!result[0].schema) { + throw new Error('Failed to fetch schema'); } - setIntrospection(response.data as IntrospectionQuery); + setIntrospection(introspectionFromSchema(result[0].schema)); } catch (error: unknown) { if ( error && @@ -104,7 +108,12 @@ export const useEndpoint = (props: { throw error; } }, - [endpoint], + [ + endpoint, + props.settingsApi?.settings.fetch.timeout, + props.settingsApi?.settings.introspection.method, + props.settingsApi?.settings.introspection.schemaDescription, + ], ); const shouldPollSchema = useMemo(() => { @@ -129,6 +138,7 @@ export const useEndpoint = (props: { 5000, intervalController.signal, ); + return () => { intervalController.abort(); }; diff --git a/packages/libraries/laboratory/src/lib/operations.ts b/packages/libraries/laboratory/src/lib/operations.ts index f2ad388d079..9f631d81cf1 100644 --- a/packages/libraries/laboratory/src/lib/operations.ts +++ b/packages/libraries/laboratory/src/lib/operations.ts @@ -1,8 +1,16 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; -import type { GraphQLSchema } from 'graphql'; -import { createClient } from 'graphql-ws'; +import { + DocumentNode, + ExecutionResult, + getOperationAST, + Kind, + parse, + type GraphQLSchema, +} from 'graphql'; import { decompressFromEncodedURIComponent } from 'lz-string'; import { v4 as uuidv4 } from 'uuid'; +import { isAsyncIterable } from '@/lib/utils'; +import { SubscriptionProtocol, UrlLoader } from '@graphql-tools/url-loader'; import { LaboratoryPermission, LaboratoryPermissions } from '../components/laboratory/context'; import type { LaboratoryCollectionOperation, @@ -23,6 +31,14 @@ import type { LaboratoryPreflightActions, LaboratoryPreflightState } from './pre import type { LaboratorySettingsActions, LaboratorySettingsState } from './settings'; import type { LaboratoryTabOperation, LaboratoryTabsActions, LaboratoryTabsState } from './tabs'; +function getOperationType(query: string): 'query' | 'mutation' | 'subscription' | null { + try { + return getOperationAST(parse(query))?.operation ?? null; + } catch { + return null; + } +} + export interface LaboratoryOperation { id: string; name: string; @@ -66,7 +82,7 @@ export interface LaboratoryOperationsActions { operationName?: string; onResponse?: (response: string) => void; }, - ) => Promise; + ) => Promise; stopActiveOperation: (() => void) | null; isActiveOperationLoading: boolean; isOperationLoading: (operationId: string) => boolean; @@ -80,6 +96,27 @@ export interface LaboratoryOperationsCallbacks { onOperationDelete?: (operation: LaboratoryOperation) => void; } +const getOperationWithFragments = ( + document: DocumentNode, + operationName?: string, +): DocumentNode => { + const definitions = document.definitions.filter(definition => { + if ( + definition.kind === Kind.OPERATION_DEFINITION && + operationName && + definition.name?.value !== operationName + ) { + return false; + } + return true; + }); + + return { + kind: Kind.DOCUMENT, + definitions, + }; +}; + export const useOperations = ( props: { checkPermissions: ( @@ -326,6 +363,8 @@ export const useOperations = ( return activeOperation ? isOperationLoading(activeOperation.id) : false; }, [activeOperation, isOperationLoading]); + const loader = useMemo(() => new UrlLoader(), []); + const runActiveOperation = useCallback( async ( endpoint: string, @@ -337,7 +376,7 @@ export const useOperations = ( }, plugins: LaboratoryPlugin[] = props.pluginsApi?.plugins ?? [], pluginsState: Record = props.pluginsApi?.pluginsState ?? {}, - ) => { + ): Promise => { if (!activeOperation?.query) { return null; } @@ -393,101 +432,76 @@ export const useOperations = ( ) : {}; - if (activeOperation.query.startsWith('subscription')) { - const client = createClient({ - url: endpoint.replace('http', 'ws'), - connectionParams: { - ...mergedHeaders, - }, - }); + const executor = loader.getExecutorAsync(endpoint, { + subscriptionsEndpoint: endpoint, + subscriptionsProtocol: + (props.settingsApi?.settings.subscriptions.protocol as SubscriptionProtocol) ?? + SubscriptionProtocol.GRAPHQL_SSE, + credentials: props.settingsApi?.settings.fetch.credentials, + specifiedByUrl: true, + directiveIsRepeatable: true, + inputValueDeprecation: true, + retry: props.settingsApi?.settings.fetch.retry, + timeout: props.settingsApi?.settings.fetch.timeout, + useGETForQueries: props.settingsApi?.settings.fetch.useGETForQueries, + exposeHTTPDetailsInExtensions: true, + fetch, + }); - client.on('connected', () => { - console.log('connected'); - }); + const document = getOperationWithFragments(parse(activeOperation.query)); - client.on('error', () => { - setStopOperationsFunctions(prev => { - const newStopOperationsFunctions = { ...prev }; - delete newStopOperationsFunctions[activeOperation.id]; - return newStopOperationsFunctions; - }); - }); + const abortController = new AbortController(); - client.on('closed', () => { + setStopOperationsFunctions(prev => ({ + ...prev, + [activeOperation.id]: () => { + abortController.abort(); + }, + })); + + const response = await executor({ + document, + variables, + extensions: { + ...extensions, + headers: mergedHeaders, + }, + signal: abortController.signal, + }); + + if (isAsyncIterable(response)) { + try { + for await (const item of response) { + options?.onResponse?.(JSON.stringify(item ?? {})); + } + } finally { setStopOperationsFunctions(prev => { const newStopOperationsFunctions = { ...prev }; delete newStopOperationsFunctions[activeOperation.id]; return newStopOperationsFunctions; }); - }); - - client.subscribe( - { - query: activeOperation.query, - variables, - extensions, - }, - { - next: message => { - options?.onResponse?.(JSON.stringify(message ?? {})); - }, - error: () => {}, - complete: () => {}, - }, - ); + } - setStopOperationsFunctions(prev => ({ - ...prev, - [activeOperation.id]: () => { - void client.dispose(); - setStopOperationsFunctions(prev => { - const newStopOperationsFunctions = { ...prev }; - delete newStopOperationsFunctions[activeOperation.id]; - return newStopOperationsFunctions; - }); - }, - })); - - return Promise.resolve(new Response()); + return null; } - const abortController = new AbortController(); - - const response = fetch(endpoint, { - method: 'POST', - credentials: props.settingsApi?.settings.fetch.credentials, - body: JSON.stringify({ - query: activeOperation.query, - operationName: options?.operationName, - variables, - extensions, - }), - headers: { - ...mergedHeaders, - 'Content-Type': 'application/json', - }, - signal: abortController.signal, - }).finally(() => { - setStopOperationsFunctions(prev => { - const newStopOperationsFunctions = { ...prev }; - delete newStopOperationsFunctions[activeOperation.id]; + if (response.extensions?.response?.body) { + delete response.extensions.response.body; + } - return newStopOperationsFunctions; - }); + setStopOperationsFunctions(prev => { + const newStopOperationsFunctions = { ...prev }; + delete newStopOperationsFunctions[activeOperation.id]; + return newStopOperationsFunctions; }); - setStopOperationsFunctions(prev => ({ - ...prev, - [activeOperation.id]: () => abortController.abort(), - })); - return response; }, - [activeOperation, props.preflightApi, props.envApi, props.pluginsApi], + [activeOperation, props.preflightApi, props.envApi, props.pluginsApi, props.settingsApi], ); const isOperationSubscription = useCallback((operation: LaboratoryOperation) => { - return operation.query?.startsWith('subscription') ?? false; + return getOperationType(operation.query) === 'subscription'; }, []); const isActiveOperationSubscription = useMemo(() => { diff --git a/packages/libraries/laboratory/src/lib/settings.ts b/packages/libraries/laboratory/src/lib/settings.ts index 8b81a4b6d00..20edcfe701b 100644 --- a/packages/libraries/laboratory/src/lib/settings.ts +++ b/packages/libraries/laboratory/src/lib/settings.ts @@ -11,12 +11,48 @@ export type LaboratorySettings = { protocol: 'SSE' | 'GRAPHQL_SSE' | 'WS' | 'LEGACY_WS'; }; introspection: { - queryName?: string; method?: 'GET' | 'POST'; schemaDescription?: boolean; }; }; +export const defaultLaboratorySettings: LaboratorySettings = { + fetch: { + credentials: 'same-origin', + timeout: 10000, + retry: 3, + useGETForQueries: false, + }, + subscriptions: { + protocol: 'WS', + }, + introspection: { + method: 'POST', + schemaDescription: false, + }, +}; + +export const normalizeLaboratorySettings = ( + settings?: Partial | null, +): LaboratorySettings => ({ + fetch: { + credentials: settings?.fetch?.credentials ?? defaultLaboratorySettings.fetch.credentials, + timeout: settings?.fetch?.timeout ?? defaultLaboratorySettings.fetch.timeout, + retry: settings?.fetch?.retry ?? defaultLaboratorySettings.fetch.retry, + useGETForQueries: + settings?.fetch?.useGETForQueries ?? defaultLaboratorySettings.fetch.useGETForQueries, + }, + subscriptions: { + protocol: settings?.subscriptions?.protocol ?? defaultLaboratorySettings.subscriptions.protocol, + }, + introspection: { + method: settings?.introspection?.method ?? defaultLaboratorySettings.introspection.method, + schemaDescription: + settings?.introspection?.schemaDescription ?? + defaultLaboratorySettings.introspection.schemaDescription, + }, +}); + export interface LaboratorySettingsState { settings: LaboratorySettings; } @@ -30,28 +66,14 @@ export const useSettings = (props: { onSettingsChange?: (settings: LaboratorySettings | null) => void; }): LaboratorySettingsState & LaboratorySettingsActions => { const [settings, _setSettings] = useState( - props.defaultSettings ?? { - fetch: { - credentials: 'same-origin', - timeout: 10000, - retry: 3, - useGETForQueries: false, - }, - subscriptions: { - protocol: 'WS', - }, - introspection: { - queryName: 'IntrospectionQuery', - method: 'POST', - schemaDescription: false, - }, - }, + normalizeLaboratorySettings(props.defaultSettings), ); const setSettings = useCallback( (settings: LaboratorySettings) => { - _setSettings(settings); - props.onSettingsChange?.(settings); + const normalizedSettings = normalizeLaboratorySettings(settings); + _setSettings(normalizedSettings); + props.onSettingsChange?.(normalizedSettings); }, [props], ); diff --git a/packages/libraries/laboratory/src/lib/utils.ts b/packages/libraries/laboratory/src/lib/utils.ts index 2f4142e3ebc..8d81f279660 100644 --- a/packages/libraries/laboratory/src/lib/utils.ts +++ b/packages/libraries/laboratory/src/lib/utils.ts @@ -40,3 +40,7 @@ export async function asyncInterval( }); } } + +export function isAsyncIterable(val: unknown): val is AsyncIterable { + return typeof Object(val)[Symbol.asyncIterator] === 'function'; +} diff --git a/packages/libraries/render-laboratory/src/index.ts b/packages/libraries/render-laboratory/src/index.ts index 2147449e611..985ed96574e 100644 --- a/packages/libraries/render-laboratory/src/index.ts +++ b/packages/libraries/render-laboratory/src/index.ts @@ -1,4 +1,5 @@ import type { GraphiQLOptions } from 'graphql-yoga'; +import type { LaboratoryProps } from '@graphql-hive/laboratory'; import { editorWorkerService, favicon, @@ -9,6 +10,30 @@ import { typescriptWorker, } from './laboratory.js'; +const mapGraphiQLOptionsToLaboratoryProps = (opts?: GraphiQLOptions): LaboratoryProps => { + if (!opts) { + return {}; + } + + return { + defaultSettings: { + fetch: { + credentials: opts.credentials ?? 'same-origin', + timeout: opts.timeout, + retry: opts.retry, + useGETForQueries: opts.useGETForQueries, + }, + subscriptions: { + protocol: opts.subscriptionsProtocol ?? 'WS', + }, + introspection: { + method: opts.method, + schemaDescription: opts.schemaDescription, + }, + }, + } satisfies LaboratoryProps; +}; + export const renderLaboratory = (opts?: GraphiQLOptions) => /* HTML */ ` @@ -63,7 +88,10 @@ export const renderLaboratory = (opts?: GraphiQLOptions) => /* HTML */ ` ${js}; - HiveLaboratory.renderLaboratory(window.document.querySelector('#root')); + HiveLaboratory.renderLaboratory( + window.document.querySelector('#root'), + ${JSON.stringify(mapGraphiQLOptionsToLaboratoryProps(opts))}, + ); diff --git a/packages/web/app/src/pages/target-laboratory-new.tsx b/packages/web/app/src/pages/target-laboratory-new.tsx index 6e14634af7e..dc6834d15d1 100644 --- a/packages/web/app/src/pages/target-laboratory-new.tsx +++ b/packages/web/app/src/pages/target-laboratory-new.tsx @@ -596,11 +596,7 @@ function useLaboratoryState(props: { defaultHistory: historyData ?? [], defaultTabs, defaultActiveTabId: getLocalStorageState('activeTabId', null), - defaultSettings: getLocalStorageState('settings', { - fetch: { - credentials: 'same-origin', - }, - }), + defaultSettings: getLocalStorageState('settings', null), defaultPreflight: preflight?.preflightScript?.sourceCode ? { script: preflight.preflightScript.sourceCode, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cb5bcd7cc9..6798f62caf9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -676,6 +676,9 @@ importers: '@base-ui/react': specifier: ^1.1.0 version: 1.1.0(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@graphql-tools/url-loader': + specifier: ^9.1.0 + version: 9.1.0(@types/node@24.12.2)(graphql@16.12.0) radix-ui: specifier: ^1.4.3 version: 1.4.3(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -848,9 +851,6 @@ importers: graphql: specifier: ^16.12.0 version: 16.12.0 - graphql-ws: - specifier: ^6.0.6 - version: 6.0.6(graphql@16.12.0)(ws@8.18.0) lodash: specifier: ^4.17.23 version: 4.18.1 @@ -896,6 +896,9 @@ importers: sonner: specifier: ^2.0.7 version: 2.0.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + subscriptions-transport-ws: + specifier: ^0.11.0 + version: 0.11.0(graphql@16.12.0) tailwind-merge: specifier: ^3.4.0 version: 3.4.0 @@ -974,8 +977,6 @@ importers: version: 5.13.3(graphql@16.12.0) publishDirectory: dist - packages/libraries/router: {} - packages/libraries/yoga: dependencies: '@graphql-hive/core': @@ -986,7 +987,7 @@ importers: version: 1.0.9(pino@10.3.0) '@graphql-yoga/plugin-persisted-operations': specifier: ^3.9.0 - version: 3.9.0(@graphql-tools/utils@11.0.0(graphql@16.9.0))(graphql-yoga@5.13.3(graphql@16.9.0))(graphql@16.9.0) + version: 3.9.0(@graphql-tools/utils@11.0.1-alpha-20260403104244-04c5cf56aba6702e37b7efb722f6b5158f5a9de2(graphql@16.9.0))(graphql-yoga@5.13.3(graphql@16.9.0))(graphql@16.9.0) graphql: specifier: ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 version: 16.9.0 @@ -4751,6 +4752,12 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-common@1.0.6': + resolution: {integrity: sha512-23/K5C+LSlHDI0mj2SwCJ33RcELCcyDUgABm1Z8St7u/4Z5+95i925H/NAjUyggRjiaY8vYtNiMOPE49aPX1sg==} + engines: {node: '>=20.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-graphql-ws@0.0.14': resolution: {integrity: sha512-P2nlkAsPZKLIXImFhj0YTtny5NQVGSsKnhi7PzXiaHSXc6KkzqbWZHKvikD4PObanqg+7IO58rKFpGXP7eeO+w==} peerDependencies: @@ -4780,6 +4787,12 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-graphql-ws@3.1.5': + resolution: {integrity: sha512-WXRsfwu9AkrORD9nShrd61OwwxeQ5+eXYcABRR3XPONFIS8pWQfDJGGqxql9/227o/s0DV5SIfkBURb5Knzv+A==} + engines: {node: '>=20.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-http@0.1.9': resolution: {integrity: sha512-tNzMt5qc1ptlHKfpSv9wVBVKCZ7gks6Yb/JcYJluxZIT4qRV+TtOFjpptfBU63usgrGVOVcGjzWc/mt7KhmmpQ==} peerDependencies: @@ -4803,6 +4816,12 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-http@3.2.1': + resolution: {integrity: sha512-53i0TYO0cznIlZDJcnq4gQ6SOZ8efGgCDV33MYh6oqEapcp36tCMEVnVGVxcX5qRRyNHkqTY6hkA+/AyK9kicQ==} + engines: {node: '>=20.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-legacy-ws@0.0.11': resolution: {integrity: sha512-4ai+NnxlNfvIQ4c70hWFvOZlSUN8lt7yc+ZsrwtNFbFPH/EroIzFMapAxM9zwyv9bH38AdO3TQxZ5zNxgBdvUw==} peerDependencies: @@ -4820,6 +4839,12 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor-legacy-ws@1.1.26': + resolution: {integrity: sha512-rlFHk8XoRCXjARQAlHTgtisyE5KJxMb9UyR4hRbD6tLlYjmzNf9ms8GjsLYe/j1QpHJ7fNDm9aXqj1+evhQ/MQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/executor@0.0.17': resolution: {integrity: sha512-DVKyMclsNY8ei14FUrR4jn24VHB3EuFldD8yGWrcJ8cudSh47sknznvXN6q0ffqDeAf0IlZSaBCHrOTBqA7OfQ==} peerDependencies: @@ -5087,6 +5112,12 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/url-loader@9.1.0': + resolution: {integrity: sha512-G3Ul5sLsLOJlfT4LkdQSKcHoJ+4CuSeUbRT1XjBXZSgNkeXZt2MXHJQX0X8+b4mJq7fI3thcfbiB+5sEUlnT7g==} + engines: {node: '>=20.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/utils@10.11.0': resolution: {integrity: sha512-iBFR9GXIs0gCD+yc3hoNswViL1O5josI33dUqiNStFI/MHLCEPduasceAcazRH77YONKNiviHBV8f7OgcT4o2Q==} engines: {node: '>=16.0.0'} @@ -5117,6 +5148,12 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/utils@11.0.1-alpha-20260403104244-04c5cf56aba6702e37b7efb722f6b5158f5a9de2': + resolution: {integrity: sha512-8uABmdEMr7gS7hOcEO0p6Y3cQZXNREE/4YWcSZWPuDSDU90rGJscwMlTcgW3zFwb3qqJ9ZpskQRq4ae8gMpa1Q==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + '@graphql-tools/utils@9.2.1': resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} peerDependencies: @@ -5134,12 +5171,6 @@ packages: peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/wrap@11.0.5': - resolution: {integrity: sha512-W0lm1AWLUAF2uKyrplC5PmyVJGCD/n7HO/R+bxoAIGQlZ2ESTbdB1DqZalMUF3D6AwmdzgTsDgoZBJgndnWs9g==} - engines: {node: '>=20.0.0'} - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - '@graphql-tools/wrap@11.1.2': resolution: {integrity: sha512-TcKZzUzJNmuyMBQ1oMdnxhBUUacN/5VEJu0/1KVce2aIzCwTTaN9JTU3MgjO7l5Ixn4QLkc6XbxYNv0cHDQgtQ==} engines: {node: '>=20.0.0'} @@ -11128,6 +11159,9 @@ packages: babel-plugin-react-compiler@19.1.0-rc.3: resolution: {integrity: sha512-mjRn69WuTz4adL0bXGx8Rsyk1086zFJeKmes6aK0xPuK3aaXmDJdLHqwKKMrpm6KAI1MCoUK72d2VeqQbu8YIA==} + backo2@1.0.2: + resolution: {integrity: sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==} + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -12800,6 +12834,9 @@ packages: eventemitter2@6.4.7: resolution: {integrity: sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==} + eventemitter3@3.1.2: + resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -14365,6 +14402,9 @@ packages: isstream@0.1.2: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + iterall@1.3.0: + resolution: {integrity: sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==} + iterator.prototype@1.1.5: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} @@ -17856,6 +17896,12 @@ packages: stylis@4.1.3: resolution: {integrity: sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==} + subscriptions-transport-ws@0.11.0: + resolution: {integrity: sha512-8D4C6DIH5tGiAIpp5I0wD/xRlNiZAPGHygzCe7VzyzUoxHtawzjNAY9SUTXU05/EY2NMY9/9GF0ycizkXr1CWQ==} + deprecated: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md + peerDependencies: + graphql: ^15.7.2 || ^16.0.0 + sucrase@3.35.0: resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} engines: {node: '>=16 || 14 >=14.17'} @@ -17901,6 +17947,14 @@ packages: swap-case@2.0.2: resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} + symbol-observable@1.2.0: + resolution: {integrity: sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==} + engines: {node: '>=0.10.0'} + + sync-fetch@0.6.0: + resolution: {integrity: sha512-IELLEvzHuCfc1uTsshPK58ViSdNqXxlml1U+fmwJIKLYKOr/rAtBrorE2RYm5IHaMpDNlmC0fr1LAvdXvyheEQ==} + engines: {node: '>=18'} + sync-fetch@0.6.0-2: resolution: {integrity: sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A==} engines: {node: '>=18'} @@ -23669,7 +23723,7 @@ snapshots: '@graphql-tools/batch-delegate': 10.0.5(graphql@16.12.0) '@graphql-tools/delegate': 11.1.3(graphql@16.12.0) '@graphql-tools/utils': 10.9.1(graphql@16.12.0) - '@graphql-tools/wrap': 11.0.5(graphql@16.12.0) + '@graphql-tools/wrap': 11.1.2(graphql@16.12.0) '@whatwg-node/disposablestack': 0.0.6 '@whatwg-node/fetch': 0.10.13 '@whatwg-node/promise-helpers': 1.3.2 @@ -23693,7 +23747,7 @@ snapshots: '@graphql-tools/batch-delegate': 10.0.5(graphql@16.12.0) '@graphql-tools/delegate': 11.1.3(graphql@16.12.0) '@graphql-tools/utils': 10.9.1(graphql@16.12.0) - '@graphql-tools/wrap': 11.0.5(graphql@16.12.0) + '@graphql-tools/wrap': 11.1.2(graphql@16.12.0) '@whatwg-node/disposablestack': 0.0.6 '@whatwg-node/fetch': 0.10.13 '@whatwg-node/promise-helpers': 1.3.2 @@ -23717,7 +23771,7 @@ snapshots: '@graphql-tools/batch-delegate': 10.0.5(graphql@16.9.0) '@graphql-tools/delegate': 11.1.3(graphql@16.9.0) '@graphql-tools/utils': 10.9.1(graphql@16.9.0) - '@graphql-tools/wrap': 11.0.5(graphql@16.9.0) + '@graphql-tools/wrap': 11.1.2(graphql@16.9.0) '@whatwg-node/disposablestack': 0.0.6 '@whatwg-node/fetch': 0.10.13 '@whatwg-node/promise-helpers': 1.3.2 @@ -24001,6 +24055,12 @@ snapshots: '@graphql-tools/utils': 10.11.0(graphql@16.9.0) graphql: 16.9.0 + '@graphql-tools/executor-common@1.0.6(graphql@16.12.0)': + dependencies: + '@envelop/core': 5.5.1 + '@graphql-tools/utils': 11.0.0(graphql@16.12.0) + graphql: 16.12.0 + '@graphql-tools/executor-graphql-ws@0.0.14(graphql@16.9.0)': dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.9.0) @@ -24077,6 +24137,23 @@ snapshots: - uWebSockets.js - utf-8-validate + '@graphql-tools/executor-graphql-ws@3.1.5(graphql@16.12.0)': + dependencies: + '@graphql-tools/executor-common': 1.0.6(graphql@16.12.0) + '@graphql-tools/utils': 11.0.0(graphql@16.12.0) + '@whatwg-node/disposablestack': 0.0.6 + graphql: 16.12.0 + graphql-ws: 6.0.6(graphql@16.12.0)(ws@8.18.0) + isows: 1.0.7(ws@8.18.0) + tslib: 2.8.1 + ws: 8.18.0 + transitivePeerDependencies: + - '@fastify/websocket' + - bufferutil + - crossws + - uWebSockets.js + - utf-8-validate + '@graphql-tools/executor-http@0.1.9(@types/node@24.12.2)(graphql@16.9.0)': dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.9.0) @@ -24129,7 +24206,7 @@ snapshots: '@whatwg-node/fetch': 0.10.13 '@whatwg-node/promise-helpers': 1.3.2 graphql: 16.9.0 - meros: 1.2.1(@types/node@24.12.2) + meros: 1.3.2(@types/node@24.12.2) tslib: 2.8.1 transitivePeerDependencies: - '@types/node' @@ -24179,6 +24256,21 @@ snapshots: transitivePeerDependencies: - '@types/node' + '@graphql-tools/executor-http@3.2.1(@types/node@24.12.2)(graphql@16.12.0)': + dependencies: + '@graphql-hive/signal': 2.0.0 + '@graphql-tools/executor-common': 1.0.6(graphql@16.12.0) + '@graphql-tools/utils': 11.0.0(graphql@16.12.0) + '@repeaterjs/repeater': 3.0.6 + '@whatwg-node/disposablestack': 0.0.6 + '@whatwg-node/fetch': 0.10.13 + '@whatwg-node/promise-helpers': 1.3.2 + graphql: 16.12.0 + meros: 1.3.2(@types/node@24.12.2) + tslib: 2.8.1 + transitivePeerDependencies: + - '@types/node' + '@graphql-tools/executor-legacy-ws@0.0.11(graphql@16.9.0)': dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.9.0) @@ -24215,6 +24307,18 @@ snapshots: - bufferutil - utf-8-validate + '@graphql-tools/executor-legacy-ws@1.1.26(graphql@16.12.0)': + dependencies: + '@graphql-tools/utils': 11.0.0(graphql@16.12.0) + '@types/ws': 8.5.3 + graphql: 16.12.0 + isomorphic-ws: 5.0.0(ws@8.18.0) + tslib: 2.8.1 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@graphql-tools/executor@0.0.17(graphql@16.9.0)': dependencies: '@graphql-tools/utils': 9.2.1(graphql@16.9.0) @@ -24868,6 +24972,29 @@ snapshots: - uWebSockets.js - utf-8-validate + '@graphql-tools/url-loader@9.1.0(@types/node@24.12.2)(graphql@16.12.0)': + dependencies: + '@graphql-tools/executor-graphql-ws': 3.1.5(graphql@16.12.0) + '@graphql-tools/executor-http': 3.2.1(@types/node@24.12.2)(graphql@16.12.0) + '@graphql-tools/executor-legacy-ws': 1.1.26(graphql@16.12.0) + '@graphql-tools/utils': 11.0.0(graphql@16.12.0) + '@graphql-tools/wrap': 11.1.2(graphql@16.12.0) + '@types/ws': 8.5.3 + '@whatwg-node/fetch': 0.10.13 + '@whatwg-node/promise-helpers': 1.3.2 + graphql: 16.12.0 + isomorphic-ws: 5.0.0(ws@8.18.0) + sync-fetch: 0.6.0 + tslib: 2.8.1 + ws: 8.18.0 + transitivePeerDependencies: + - '@fastify/websocket' + - '@types/node' + - bufferutil + - crossws + - uWebSockets.js + - utf-8-validate + '@graphql-tools/utils@10.11.0(graphql@16.12.0)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) @@ -24919,6 +25046,14 @@ snapshots: graphql: 16.9.0 tslib: 2.8.1 + '@graphql-tools/utils@11.0.0(graphql@16.12.0)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.12.0) + '@whatwg-node/promise-helpers': 1.3.2 + cross-inspect: 1.0.1 + graphql: 16.12.0 + tslib: 2.8.1 + '@graphql-tools/utils@11.0.0(graphql@16.9.0)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) @@ -24927,6 +25062,14 @@ snapshots: graphql: 16.9.0 tslib: 2.8.1 + '@graphql-tools/utils@11.0.1-alpha-20260403104244-04c5cf56aba6702e37b7efb722f6b5158f5a9de2(graphql@16.9.0)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@whatwg-node/promise-helpers': 1.3.2 + cross-inspect: 1.0.1 + graphql: 16.9.0 + tslib: 2.8.1 + '@graphql-tools/utils@9.2.1(graphql@16.9.0)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) @@ -24951,24 +25094,6 @@ snapshots: graphql: 16.9.0 tslib: 2.8.1 - '@graphql-tools/wrap@11.0.5(graphql@16.12.0)': - dependencies: - '@graphql-tools/delegate': 11.1.3(graphql@16.12.0) - '@graphql-tools/schema': 10.0.29(graphql@16.12.0) - '@graphql-tools/utils': 10.11.0(graphql@16.12.0) - '@whatwg-node/promise-helpers': 1.3.2 - graphql: 16.12.0 - tslib: 2.8.1 - - '@graphql-tools/wrap@11.0.5(graphql@16.9.0)': - dependencies: - '@graphql-tools/delegate': 11.1.3(graphql@16.9.0) - '@graphql-tools/schema': 10.0.29(graphql@16.9.0) - '@graphql-tools/utils': 10.11.0(graphql@16.9.0) - '@whatwg-node/promise-helpers': 1.3.2 - graphql: 16.9.0 - tslib: 2.8.1 - '@graphql-tools/wrap@11.1.2(graphql@16.12.0)': dependencies: '@graphql-tools/delegate': 12.0.2(graphql@16.12.0) @@ -25117,9 +25242,9 @@ snapshots: graphql: 16.9.0 graphql-yoga: 5.17.1(graphql@16.9.0) - '@graphql-yoga/plugin-persisted-operations@3.9.0(@graphql-tools/utils@11.0.0(graphql@16.9.0))(graphql-yoga@5.13.3(graphql@16.9.0))(graphql@16.9.0)': + '@graphql-yoga/plugin-persisted-operations@3.9.0(@graphql-tools/utils@11.0.1-alpha-20260403104244-04c5cf56aba6702e37b7efb722f6b5158f5a9de2(graphql@16.9.0))(graphql-yoga@5.13.3(graphql@16.9.0))(graphql@16.9.0)': dependencies: - '@graphql-tools/utils': 11.0.0(graphql@16.9.0) + '@graphql-tools/utils': 11.0.1-alpha-20260403104244-04c5cf56aba6702e37b7efb722f6b5158f5a9de2(graphql@16.9.0) graphql: 16.9.0 graphql-yoga: 5.13.3(graphql@16.9.0) @@ -32323,6 +32448,8 @@ snapshots: dependencies: '@babel/types': 7.28.5 + backo2@1.0.2: {} + bail@2.0.2: {} balanced-match@1.0.2: {} @@ -34321,6 +34448,8 @@ snapshots: eventemitter2@6.4.7: {} + eventemitter3@3.1.2: {} + eventemitter3@4.0.7: {} eventemitter3@5.0.1: {} @@ -36293,6 +36422,8 @@ snapshots: isstream@0.1.2: {} + iterall@1.3.0: {} + iterator.prototype@1.1.5: dependencies: define-data-property: 1.1.4 @@ -37202,10 +37333,6 @@ snapshots: merge2@1.4.1: {} - meros@1.2.1(@types/node@24.12.2): - optionalDependencies: - '@types/node': 24.12.2 - meros@1.2.1(@types/node@25.5.0): optionalDependencies: '@types/node': 25.5.0 @@ -40513,6 +40640,18 @@ snapshots: stylis@4.1.3: {} + subscriptions-transport-ws@0.11.0(graphql@16.12.0): + dependencies: + backo2: 1.0.2 + eventemitter3: 3.1.2 + graphql: 16.12.0 + iterall: 1.3.0 + symbol-observable: 1.2.0 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.13 @@ -40565,6 +40704,14 @@ snapshots: dependencies: tslib: 2.8.1 + symbol-observable@1.2.0: {} + + sync-fetch@0.6.0: + dependencies: + node-fetch: 3.3.2 + timeout-signal: 2.0.0 + whatwg-mimetype: 4.0.0 + sync-fetch@0.6.0-2: dependencies: node-fetch: 3.3.2