Skip to content

Commit

Permalink
Align codegen and language server inline fragment __typename use
Browse files Browse the repository at this point in the history
The `withTypenameFieldAddedWhereNeeded` utility in `apollo-language-server`
was updated in #1286 to make sure `__typename`'s are added to inline
fragments, when used by commands like `client:push`. The
`apollo-codegen-core` package currently uses its own copy of
`withTypenameFieldAddedWhereNeeded` however, which was not updated. This
means that operations can be registered (in Apollo's operation registry)
via `client:push` that don't line up with the operations output by codegen.

This commit adjusts the `apollo-codegen-core` package to use the same
`withTypenameFieldAddedWhereNeeded` function as `apollo-language-server`
(which is already a dependency of codegen), to make sure the operations
output from codegen line up with the operations pushed via
`client:push`.
  • Loading branch information
hwillson committed Nov 11, 2021
1 parent 6bcaa78 commit 39a70fb
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 82 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
- Export useful operation sanitization transforms [PR #2057](https://github.com/apollographql/apollo-tooling/pull/2057)
- Preserve directive usages on SchemaDefinition nodes in `buildSchemaFromSDL` [PR #2457](https://github.com/apollographql/apollo-tooling/pull/2457)

- `apollo-language-server` / `apollo-codegen-core`
- Adjust `apollo-codegen-core` to use the same `withTypenameFieldAddedWhereNeeded` utility as `apollo-language-server`, to make sure modified operations align between codegen and anything leveraging the language server utility functions (like the `client:push` command). <br/>
[@hwillson](https://github.com/hwillson) in [#2473](https://github.com/apollographql/apollo-tooling/pull/2473)

## `apollo@2.33.7`

- `apollo-graphql@0.9.4`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ exports[`JSON output should generate JSON output for a query with a fragment spr
\\"fragmentsReferenced\\": [
\\"CharacterDetails\\"
],
\\"sourceWithFragments\\": \\"query HeroAndDetails {\\\\n hero {\\\\n __typename\\\\n id\\\\n ...CharacterDetails\\\\n }\\\\n}\\\\nfragment CharacterDetails on Character {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n primaryFunction\\\\n }\\\\n ... on Human {\\\\n height\\\\n }\\\\n}\\",
\\"operationId\\": \\"9ea2d583a2bcf98ddcedc95a807e34011ff3c0f66fabaf01fa0169e4a4159121\\"
\\"sourceWithFragments\\": \\"query HeroAndDetails {\\\\n hero {\\\\n __typename\\\\n id\\\\n ...CharacterDetails\\\\n }\\\\n}\\\\nfragment CharacterDetails on Character {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n __typename\\\\n primaryFunction\\\\n }\\\\n ... on Human {\\\\n __typename\\\\n height\\\\n }\\\\n}\\",
\\"operationId\\": \\"8382c257b6468c99d5f57b35465ec8b2f8ad6cba4ea6f7dbf4040894787c8e02\\"
}
],
\\"fragments\\": [
Expand All @@ -215,7 +215,7 @@ exports[`JSON output should generate JSON output for a query with a fragment spr
],
\\"fragmentName\\": \\"CharacterDetails\\",
\\"filePath\\": \\"GraphQL request\\",
\\"source\\": \\"fragment CharacterDetails on Character {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n primaryFunction\\\\n }\\\\n ... on Human {\\\\n height\\\\n }\\\\n}\\",
\\"source\\": \\"fragment CharacterDetails on Character {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n __typename\\\\n primaryFunction\\\\n }\\\\n ... on Human {\\\\n __typename\\\\n height\\\\n }\\\\n}\\",
\\"fields\\": [
{
\\"responseName\\": \\"__typename\\",
Expand Down Expand Up @@ -707,7 +707,7 @@ exports[`JSON output should list all interfaces and their implementing types und
\\"operationType\\": \\"query\\",
\\"rootType\\": \\"Query\\",
\\"variables\\": [],
\\"source\\": \\"query HeroForEpisode {\\\\n hero(episode: JEDI) {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n primaryFunction\\\\n }\\\\n }\\\\n}\\",
\\"source\\": \\"query HeroForEpisode {\\\\n hero(episode: JEDI) {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n __typename\\\\n primaryFunction\\\\n }\\\\n }\\\\n}\\",
\\"fields\\": [
{
\\"responseName\\": \\"hero\\",
Expand Down Expand Up @@ -779,8 +779,8 @@ exports[`JSON output should list all interfaces and their implementing types und
\\"fragmentSpreads\\": [],
\\"inlineFragments\\": [],
\\"fragmentsReferenced\\": [],
\\"sourceWithFragments\\": \\"query HeroForEpisode {\\\\n hero(episode: JEDI) {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n primaryFunction\\\\n }\\\\n }\\\\n}\\",
\\"operationId\\": \\"173a7ebf41abd014f3fc54ddd007f6182fca738bd44a1e2d1bb75503c8bf79f6\\"
\\"sourceWithFragments\\": \\"query HeroForEpisode {\\\\n hero(episode: JEDI) {\\\\n __typename\\\\n name\\\\n ... on Droid {\\\\n __typename\\\\n primaryFunction\\\\n }\\\\n }\\\\n}\\",
\\"operationId\\": \\"ea3ecdd4626f2b1423ed6c91cf4a0f1b506b66391c6ab2bb67f1c605bcdcaf8e\\"
}
],
\\"fragments\\": [],
Expand All @@ -807,7 +807,7 @@ exports[`JSON output should list all unions and their types under a \`unionTypes
\\"operationType\\": \\"query\\",
\\"rootType\\": \\"Query\\",
\\"variables\\": [],
\\"source\\": \\"query Search {\\\\n search(text: \\\\\\"an\\\\\\") {\\\\n __typename\\\\n ... on Human {\\\\n name\\\\n height\\\\n }\\\\n ... on Droid {\\\\n name\\\\n primaryFunction\\\\n }\\\\n ... on Starship {\\\\n name\\\\n length\\\\n }\\\\n }\\\\n}\\",
\\"source\\": \\"query Search {\\\\n search(text: \\\\\\"an\\\\\\") {\\\\n __typename\\\\n ... on Human {\\\\n __typename\\\\n name\\\\n height\\\\n }\\\\n ... on Droid {\\\\n __typename\\\\n name\\\\n primaryFunction\\\\n }\\\\n ... on Starship {\\\\n __typename\\\\n name\\\\n length\\\\n }\\\\n }\\\\n}\\",
\\"fields\\": [
{
\\"responseName\\": \\"search\\",
Expand Down Expand Up @@ -935,8 +935,8 @@ exports[`JSON output should list all unions and their types under a \`unionTypes
\\"fragmentSpreads\\": [],
\\"inlineFragments\\": [],
\\"fragmentsReferenced\\": [],
\\"sourceWithFragments\\": \\"query Search {\\\\n search(text: \\\\\\"an\\\\\\") {\\\\n __typename\\\\n ... on Human {\\\\n name\\\\n height\\\\n }\\\\n ... on Droid {\\\\n name\\\\n primaryFunction\\\\n }\\\\n ... on Starship {\\\\n name\\\\n length\\\\n }\\\\n }\\\\n}\\",
\\"operationId\\": \\"9887ff0652e14d678a66769b853c41293d4afb1d1338bbbdb9f84e66979605dd\\"
\\"sourceWithFragments\\": \\"query Search {\\\\n search(text: \\\\\\"an\\\\\\") {\\\\n __typename\\\\n ... on Human {\\\\n __typename\\\\n name\\\\n height\\\\n }\\\\n ... on Droid {\\\\n __typename\\\\n name\\\\n primaryFunction\\\\n }\\\\n ... on Starship {\\\\n __typename\\\\n name\\\\n length\\\\n }\\\\n }\\\\n}\\",
\\"operationId\\": \\"4e878da6864f199125278cef600dbd9609d553cec95f363324dea5ca7410e4c5\\"
}
],
\\"fragments\\": [],
Expand Down
3 changes: 2 additions & 1 deletion packages/apollo-codegen-core/src/compiler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ import {
getFieldDef,
valueFromValueNode,
filePathForNode,
withTypenameFieldAddedWhereNeeded,
isMetaFieldName
} from "../utilities/graphql";

import { withTypenameFieldAddedWhereNeeded } from "apollo-language-server";

export interface CompilerOptions {
addTypename?: boolean;
mergeInFieldsFromFragmentSpreads?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { parse, print } from "graphql";
import {
withTypenameFieldAddedWhereNeeded,
removeConnectionDirectives,
removeClientDirectives
} from "../graphql";
import { removeConnectionDirectives, removeClientDirectives } from "../graphql";
import { withTypenameFieldAddedWhereNeeded } from "apollo-language-server";

describe("typename additions", () => {
it("adds typenames to selectionSets", () => {
Expand Down
32 changes: 0 additions & 32 deletions packages/apollo-codegen-core/src/utilities/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,38 +81,6 @@ const typenameField = {
name: { kind: Kind.NAME, value: "__typename" }
};

export function withTypenameFieldAddedWhereNeeded(ast: ASTNode) {
return visit(ast, {
enter: {
SelectionSet(node: SelectionSetNode) {
return {
...node,
selections: node.selections.filter(
selection =>
!(
selection.kind === "Field" &&
(selection as FieldNode).name.value === "__typename"
)
)
};
}
},
leave(node: ASTNode) {
if (!(node.kind === "Field" || node.kind === "FragmentDefinition"))
return undefined;
if (!node.selectionSet) return undefined;

return {
...node,
selectionSet: {
...node.selectionSet,
selections: [typenameField, ...node.selectionSet.selections]
}
};
}
});
}

export function sourceAt(location: Location) {
return location.source.body.slice(location.start, location.end);
}
Expand Down
66 changes: 33 additions & 33 deletions packages/apollo-language-server/src/graphqlTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1702,108 +1702,108 @@ export enum ValidationErrorType {
* Filter options to exclude by client reference ID, client name, and client version.
*/
export interface ClientInfoFilter {
name?: string | null;
referenceID?: string | null;
name?: string | null;
version?: string | null;
}

/**
* This is stored with a schema when it is uploaded
*/
export interface GitContextInput {
branch?: string | null;
remoteUrl?: string | null;
commit?: string | null;
committer?: string | null;
message?: string | null;
remoteUrl?: string | null;
branch?: string | null;
}

export interface HistoricQueryParameters {
excludedClients?: ClientInfoFilter[] | null;
from?: any | null;
ignoredOperations?: string[] | null;
includedVariants?: string[] | null;
to?: any | null;
queryCountThreshold?: number | null;
queryCountThresholdPercentage?: number | null;
to?: any | null;
ignoredOperations?: string[] | null;
excludedClients?: ClientInfoFilter[] | null;
includedVariants?: string[] | null;
}

export interface IntrospectionDirectiveInput {
args: IntrospectionInputValueInput[];
name: string;
description?: string | null;
isRepeatable?: boolean | null;
locations: IntrospectionDirectiveLocation[];
name: string;
args: IntrospectionInputValueInput[];
isRepeatable?: boolean | null;
}

/**
* __EnumValue introspection type
*/
export interface IntrospectionEnumValueInput {
deprecationReason?: string | null;
name: string;
description?: string | null;
isDeprecated: boolean;
name: string;
deprecationReason?: string | null;
}

/**
* __Field introspection type
*/
export interface IntrospectionFieldInput {
args: IntrospectionInputValueInput[];
deprecationReason?: string | null;
description?: string | null;
isDeprecated: boolean;
name: string;
description?: string | null;
args: IntrospectionInputValueInput[];
type: IntrospectionTypeInput;
isDeprecated: boolean;
deprecationReason?: string | null;
}

/**
* __Value introspection type
*/
export interface IntrospectionInputValueInput {
defaultValue?: string | null;
deprecationReason?: string | null;
description?: string | null;
isDeprecated?: boolean | null;
name: string;
description?: string | null;
type: IntrospectionTypeInput;
defaultValue?: string | null;
isDeprecated?: boolean | null;
deprecationReason?: string | null;
}

/**
* __Schema introspection type
*/
export interface IntrospectionSchemaInput {
description?: string | null;
directives: IntrospectionDirectiveInput[];
mutationType?: IntrospectionTypeRefInput | null;
types?: IntrospectionTypeInput[] | null;
queryType: IntrospectionTypeRefInput;
mutationType?: IntrospectionTypeRefInput | null;
subscriptionType?: IntrospectionTypeRefInput | null;
types?: IntrospectionTypeInput[] | null;
directives: IntrospectionDirectiveInput[];
description?: string | null;
}

/**
* __Type introspection type
*/
export interface IntrospectionTypeInput {
kind: IntrospectionTypeKind;
name?: string | null;
description?: string | null;
enumValues?: IntrospectionEnumValueInput[] | null;
specifiedByUrl?: string | null;
fields?: IntrospectionFieldInput[] | null;
inputFields?: IntrospectionInputValueInput[] | null;
interfaces?: IntrospectionTypeInput[] | null;
kind: IntrospectionTypeKind;
name?: string | null;
ofType?: IntrospectionTypeInput | null;
possibleTypes?: IntrospectionTypeInput[] | null;
specifiedByUrl?: string | null;
enumValues?: IntrospectionEnumValueInput[] | null;
inputFields?: IntrospectionInputValueInput[] | null;
ofType?: IntrospectionTypeInput | null;
}

/**
* Shallow __Type introspection type
*/
export interface IntrospectionTypeRefInput {
kind?: string | null;
name: string;
kind?: string | null;
}

export interface OperationDocumentInput {
Expand All @@ -1823,8 +1823,8 @@ export interface OperationDocumentInput {
* the hash does not need to be and will be computed server-side.
*/
export interface PartialSchemaInput {
hash?: string | null;
sdl?: string | null;
hash?: string | null;
}

export interface RegisteredClientIdentityInput {
Expand All @@ -1834,9 +1834,9 @@ export interface RegisteredClientIdentityInput {
}

export interface RegisteredOperationInput {
signature: string;
document?: string | null;
metadata?: RegisteredOperationMetadataInput | null;
signature: string;
}

export interface RegisteredOperationMetadataInput {
Expand Down
4 changes: 2 additions & 2 deletions packages/apollo-language-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ export * from "./config";
import * as graphqlTypes from "./graphqlTypes";
export { graphqlTypes };

// debug logger
export { Debug } from "./utilities";
// GraphQL utilities
export { Debug, withTypenameFieldAddedWhereNeeded } from "./utilities";
1 change: 1 addition & 0 deletions packages/apollo-language-server/src/utilities/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./debouncer";
export * from "./uri";
export { Debug } from "./debug";
export { withTypenameFieldAddedWhereNeeded } from "./graphql";

0 comments on commit 39a70fb

Please sign in to comment.