diff --git a/src/api.ts b/src/api.ts index 0b5793b0..58287b38 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,4 +1,5 @@ import { parse as _parse } from '@0no-co/graphql.web'; +import type { DocumentNode } from '@0no-co/graphql.web'; import type { IntrospectionQuery, @@ -10,13 +11,14 @@ import type { import type { decorateDocument, getFragmentsOfDocumentsRec, - FragmentDocumentNode, + FragmentDefDecorationLike, + FragmentDefDecoration, } from './namespace'; import type { getDocumentType } from './selection'; import type { getVariablesType } from './variables'; import type { parseDocument, DocumentNodeLike } from './parser'; -import type { stringLiteral, TypedDocumentNode } from './utils'; +import type { stringLiteral, DocumentDecoration } from './utils'; interface AbstractSetupSchema { introspection: IntrospectionQuery; @@ -44,14 +46,17 @@ type getDocumentNode< ? getDocumentType extends infer Result ? Result extends never ? never - : TypedDocumentNode> & + : TadaDocumentNode< + Result, + getVariablesType, decorateDocument + > : never : never; function graphql< const In extends stringLiteral, - const Fragments extends readonly [...FragmentDocumentNode[]], + const Fragments extends readonly [...FragmentDefDecorationLike[]], >( input: In, _fragments?: Fragments @@ -59,5 +64,32 @@ function graphql< return _parse(input) as any; } +/** A GraphQL `DocumentNode` with attached generics for its result data and variables. + * + * @remarks + * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data` + * shape it delivers on a response in the GraphQL query language. + * + * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape + * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this + * `TypedDocumentNode` type. + * + * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables` + * and resulting `data` using the types provided. + * + * @privateRemarks + * For compatibility reasons this type has been copied and internalized from: + * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10 + * + * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information. + */ +interface TadaDocumentNode< + Result = { [key: string]: any }, + Variables = { [key: string]: any }, + Decoration = never, +> extends DocumentNode, + DocumentDecoration, + FragmentDefDecoration {} + export { parse, graphql }; -export type { setupSchema }; +export type { setupSchema, TadaDocumentNode }; diff --git a/src/namespace.ts b/src/namespace.ts index 3e841164..06d218b9 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -1,5 +1,6 @@ import type { Kind } from '@0no-co/graphql.web'; import type { DocumentNodeLike } from './parser'; +import type { obj } from './utils'; /** Private namespace holding our symbols for markers. * @@ -26,9 +27,11 @@ type decorateDocument = Document['definitions typeCondition: any; } ? { - [$tada.fragmentDef]?: Document['definitions'][0] & { - readonly [$tada.fragmentId]: unique symbol; - }; + [$tada.fragmentDef]?: obj< + Document['definitions'][0] & { + readonly [$tada.fragmentId]: unique symbol; + } + >; } : {}; @@ -36,7 +39,7 @@ type getFragmentsOfDocumentsRec = Documents extends readonly [ infer Document, ...infer Rest, ] - ? (Document extends { [$tada.fragmentDef]?: any } + ? (Document extends FragmentDefDecorationLike ? Exclude extends infer FragmentDef extends { kind: Kind.FRAGMENT_DEFINITION; name: any; @@ -48,13 +51,25 @@ type getFragmentsOfDocumentsRec = Documents extends readonly [ getFragmentsOfDocumentsRec : {}; -type FragmentDocumentNode = { +interface FragmentDefDecorationLike { [$tada.fragmentDef]?: { readonly [$tada.fragmentId]: symbol; kind: Kind.FRAGMENT_DEFINITION; name: any; typeCondition: any; }; -}; +} -export type { $tada, decorateDocument, getFragmentsOfDocumentsRec, FragmentDocumentNode }; +interface FragmentDefDecoration { + [$tada.fragmentDef]?: Definition extends FragmentDefDecorationLike[$tada.fragmentDef] + ? Definition + : never; +} + +export type { + $tada, + decorateDocument, + getFragmentsOfDocumentsRec, + FragmentDefDecorationLike, + FragmentDefDecoration, +}; diff --git a/src/utils.ts b/src/utils.ts index 034384e8..6b30158f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -54,28 +54,3 @@ export interface DocumentDecoration< */ __ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result; } - -/** A GraphQL `DocumentNode` with attached generics for its result data and variables. - * - * @remarks - * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data` - * shape it delivers on a response in the GraphQL query language. - * - * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape - * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this - * `TypedDocumentNode` type. - * - * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables` - * and resulting `data` using the types provided. - * - * @privateRemarks - * For compatibility reasons this type has been copied and internalized from: - * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10 - * - * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information. - */ -export interface TypedDocumentNode< - Result = { [key: string]: any }, - Variables = { [key: string]: any }, -> extends DocumentNode, - DocumentDecoration {}