-
Notifications
You must be signed in to change notification settings - Fork 310
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix typename injection on alias and inline fragments
- Loading branch information
1 parent
6d6535d
commit ef56db0
Showing
17 changed files
with
255 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { expect, test } from 'vitest' | ||
import { $Index as schema } from '../../../tests/_/schemas/kitchen-sink/graffle/modules/SchemaRuntime.js' | ||
import type { Query } from '../../../tests/_/schemas/kitchen-sink/graffle/modules/SelectionSets.js' | ||
import { Select } from '../2_Select/__.js' | ||
import { injectTypenameOnResultFields } from './schemaErrors.js' | ||
|
||
type CasesQuery = [description: string, queryWithoutTypename: Query, queryWithTypename: Query] | ||
|
||
// todo symmetrical type tests for these cases | ||
// dprint-ignore | ||
test.each<CasesQuery>([ | ||
[`one result field`, { resultNonNull: { } }, { resultNonNull: { __typename: true } }], | ||
[`two result fields`, { resultNonNull: { }, result: { $: { case: `ErrorOne` }}}, { resultNonNull: { __typename: true }, result: { $: { case: `ErrorOne` }, __typename: true } }], | ||
[`no result fields`, { id: true, object: { id: true } }, { id: true, object: { id: true }}], | ||
[`__typename in fragment`, { resultNonNull: { ___: { __typename: true }}}, { resultNonNull: { ___: { __typename: true }, __typename: true } }], | ||
[`root field in fragment`, { ___: { resultNonNull: {} } }, { ___: { resultNonNull: { __typename: true }}}], | ||
[`root field in fragment in alias`, { ___: { resultNonNull: [`x`, {}] } }, { ___: { resultNonNull: [`x`, { __typename: true }] }}], | ||
[`root field alias `, { resultNonNull: [`x`, {}] }, { resultNonNull: [`x`, { __typename: true }] }], | ||
])(`Query %s`, (_, queryWithoutTypenameInput, queryWithTypenameInput) => { | ||
const documentWithTypename = Select.Document.normalizeOrThrow({ query: { x: queryWithTypenameInput as any } }) | ||
const documentWithoutTypename = Select.Document.normalizeOrThrow({ query: { x: queryWithoutTypenameInput as any } }) | ||
|
||
injectTypenameOnResultFields({ | ||
document:documentWithoutTypename, | ||
schema, | ||
}) | ||
|
||
expect(documentWithoutTypename).toMatchObject(documentWithTypename) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import type { RootTypeName } from '../../lib/graphql-plus/graphql.js' | ||
import type { Schema } from '../1_Schema/__.js' | ||
import { Select } from '../2_Select/__.js' | ||
|
||
export const injectTypenameOnResultFields = ( | ||
input: { | ||
operationName?: string | undefined | ||
schema: Schema.Index | ||
document: Select.Document.DocumentNormalized | ||
}, | ||
): Select.Document.DocumentNormalized => { | ||
const { document, operationName, schema } = input | ||
const operation = operationName ? document.operations[operationName] : Object.values(document.operations)[0]! | ||
|
||
if (!operation) { | ||
throw new Error(`Operation not found`) | ||
} | ||
|
||
injectTypenameOnRootResultFields({ | ||
rootTypeName: operation.rootType, | ||
schema, | ||
selectionSet: operation.selectionSet, | ||
}) | ||
|
||
return document | ||
} | ||
|
||
const injectTypenameOnRootResultFields = ( | ||
input: { | ||
schema: Schema.Index | ||
selectionSet: Select.SelectionSet.AnySelectionSet | ||
rootTypeName: RootTypeName | ||
}, | ||
): void => { | ||
const { selectionSet, schema, rootTypeName } = input | ||
|
||
for (const [rootFieldName, fieldValue] of Object.entries(selectionSet)) { | ||
const field = Select.parseSelection(rootFieldName, fieldValue) | ||
|
||
switch (field.type) { | ||
case `InlineFragment`: { | ||
// we need to check contents for result root fields | ||
for (const inlineFragmentSelectionSet of field.selectionSets) { | ||
injectTypenameOnRootResultFields({ | ||
rootTypeName, | ||
schema, | ||
selectionSet: inlineFragmentSelectionSet, | ||
}) | ||
} | ||
continue | ||
} | ||
case `SelectionSet`: { | ||
if (schema.error.rootResultFields[rootTypeName][rootFieldName]) { | ||
field.selectionSet[`__typename`] = true | ||
} | ||
continue | ||
} | ||
case `Alias`: { | ||
if (schema.error.rootResultFields[rootTypeName][rootFieldName]) { | ||
for (const alias of field.aliases) { | ||
// Casting type: This alias is for a field whose type is in rootResultFields | ||
// so it must be a selection set (e.g. not an indicator) | ||
const aliasSelectionSet = alias[1] as Select.SelectionSet.AnySelectionSet | ||
aliasSelectionSet[`__typename`] = true | ||
} | ||
} | ||
continue | ||
} | ||
default: { | ||
continue | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
tests/_/schemas/mutation-only/graffle/modules/SelectionSets.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.