Skip to content

Commit

Permalink
Add definition merging boilerplate code
Browse files Browse the repository at this point in the history
  • Loading branch information
kitten committed Jan 10, 2024
1 parent 1aac7a9 commit a8678c6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 14 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-sucrase": "^5.0.1",
"@rollup/plugin-terser": "^0.4.0",
"@types/node": "^20.10.8",
"@typescript-eslint/eslint-plugin": "^6.18.1",
"@typescript-eslint/parser": "^6.18.1",
"dotenv": "^16.0.3",
Expand Down
29 changes: 22 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 27 additions & 4 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { parse as _parse } from '@0no-co/graphql.web';
import type { DocumentNode } from '@0no-co/graphql.web';
import { Kind, parse as _parse } from '@0no-co/graphql.web';
import type { DocumentNode, DefinitionNode } from '@0no-co/graphql.web';

import type {
IntrospectionQuery,
Expand Down Expand Up @@ -59,9 +59,32 @@ function graphql<
const Fragments extends readonly [...FragmentDefDecorationLike[]],
>(
input: In,
_fragments?: Fragments
fragments?: Fragments
): getDocumentNode<In, Schema, getFragmentsOfDocumentsRec<Fragments>> {
return _parse(input) as any;
const definitions = _parse(input).definitions as DefinitionNode[];
const fragmentNames = new Map<string, unknown>();
for (const document of fragments || []) {
for (const definition of document.definitions) {
if (definition.kind !== Kind.FRAGMENT_DEFINITION) {
/*noop*/
} else if (!fragmentNames.has(definition.name.value)) {
fragmentNames.set(definition.name.value, definition);
definitions.push(definition);
} else if (
process.env.NODE_ENV !== 'production' &&
fragmentNames.get(definition.name.value) !== definition
) {
// Fragments with the same names is expected to have the same contents
console.warn(
'[WARNING: Duplicate Fragment] A fragment with name `' +
definition.name.value +
'` 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 } as any;
}

/** A GraphQL `DocumentNode` with attached generics for its result data and variables.
Expand Down
6 changes: 3 additions & 3 deletions src/namespace.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -33,7 +33,7 @@ type getFragmentsOfDocumentsRec<Documents> = Documents extends readonly [
infer Document,
...infer Rest,
]
? (Document extends FragmentDefDecorationLike
? (Document extends { [$tada.fragmentDef]?: any }
? Exclude<Document[$tada.fragmentDef], undefined> extends infer FragmentDef extends {
kind: Kind.FRAGMENT_DEFINITION;
name: any;
Expand All @@ -45,7 +45,7 @@ type getFragmentsOfDocumentsRec<Documents> = Documents extends readonly [
getFragmentsOfDocumentsRec<Rest>
: {};

interface FragmentDefDecorationLike {
interface FragmentDefDecorationLike extends DocumentNode {
[$tada.fragmentDef]?: {
readonly [$tada.fragmentId]: symbol;
kind: Kind.FRAGMENT_DEFINITION;
Expand Down

0 comments on commit a8678c6

Please sign in to comment.