From f87e67c202f6434885f2516fd06aa0981a7300ff Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 10 Jan 2024 20:51:54 +0000 Subject: [PATCH] Add definition merging boilerplate code --- src/api.ts | 32 +++++++++++++++++++++++++++++--- src/namespace.ts | 6 +++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/api.ts b/src/api.ts index badd695f..552a2363 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,4 +1,4 @@ -import { parse as _parse } from '@0no-co/graphql.web'; +import { Kind, parse as _parse } from '@0no-co/graphql.web'; import type { DocumentNode } from '@0no-co/graphql.web'; import type { @@ -59,9 +59,35 @@ function graphql< const Fragments extends readonly [...FragmentDefDecorationLike[]], >( input: In, - _fragments?: Fragments + fragments?: Fragments ): getDocumentNode> { - return _parse(input) as any; + const fragmentNames = new Map(); + const definitions = [...source.definitions]; + const source = _parse(input); + for (const document of fragments) { + for (const definition of document.definitions) { + if (definition.kind === Kind.FRAGMENT_DEFINITION) { + const name = definition.name.value; + if (!fragmentNames.has(definition.name.value)) { + fragmentNames.set(definition.name.value, definition); + definitions.push(definition); + } else if ( + process.env.NODE_ENV !== 'production' && + fragmentNames.get(name) !== definition + ) { + // Fragments with the same names is expected to have the same contents + console.warn( + '[WARNING: Duplicate Fragment] A fragment with name `' + + name + + '` already exists in this document.\n' + + 'While fragment names may not be unique across your source, each name must be unique per document.' + ); + } + } + } + } + + return { kind: Kind.DOCUMENT, definitions }; } /** A GraphQL `DocumentNode` with attached generics for its result data and variables. diff --git a/src/namespace.ts b/src/namespace.ts index a1bfab27..ed34c86d 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -1,4 +1,4 @@ -import type { Kind } from '@0no-co/graphql.web'; +import type { Kind, DocumentNode } from '@0no-co/graphql.web'; import type { DocumentNodeLike } from './parser'; import type { obj } from './utils'; @@ -33,7 +33,7 @@ type getFragmentsOfDocumentsRec = Documents extends readonly [ infer Document, ...infer Rest, ] - ? (Document extends FragmentDefDecorationLike + ? (Document extends { [$tada.fragmentDef]?: any } ? Exclude extends infer FragmentDef extends { kind: Kind.FRAGMENT_DEFINITION; name: any; @@ -45,7 +45,7 @@ type getFragmentsOfDocumentsRec = Documents extends readonly [ getFragmentsOfDocumentsRec : {}; -interface FragmentDefDecorationLike { +interface FragmentDefDecorationLike extends DocumentNode { [$tada.fragmentDef]?: { readonly [$tada.fragmentId]: symbol; kind: Kind.FRAGMENT_DEFINITION;