From a475bce0ea6ec720e981bd9567b281fe074f8fa5 Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Fri, 12 Nov 2021 14:40:31 -0800 Subject: [PATCH 1/7] Update relay compiler to support node _id field --- .../relay-transforms/src/generate_id_field.rs | 4 +- .../src/refetchable_fragment/utils.rs | 2 +- .../src/relay_client_component.rs | 2 +- .../validations/disallow_reserved_aliases.rs | 2 +- compiler/crates/schema-diff/src/check.rs | 2 +- compiler/test-project/src/App.js | 23 +- compiler/test-project/src/Component.js | 2 +- .../AppFriendsListComponent_user.graphql.js | 182 +++++++++++++ .../FriendsListPaginationQuery.graphql.js | 248 ++++++++++++++++++ .../testschema.graphql | 26 +- 10 files changed, 471 insertions(+), 22 deletions(-) create mode 100644 compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js create mode 100644 compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js diff --git a/compiler/crates/relay-transforms/src/generate_id_field.rs b/compiler/crates/relay-transforms/src/generate_id_field.rs index 52c2fe893011d..ac1508b2644f2 100644 --- a/compiler/crates/relay-transforms/src/generate_id_field.rs +++ b/compiler/crates/relay-transforms/src/generate_id_field.rs @@ -114,7 +114,7 @@ impl<'s> Transformer for GenerateIDFieldTransform<'s> { impl<'s> GenerateIDFieldTransform<'s> { fn new(program: &'s Program) -> Self { - let id_name = "id".intern(); + let id_name = "_id".intern(); let schema = &program.schema; let node_interface = match schema.get_type("Node".intern()) { @@ -124,7 +124,7 @@ impl<'s> GenerateIDFieldTransform<'s> { .fields .iter() .find(|&&id| schema.field(id).name.item == id_name) - .expect("Expected `Node` to contain a field named `id`."); + .expect("Expected `Node` to contain a field named `_id`."); Some(NodeInterface { id: node_interface_id, diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs index 700c4ea717e1a..73c3c36a0e05d 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs @@ -37,7 +37,7 @@ lazy_static! { pub static ref CONSTANTS: Constants = Constants { fetchable: "fetchable".intern(), field_name: "field_name".intern(), - id_name: "id".intern(), + id_name: "_id".intern(), node_field_name: "node".intern(), node_type_name: "Node".intern(), viewer_field_name: "viewer".intern(), diff --git a/compiler/crates/relay-transforms/src/relay_client_component.rs b/compiler/crates/relay-transforms/src/relay_client_component.rs index 9d7af8fa5a29e..ac8510adcc76b 100644 --- a/compiler/crates/relay-transforms/src/relay_client_component.rs +++ b/compiler/crates/relay-transforms/src/relay_client_component.rs @@ -30,7 +30,7 @@ lazy_static! { pub static ref RELAY_CLIENT_COMPONENT_DIRECTIVE_NAME: StringKey = "relay_client_component".intern(); static ref STRING_TYPE: StringKey = "String".intern(); - static ref ID_FIELD_NAME: StringKey = "id".intern(); + static ref ID_FIELD_NAME: StringKey = "_id".intern(); static ref NODE_TYPE_NAME: StringKey = "Node".intern(); static ref VIEWER_TYPE_NAME: StringKey = "Viewer".intern(); } diff --git a/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs b/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs index eb701b6c13d96..a3fb86d79bfd8 100644 --- a/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs +++ b/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs @@ -25,7 +25,7 @@ impl<'program> DisallowReservedAliases<'program> { fn new(program: &'program Program) -> Self { Self { program, - reserved_aliases: vec!["id".intern(), "__typename".intern(), "__id".intern()], + reserved_aliases: vec!["_id".intern(), "__typename".intern(), "__id".intern()], } } } diff --git a/compiler/crates/schema-diff/src/check.rs b/compiler/crates/schema-diff/src/check.rs index 1e29ae638a923..a50e67b55ae18 100644 --- a/compiler/crates/schema-diff/src/check.rs +++ b/compiler/crates/schema-diff/src/check.rs @@ -70,7 +70,7 @@ impl SchemaChange { } lazy_static! { - static ref ID_FIELD_KEY: StringKey = "id".intern(); + static ref ID_FIELD_KEY: StringKey = "_id".intern(); static ref JS_FIELD_KEY: StringKey = "js".intern(); static ref NODE_INTERFACE_KEY: StringKey = "Node".intern(); } diff --git a/compiler/test-project/src/App.js b/compiler/test-project/src/App.js index 4da06fbf854d7..9aa9e657ee656 100644 --- a/compiler/test-project/src/App.js +++ b/compiler/test-project/src/App.js @@ -8,9 +8,28 @@ */ graphql` - query AppQuery { - node(id: "test") { + query AppQuery($count: Int, $cursor: ID) { + node(_id: "test") { ...Component_node } + me { + ...AppFriendsListComponent_user + } } `; + +graphql` + fragment AppFriendsListComponent_user on User + @refetchable(queryName: "FriendsListPaginationQuery") { + name + friends(first: $count, after: $cursor) + @connection(key: "FriendsList_user_friends") { + edges { + node { + name + } + } + } + } + `, + diff --git a/compiler/test-project/src/Component.js b/compiler/test-project/src/Component.js index 02adec0ea5d1e..562015f5a8ed6 100644 --- a/compiler/test-project/src/Component.js +++ b/compiler/test-project/src/Component.js @@ -9,6 +9,6 @@ graphql` fragment Component_node on Node { - id + _id } `; diff --git a/compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js b/compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js new file mode 100644 index 0000000000000..a03512ad24888 --- /dev/null +++ b/compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js @@ -0,0 +1,182 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<<76b058b1f7b0810b5e62f46733815296>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { ReaderFragment } from 'relay-runtime'; +import type { FragmentReference } from "relay-runtime"; +type AppFriendsListComponent_user$ref = any; +type AppFriendsListComponent_user$fragmentType = any; +export type { AppFriendsListComponent_user$ref, AppFriendsListComponent_user$fragmentType }; +export type AppFriendsListComponent_user = {| + +name: ?string, + +friends: ?{| + +edges: ?$ReadOnlyArray, + |}, + +_id: string, + +$refType: AppFriendsListComponent_user$ref, +|}; +export type AppFriendsListComponent_user$data = AppFriendsListComponent_user; +export type AppFriendsListComponent_user$key = { + +$data?: AppFriendsListComponent_user$data, + +$fragmentRefs: AppFriendsListComponent_user$ref, + ... +}; +*/ + +var node/*: ReaderFragment*/ = (function(){ +var v0 = [ + "friends" +], +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null +}; +return { + "argumentDefinitions": [ + { + "kind": "RootArgument", + "name": "count" + }, + { + "kind": "RootArgument", + "name": "cursor" + } + ], + "kind": "Fragment", + "metadata": { + "connection": [ + { + "count": "count", + "cursor": "cursor", + "direction": "forward", + "path": (v0/*: any*/) + } + ], + "refetch": { + "connection": { + "forward": { + "count": "count", + "cursor": "cursor" + }, + "backward": null, + "path": (v0/*: any*/) + }, + "fragmentPathInResult": [ + "node" + ], + "operation": require('./FriendsListPaginationQuery.graphql'), + "identifierField": "_id" + } + }, + "name": "AppFriendsListComponent_user", + "selections": [ + (v1/*: any*/), + { + "alias": "friends", + "args": null, + "concreteType": "FriendsConnection", + "kind": "LinkedField", + "name": "__FriendsList_user_friends_connection", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FriendsEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v1/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "_id", + "storageKey": null + } + ], + "type": "User", + "abstractKey": null +}; +})(); + +(node/*: any*/).hash = "d818fa52dd21a91c8e1460b88de07bd9"; + +module.exports = node; diff --git a/compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js b/compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js new file mode 100644 index 0000000000000..812248b6fd62f --- /dev/null +++ b/compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js @@ -0,0 +1,248 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<<1546f284d932f3845de358bcad3f16c3>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { ConcreteRequest } from 'relay-runtime'; +import type { FragmentReference } from "relay-runtime"; +declare export opaque type AppFriendsListComponent_user$ref: FragmentReference; +declare export opaque type AppFriendsListComponent_user$fragmentType: AppFriendsListComponent_user$ref; +export type FriendsListPaginationQueryVariables = {| + count?: ?number, + cursor?: ?string, + _id: string, +|}; +export type FriendsListPaginationQueryResponse = {| + +node: ?{| + +$fragmentRefs: AppFriendsListComponent_user$ref, + |}, +|}; +export type FriendsListPaginationQuery = {| + variables: FriendsListPaginationQueryVariables, + response: FriendsListPaginationQueryResponse, +|}; +*/ + +var node/*: ConcreteRequest*/ = (function(){ +var v0 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "_id" +}, +v1 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "count" +}, +v2 = { + "defaultValue": null, + "kind": "LocalArgument", + "name": "cursor" +}, +v3 = [ + { + "kind": "Variable", + "name": "_id", + "variableName": "_id" + } +], +v4 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "__typename", + "storageKey": null +}, +v5 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "_id", + "storageKey": null +}, +v6 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "name", + "storageKey": null +}, +v7 = [ + { + "kind": "Variable", + "name": "after", + "variableName": "cursor" + }, + { + "kind": "Variable", + "name": "first", + "variableName": "count" + } +]; +return { + "fragment": { + "argumentDefinitions": [ + (v0/*: any*/), + (v1/*: any*/), + (v2/*: any*/) + ], + "kind": "Fragment", + "metadata": null, + "name": "FriendsListPaginationQuery", + "selections": [ + { + "alias": null, + "args": (v3/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "AppFriendsListComponent_user" + } + ], + "storageKey": null + } + ], + "type": "Query", + "abstractKey": null + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [ + (v1/*: any*/), + (v2/*: any*/), + (v0/*: any*/) + ], + "kind": "Operation", + "name": "FriendsListPaginationQuery", + "selections": [ + { + "alias": null, + "args": (v3/*: any*/), + "concreteType": null, + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v4/*: any*/), + (v5/*: any*/), + { + "kind": "InlineFragment", + "selections": [ + (v6/*: any*/), + { + "alias": null, + "args": (v7/*: any*/), + "concreteType": "FriendsConnection", + "kind": "LinkedField", + "name": "friends", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "FriendsEdge", + "kind": "LinkedField", + "name": "edges", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "node", + "plural": false, + "selections": [ + (v6/*: any*/), + (v5/*: any*/), + (v4/*: any*/) + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "cursor", + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": null, + "concreteType": "PageInfo", + "kind": "LinkedField", + "name": "pageInfo", + "plural": false, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "endCursor", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "hasNextPage", + "storageKey": null + } + ], + "storageKey": null + } + ], + "storageKey": null + }, + { + "alias": null, + "args": (v7/*: any*/), + "filters": null, + "handle": "connection", + "key": "FriendsList_user_friends", + "kind": "LinkedHandle", + "name": "friends" + } + ], + "type": "User", + "abstractKey": null + } + ], + "storageKey": null + } + ] + }, + "params": { + "cacheID": "48e7e53c894c3797ec3f3480d209c212", + "id": null, + "metadata": {}, + "name": "FriendsListPaginationQuery", + "operationKind": "query", + "text": "query FriendsListPaginationQuery(\n $count: Int\n $cursor: ID\n $_id: ID!\n) {\n node(_id: $_id) {\n __typename\n ...AppFriendsListComponent_user\n _id\n }\n}\n\nfragment AppFriendsListComponent_user on User {\n name\n friends(first: $count, after: $cursor) {\n edges {\n node {\n name\n _id\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n _id\n}\n" + } +}; +})(); + +(node/*: any*/).hash = "d818fa52dd21a91c8e1460b88de07bd9"; + +module.exports = node; diff --git a/packages/relay-test-utils-internal/testschema.graphql b/packages/relay-test-utils-internal/testschema.graphql index f6af83a1ea71e..072743a6f102c 100644 --- a/packages/relay-test-utils-internal/testschema.graphql +++ b/packages/relay-test-utils-internal/testschema.graphql @@ -46,7 +46,7 @@ type Query { neverNode: NeverNode named: Named me: User - node(id: ID): Node + node(_id: ID): Node node_id_required(id: ID!): Node nodes(ids: [ID!]): [Node] settings(environment: Environment): Settings @@ -77,7 +77,7 @@ interface AllConcreteTypesImplementNode { } type FakeNode { - id: ID! + _id: ID! } type NonNode { @@ -301,7 +301,7 @@ type Comment implements Node { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -454,7 +454,7 @@ type Feedback implements Node & HasJsField { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -487,7 +487,7 @@ interface FeedUnit { actor: Actor actorCount: Int feedback: Feedback - id: ID! + _id: ID! message: Text tracking: String actor_key: ID! @@ -583,7 +583,7 @@ interface Node { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -621,7 +621,7 @@ interface Actor { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String name: String nameRenderer(supported: [String!]): UserNameRenderer @@ -676,7 +676,7 @@ type Page implements Node & Actor & Entity { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -749,7 +749,7 @@ type NonNodeStory implements FeedUnit @fetchable(field_name: "fetch_id") { actor: Actor actorCount: Int feedback: Feedback - id: ID! + _id: ID! fetch_id: ID! message: Text tracking: String @@ -807,7 +807,7 @@ type PhotoStory implements FeedUnit & Node { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -870,7 +870,7 @@ type Story implements FeedUnit & Node & MaybeNodeInterface { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -1043,7 +1043,7 @@ type User implements Named & Node & Actor & HasJsField & Entity & AllConcreteTyp traits: [PersonalityTraits] ): FriendsConnection hometown: Page - id: ID! + _id: ID! js(module: String!, id: String): JSDependency lastName: String likers(first: Int): LikersOfContentConnection @@ -1220,7 +1220,7 @@ type IDFieldTests { object: IDFieldIsObject } type IDFieldIsIDNonNull { - id: ID! + _id: ID! } type IDFieldIsID { id: ID From 6ddf16272ad8ee366208894dc34d8f240f8b8b92 Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Fri, 12 Nov 2021 16:17:33 -0800 Subject: [PATCH 2/7] Mostly working configurable node interface ID --- .../relay-codegen/tests/client_edges/mod.rs | 2 +- .../relay-compiler-playground/src/lib.rs | 1 + .../relay-compiler/src/build_project/mod.rs | 1 + compiler/crates/relay-compiler/src/config.rs | 11 +++++++++ .../tests/compile_relay_artifacts/mod.rs | 1 + .../crates/relay-lsp/src/graphql_tools/mod.rs | 1 + .../relay-transforms/src/apply_transforms.rs | 24 +++++++++++++------ .../relay-transforms/src/client_edges.rs | 10 ++++---- .../relay-transforms/src/generate_id_field.rs | 10 ++++---- .../fetchable_query_generator.rs | 9 ++++--- .../src/refetchable_fragment/mod.rs | 9 +++++-- .../node_query_generator.rs | 24 ++++++++++++------- .../query_query_generator.rs | 1 + .../src/refetchable_fragment/utils.rs | 2 -- .../viewer_query_generator.rs | 1 + .../src/relay_client_component.rs | 1 - .../validations/disallow_reserved_aliases.rs | 2 +- .../tests/client_edges/mod.rs | 2 +- .../relay-typegen/tests/generate_flow/mod.rs | 1 + .../tests/generate_typescript/mod.rs | 1 + compiler/crates/schema-diff/src/check.rs | 2 +- compiler/test-project/relay.json | 3 ++- 22 files changed, 82 insertions(+), 37 deletions(-) diff --git a/compiler/crates/relay-codegen/tests/client_edges/mod.rs b/compiler/crates/relay-codegen/tests/client_edges/mod.rs index bc6bb33f6057f..1a807bd849dd0 100644 --- a/compiler/crates/relay-codegen/tests/client_edges/mod.rs +++ b/compiler/crates/relay-codegen/tests/client_edges/mod.rs @@ -22,7 +22,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { let ir = build(&schema, &ast.definitions).unwrap(); let program = Program::from_definitions(Arc::clone(&schema), ir); let next_program = sort_selections( - &client_edges(&program) + &client_edges(&program, None) .and_then(|program| relay_resolvers(&program, true)) .unwrap(), ); diff --git a/compiler/crates/relay-compiler-playground/src/lib.rs b/compiler/crates/relay-compiler-playground/src/lib.rs index f6f33561ce269..91f6238d9cb31 100644 --- a/compiler/crates/relay-compiler-playground/src/lib.rs +++ b/compiler/crates/relay-compiler-playground/src/lib.rs @@ -310,6 +310,7 @@ fn get_programs( base_fragment_names, &connection_interface, Arc::new(feature_flags), + None, &None, Arc::new(perf_logger), None, diff --git a/compiler/crates/relay-compiler/src/build_project/mod.rs b/compiler/crates/relay-compiler/src/build_project/mod.rs index 37575cb2a9296..ea98de472f633 100644 --- a/compiler/crates/relay-compiler/src/build_project/mod.rs +++ b/compiler/crates/relay-compiler/src/build_project/mod.rs @@ -134,6 +134,7 @@ pub fn transform_program( base_fragment_names, &config.connection_interface, Arc::clone(&project_config.feature_flags), + project_config.node_interface_id_field, &project_config.test_path_regex, perf_logger, Some(print_stats), diff --git a/compiler/crates/relay-compiler/src/config.rs b/compiler/crates/relay-compiler/src/config.rs index f2231bc97099e..d6703093998c0 100644 --- a/compiler/crates/relay-compiler/src/config.rs +++ b/compiler/crates/relay-compiler/src/config.rs @@ -273,6 +273,7 @@ impl Config { skip_types_for_artifact: None, rollout: config_file_project.rollout, js_module_format: config_file_project.js_module_format, + node_interface_id_field: config_file_project.node_interface_id_field, }; Ok((project_name, project_config)) }) @@ -517,6 +518,7 @@ pub struct ProjectConfig { pub skip_types_for_artifact: Option bool) + Send + Sync>>, pub rollout: Rollout, pub js_module_format: JsModuleFormat, + pub node_interface_id_field: Option, } impl Debug for ProjectConfig { @@ -541,6 +543,7 @@ impl Debug for ProjectConfig { skip_types_for_artifact, rollout, js_module_format, + node_interface_id_field, } = self; f.debug_struct("ProjectConfig") .field("name", name) @@ -576,6 +579,7 @@ impl Debug for ProjectConfig { ) .field("rollout", rollout) .field("js_module_format", js_module_format) + .field("node_interface_id_field", node_interface_id_field) .finish() } } @@ -679,6 +683,9 @@ pub struct SingleProjectConfigFile { /// It contains URL and addition parameters that will be included /// with the request (think API_KEY, APP_ID, etc...) pub persist_config: Option, + + /// The name of the `id` field that exists on the `Node` interface. + pub node_interface_id_field: Option, } impl Default for SingleProjectConfigFile { @@ -694,6 +701,7 @@ impl Default for SingleProjectConfigFile { custom_scalars: Default::default(), eager_es_modules: false, persist_config: None, + node_interface_id_field: None, } } } @@ -902,6 +910,9 @@ struct ConfigFileProject { #[serde(default)] js_module_format: JsModuleFormat, + + #[serde(default)] + pub node_interface_id_field: Option, } #[derive(Debug, Serialize, Deserialize)] diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs index a03b4ab9b7236..fd920d7be718d 100644 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs @@ -90,6 +90,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { Default::default(), &connection_interface, Arc::new(feature_flags), + None, &None, Arc::new(ConsoleLogger), None, diff --git a/compiler/crates/relay-lsp/src/graphql_tools/mod.rs b/compiler/crates/relay-lsp/src/graphql_tools/mod.rs index 3a586a31c83ed..b37ac564565ba 100644 --- a/compiler/crates/relay-lsp/src/graphql_tools/mod.rs +++ b/compiler/crates/relay-lsp/src/graphql_tools/mod.rs @@ -134,6 +134,7 @@ fn transform_program( Default::default(), &config.connection_interface, Arc::clone(&project_config.feature_flags), + project_config.node_interface_id_field, &None, perf_logger, None, diff --git a/compiler/crates/relay-transforms/src/apply_transforms.rs b/compiler/crates/relay-transforms/src/apply_transforms.rs index 64f2d1df3ba0e..3619209795799 100644 --- a/compiler/crates/relay-transforms/src/apply_transforms.rs +++ b/compiler/crates/relay-transforms/src/apply_transforms.rs @@ -29,6 +29,7 @@ pub fn apply_transforms( base_fragment_names: Arc, connection_interface: &ConnectionInterface, feature_flags: Arc, + node_interface_id_field: Option, test_path_regex: &Option, perf_logger: Arc, print_stats: Option ()>, @@ -55,6 +56,7 @@ where Arc::clone(&program), connection_interface, Arc::clone(&feature_flags), + node_interface_id_field, Arc::clone(&base_fragment_names), Arc::clone(&perf_logger), )?; @@ -64,6 +66,7 @@ where let operation_program = apply_operation_transforms( project_name, Arc::clone(&common_program), + node_interface_id_field, connection_interface, Arc::clone(&base_fragment_names), Arc::clone(&perf_logger), @@ -108,6 +111,7 @@ where project_name, Arc::clone(&program), Arc::clone(&feature_flags), + node_interface_id_field, Arc::clone(&base_fragment_names), Arc::clone(&perf_logger), ) @@ -129,7 +133,8 @@ fn apply_common_transforms( program: Arc, connection_interface: &ConnectionInterface, feature_flags: Arc, - base_fragment_names: Arc, + node_interface_id_field: Option, + base_fragment_names: Arc>, perf_logger: Arc, ) -> DiagnosticsResult> { let log_event = perf_logger.create_event("apply_common_transforms"); @@ -148,11 +153,10 @@ fn apply_common_transforms( transform_subscriptions(&program) })?; program = log_event.time("transform_refetchable_fragment", || { - transform_refetchable_fragment(&program, &base_fragment_names, false) + transform_refetchable_fragment(&program, node_interface_id_field, &base_fragment_names, false) })?; - program = log_event.time("client_edges", || client_edges(&program))?; - + program = log_event.time("client_edges", || client_edges(&program, node_interface_id_field))?; program = log_event.time("relay_resolvers", || { relay_resolvers(&program, feature_flags.enable_relay_resolver_transform) })?; @@ -225,6 +229,7 @@ fn apply_reader_transforms( fn apply_operation_transforms( project_name: StringKey, program: Arc, + node_interface_id_field: Option, connection_interface: &ConnectionInterface, base_fragment_names: Arc, perf_logger: Arc, @@ -239,7 +244,7 @@ fn apply_operation_transforms( program = log_event.time("split_module_import", || { split_module_import(&program, &base_fragment_names) }); - program = log_event.time("generate_id_field", || generate_id_field(&program)); + program = log_event.time("generate_id_field", || generate_id_field(&program, node_interface_id_field)); program = log_event.time("declarative_connection", || { transform_declarative_connection(&program, connection_interface) })?; @@ -397,7 +402,12 @@ fn apply_typegen_transforms( project_name: StringKey, program: Arc, feature_flags: Arc, +<<<<<<< HEAD base_fragment_names: Arc, +======= + node_interface_id_field: Option, + base_fragment_names: Arc>, +>>>>>>> d4315a7d83d (Mostly working configurable node interface ID) perf_logger: Arc, ) -> DiagnosticsResult> { let log_event = perf_logger.create_event("apply_typegen_transforms"); @@ -411,7 +421,7 @@ fn apply_typegen_transforms( transform_subscriptions(&program) })?; program = log_event.time("required_directive", || required_directive(&program))?; - program = log_event.time("client_edges", || client_edges(&program))?; + program = log_event.time("client_edges", || client_edges(&program, node_interface_id_field))?; program = log_event.time( "transform_assignable_fragment_spreads_in_regular_queries", || transform_assignable_fragment_spreads_in_regular_queries(&program), @@ -424,7 +434,7 @@ fn apply_typegen_transforms( })?; log_event.time("flatten", || flatten(&mut program, false, false))?; program = log_event.time("transform_refetchable_fragment", || { - transform_refetchable_fragment(&program, &base_fragment_names, true) + transform_refetchable_fragment(&program, node_interface_id_field, &base_fragment_names, true) })?; program = log_event.time("remove_base_fragments", || { remove_base_fragments(&program, base_fragment_names) diff --git a/compiler/crates/relay-transforms/src/client_edges.rs b/compiler/crates/relay-transforms/src/client_edges.rs index 461bde02a36b7..77d1b85a4cf96 100644 --- a/compiler/crates/relay-transforms/src/client_edges.rs +++ b/compiler/crates/relay-transforms/src/client_edges.rs @@ -79,8 +79,8 @@ impl<'a> ClientEdgeMetadata<'a> { }) } } -pub fn client_edges(program: &Program) -> DiagnosticsResult { - let mut transform = ClientEdgesTransform::new(program); +pub fn client_edges(program: &Program, node_interface_id_field: Option) -> DiagnosticsResult { + let mut transform = ClientEdgesTransform::new(program, node_interface_id_field); let mut next_program = transform .transform_program(program) .replace_or_else(|| program.clone()); @@ -106,12 +106,14 @@ struct ClientEdgesTransform<'program> { new_fragments: Vec>, new_operations: Vec, errors: Vec, + node_interface_id_field: Option, } impl<'program> ClientEdgesTransform<'program> { - fn new(program: &'program Program) -> Self { + fn new(program: &'program Program, node_interface_id_field: Option) -> Self { Self { program, + node_interface_id_field, path: Default::default(), query_names: Default::default(), document_name: Default::default(), @@ -169,7 +171,7 @@ impl<'program> ClientEdgesTransform<'program> { selections, }; - let mut transformer = RefetchableFragment::new(self.program, false); + let mut transformer = RefetchableFragment::new(self.program, false, self.node_interface_id_field); let refetchable_fragment = transformer .transform_refetch_fragment_with_refetchable_directive( diff --git a/compiler/crates/relay-transforms/src/generate_id_field.rs b/compiler/crates/relay-transforms/src/generate_id_field.rs index ac1508b2644f2..187d2dec1ca52 100644 --- a/compiler/crates/relay-transforms/src/generate_id_field.rs +++ b/compiler/crates/relay-transforms/src/generate_id_field.rs @@ -20,8 +20,8 @@ use std::{ /// A transform that adds an `id` field on any type that has an id field but /// where there is no unaliased `id` selection. -pub fn generate_id_field(program: &Program) -> Program { - let mut transform = GenerateIDFieldTransform::new(program); +pub fn generate_id_field(program: &Program, node_interface_id_field: Option) -> Program { + let mut transform = GenerateIDFieldTransform::new(program, node_interface_id_field); transform .transform_program(program) .replace_or_else(|| program.clone()) @@ -113,8 +113,8 @@ impl<'s> Transformer for GenerateIDFieldTransform<'s> { } impl<'s> GenerateIDFieldTransform<'s> { - fn new(program: &'s Program) -> Self { - let id_name = "_id".intern(); + fn new(program: &'s Program, node_interface_id_field: Option) -> Self { + let id_name = node_interface_id_field.unwrap_or("id".intern()); let schema = &program.schema; let node_interface = match schema.get_type("Node".intern()) { @@ -124,7 +124,7 @@ impl<'s> GenerateIDFieldTransform<'s> { .fields .iter() .find(|&&id| schema.field(id).name.item == id_name) - .expect("Expected `Node` to contain a field named `_id`."); + .expect(&format!("Expected `Node` to contain a field named `{:}`.", id_name).to_string()); Some(NodeInterface { id: node_interface_id, diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs index a66c867377173..6d1e4543eb919 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs @@ -22,10 +22,13 @@ use std::sync::Arc; fn build_refetch_operation( schema: &SDLSchema, + node_interface_id_field: Option, fragment: &Arc, query_name: StringKey, variables_map: &VariableMap, ) -> DiagnosticsResult> { + let id_name = node_interface_id_field.unwrap_or("id".intern()); + if let Some(identifier_field_name) = get_fetchable_field_name(fragment, schema)? { let identifier_field_id = get_identifier_field_id(fragment, schema, identifier_field_name)?; @@ -58,7 +61,7 @@ fn build_refetch_operation( ), }); let mut variable_definitions = build_operation_variable_definitions(&fragment); - if let Some(id_argument) = variable_definitions.named(CONSTANTS.id_name) { + if let Some(id_argument) = variable_definitions.named(id_name) { return Err(vec![Diagnostic::error( ValidationMessage::RefetchableFragmentOnNodeWithExistingID { fragment_name: fragment.name.item, @@ -67,7 +70,7 @@ fn build_refetch_operation( )]); } variable_definitions.push(VariableDefinition { - name: WithLocation::new(fragment.name.location, CONSTANTS.id_name), + name: WithLocation::new(fragment.name.location, id_name), type_: id_arg.type_.non_null(), default_value: None, directives: vec![], @@ -83,7 +86,7 @@ fn build_refetch_operation( value: WithLocation::new( fragment.name.location, Value::Variable(Variable { - name: WithLocation::new(fragment.name.location, CONSTANTS.id_name), + name: WithLocation::new(fragment.name.location, id_name), type_: id_arg.type_.non_null(), }), ), diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/mod.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/mod.rs index 60bc3f438759c..39a7704139b3c 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/mod.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/mod.rs @@ -54,13 +54,14 @@ pub use self::refetchable_directive::REFETCHABLE_NAME; /// Fragment to Root IR nodes. pub fn transform_refetchable_fragment( program: &Program, + node_interface_id_field: Option, base_fragment_names: &'_ StringKeySet, for_typegen: bool, ) -> DiagnosticsResult { let mut next_program = Program::new(Arc::clone(&program.schema)); let query_type = program.schema.query_type().unwrap(); - let mut transformer = RefetchableFragment::new(program, for_typegen); + let mut transformer = RefetchableFragment::new(program, for_typegen, node_interface_id_field); for operation in program.operations() { next_program.insert_operation(Arc::clone(operation)); @@ -102,15 +103,17 @@ pub struct RefetchableFragment<'program> { existing_refetch_operations: ExistingRefetchOperations, for_typegen: bool, program: &'program Program, + node_interface_id_field: Option, } impl<'program> RefetchableFragment<'program> { - pub fn new(program: &'program Program, for_typegen: bool) -> Self { + pub fn new(program: &'program Program, for_typegen: bool, node_interface_id_field: Option) -> Self { RefetchableFragment { connection_constants: Default::default(), existing_refetch_operations: Default::default(), for_typegen, program, + node_interface_id_field, } } @@ -145,6 +148,7 @@ impl<'program> RefetchableFragment<'program> { for generator in GENERATORS.iter() { if let Some(refetch_root) = (generator.build_refetch_operation)( &self.program.schema, + self.node_interface_id_field, fragment, refetchable_directive.query_name.item, &variables_map, @@ -294,6 +298,7 @@ impl<'program> RefetchableFragment<'program> { type BuildRefetchOperationFn = fn( schema: &SDLSchema, + node_interface_id_field: Option, fragment: &Arc, query_name: StringKey, variables_map: &VariableMap, diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs index f3194c2537d3c..49f6e5b76185c 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs @@ -16,16 +16,19 @@ use graphql_ir::{ Argument, Field, FragmentDefinition, InlineFragment, LinkedField, ScalarField, Selection, ValidationMessage, Value, Variable, VariableDefinition, }; -use intern::string_key::StringKey; +use intern::string_key::{Intern,StringKey}; use schema::{Argument as ArgumentDef, FieldID, InterfaceID, SDLSchema, Schema, Type}; use std::sync::Arc; fn build_refetch_operation( schema: &SDLSchema, + node_interface_id_field: Option, fragment: &Arc, query_name: StringKey, variables_map: &VariableMap, ) -> DiagnosticsResult> { + let id_name = node_interface_id_field.unwrap_or("id".intern()); + let node_interface_id = schema.get_type(CONSTANTS.node_type_name).and_then(|type_| { if let Type::Interface(id) = type_ { Some(id) @@ -33,6 +36,7 @@ fn build_refetch_operation( None } }); + match node_interface_id { None => Ok(None), Some(node_interface_id) => { @@ -71,7 +75,7 @@ fn build_refetch_operation( // Check if the fragment type have an `id` field let should_generate_inline_fragment_on_node = schema - .named_field(fragment.type_condition, CONSTANTS.id_name) + .named_field(fragment.type_condition, id_name) .is_none(); let query_type = schema.query_type().unwrap(); @@ -81,7 +85,8 @@ fn build_refetch_operation( let id_field_id = *node_interface .fields .iter() - .find(|&&id| schema.field(id).name.item == CONSTANTS.id_name) + .find(|&&id| schema.field(id).name.item == id_name) + // TODO: Fix this error message .expect("Expected `Node` to contain a field named `id`."); let fragment = Arc::new(FragmentDefinition { @@ -90,7 +95,7 @@ fn build_refetch_operation( RefetchableMetadata { operation_name: query_name, path: vec![CONSTANTS.node_field_name], - identifier_field: Some(CONSTANTS.id_name), + identifier_field: Some(id_name), }, ), used_global_variables: build_used_global_variables( @@ -99,6 +104,7 @@ fn build_refetch_operation( )?, variable_definitions: fragment.variable_definitions.clone(), selections: enforce_selections_with_id_field( + node_interface_id_field, fragment, schema, id_field_id, @@ -111,7 +117,7 @@ fn build_refetch_operation( ..fragment.as_ref().clone() }); let mut variable_definitions = build_operation_variable_definitions(&fragment); - if let Some(id_argument) = variable_definitions.named(CONSTANTS.id_name) { + if let Some(id_argument) = variable_definitions.named(id_name) { return Err(vec![Diagnostic::error( ValidationMessage::RefetchableFragmentOnNodeWithExistingID { fragment_name: fragment.name.item, @@ -121,7 +127,7 @@ fn build_refetch_operation( } variable_definitions.push(VariableDefinition { - name: WithLocation::new(fragment.name.location, CONSTANTS.id_name), + name: WithLocation::new(fragment.name.location, id_name), type_: id_arg.type_.non_null(), default_value: None, directives: vec![], @@ -136,7 +142,7 @@ fn build_refetch_operation( value: WithLocation::new( fragment.name.location, Value::Variable(Variable { - name: WithLocation::new(fragment.name.location, CONSTANTS.id_name), + name: WithLocation::new(fragment.name.location, id_name), type_: id_arg.type_.non_null(), }), ), @@ -174,15 +180,17 @@ fn get_node_field_id_and_id_arg<'s>( } fn enforce_selections_with_id_field( + node_interface_id_field: Option, fragment: &FragmentDefinition, schema: &SDLSchema, id_field_id: FieldID, node_interface_id: Option, ) -> Vec { + let id_name = node_interface_id_field.unwrap_or("id".intern()); let mut next_selections = fragment.selections.clone(); let has_id_field = next_selections.iter().any(|sel| { if let Selection::ScalarField(field) = sel { - field.alias_or_name(schema) == CONSTANTS.id_name + field.alias_or_name(schema) == id_name && schema.field(field.definition.item).type_ == schema.field(id_field_id).type_ } else { false diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/query_query_generator.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/query_query_generator.rs index 54fdd40b1d507..2872e3e77cecd 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/query_query_generator.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/query_query_generator.rs @@ -19,6 +19,7 @@ use std::sync::Arc; fn build_refetch_operation( schema: &SDLSchema, + _node_interface_id_field: Option, fragment: &Arc, query_name: StringKey, variables_map: &VariableMap, diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs index 73c3c36a0e05d..fc8760cc5c943 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/utils.rs @@ -26,7 +26,6 @@ associated_data_impl!(RefetchableMetadata); pub struct Constants { pub fetchable: StringKey, pub field_name: StringKey, - pub id_name: StringKey, pub node_field_name: StringKey, pub node_type_name: StringKey, pub viewer_field_name: StringKey, @@ -37,7 +36,6 @@ lazy_static! { pub static ref CONSTANTS: Constants = Constants { fetchable: "fetchable".intern(), field_name: "field_name".intern(), - id_name: "_id".intern(), node_field_name: "node".intern(), node_type_name: "Node".intern(), viewer_field_name: "viewer".intern(), diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/viewer_query_generator.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/viewer_query_generator.rs index 0ad99b3f25b9f..d1b1c12487768 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/viewer_query_generator.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/viewer_query_generator.rs @@ -19,6 +19,7 @@ use std::sync::Arc; fn build_refetch_operation( schema: &SDLSchema, + _node_interface_id_field: Option, fragment: &Arc, query_name: StringKey, variables_map: &VariableMap, diff --git a/compiler/crates/relay-transforms/src/relay_client_component.rs b/compiler/crates/relay-transforms/src/relay_client_component.rs index ac8510adcc76b..e428d8b64e2ae 100644 --- a/compiler/crates/relay-transforms/src/relay_client_component.rs +++ b/compiler/crates/relay-transforms/src/relay_client_component.rs @@ -30,7 +30,6 @@ lazy_static! { pub static ref RELAY_CLIENT_COMPONENT_DIRECTIVE_NAME: StringKey = "relay_client_component".intern(); static ref STRING_TYPE: StringKey = "String".intern(); - static ref ID_FIELD_NAME: StringKey = "_id".intern(); static ref NODE_TYPE_NAME: StringKey = "Node".intern(); static ref VIEWER_TYPE_NAME: StringKey = "Viewer".intern(); } diff --git a/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs b/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs index a3fb86d79bfd8..eb701b6c13d96 100644 --- a/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs +++ b/compiler/crates/relay-transforms/src/validations/disallow_reserved_aliases.rs @@ -25,7 +25,7 @@ impl<'program> DisallowReservedAliases<'program> { fn new(program: &'program Program) -> Self { Self { program, - reserved_aliases: vec!["_id".intern(), "__typename".intern(), "__id".intern()], + reserved_aliases: vec!["id".intern(), "__typename".intern(), "__id".intern()], } } } diff --git a/compiler/crates/relay-transforms/tests/client_edges/mod.rs b/compiler/crates/relay-transforms/tests/client_edges/mod.rs index 1d26822375ad8..051a76dd9f6a8 100644 --- a/compiler/crates/relay-transforms/tests/client_edges/mod.rs +++ b/compiler/crates/relay-transforms/tests/client_edges/mod.rs @@ -24,7 +24,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { let ir = build(&schema, &ast.definitions).unwrap(); let program = Program::from_definitions(Arc::clone(&schema), ir); - let mut next_program = client_edges(&program) + let mut next_program = client_edges(&program, None) .map_err(|diagnostics| diagnostics_to_sorted_string(fixture.content, &diagnostics))?; next_program = relay_resolvers(&next_program, true) diff --git a/compiler/crates/relay-typegen/tests/generate_flow/mod.rs b/compiler/crates/relay-typegen/tests/generate_flow/mod.rs index f5339b608ea0d..393053b758417 100644 --- a/compiler/crates/relay-typegen/tests/generate_flow/mod.rs +++ b/compiler/crates/relay-typegen/tests/generate_flow/mod.rs @@ -54,6 +54,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { Default::default(), &ConnectionInterface::default(), Arc::new(feature_flags), + None, &None, Arc::new(ConsoleLogger), None, diff --git a/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs b/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs index 50373dac7fa97..37b725c01a04c 100644 --- a/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs +++ b/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs @@ -42,6 +42,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { Default::default(), &ConnectionInterface::default(), Arc::new(FeatureFlags::default()), + None, &None, Arc::new(ConsoleLogger), None, diff --git a/compiler/crates/schema-diff/src/check.rs b/compiler/crates/schema-diff/src/check.rs index a50e67b55ae18..1e29ae638a923 100644 --- a/compiler/crates/schema-diff/src/check.rs +++ b/compiler/crates/schema-diff/src/check.rs @@ -70,7 +70,7 @@ impl SchemaChange { } lazy_static! { - static ref ID_FIELD_KEY: StringKey = "_id".intern(); + static ref ID_FIELD_KEY: StringKey = "id".intern(); static ref JS_FIELD_KEY: StringKey = "js".intern(); static ref NODE_INTERFACE_KEY: StringKey = "Node".intern(); } diff --git a/compiler/test-project/relay.json b/compiler/test-project/relay.json index de7cee9f83957..ea0225f2c61a5 100644 --- a/compiler/test-project/relay.json +++ b/compiler/test-project/relay.json @@ -13,7 +13,8 @@ "test": { "customScalarTypes": {}, "enumModuleSuffix": ".test", - "schema": "packages/relay-test-utils-internal/testschema.graphql" + "schema": "packages/relay-test-utils-internal/testschema.graphql", + "nodeInterfaceIdField": "_id" } } } From 71f921d2f58b93a21afeefe0f2e99822f60f71a2 Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Fri, 12 Nov 2021 16:27:05 -0800 Subject: [PATCH 3/7] Wire through the rest of the id fields --- .../relay-compiler/src/build_project/mod.rs | 4 ++-- .../relay-compiler/src/compiler_state.rs | 10 +++++----- .../src/server/lsp_state_resources.rs | 4 ++-- .../node_query_generator.rs | 3 +-- compiler/crates/schema-diff/src/check.rs | 20 +++++++++++-------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/compiler/crates/relay-compiler/src/build_project/mod.rs b/compiler/crates/relay-compiler/src/build_project/mod.rs index ea98de472f633..182c3af02ad5a 100644 --- a/compiler/crates/relay-compiler/src/build_project/mod.rs +++ b/compiler/crates/relay-compiler/src/build_project/mod.rs @@ -157,9 +157,9 @@ pub fn build_programs( ) -> Result { let project_name = project_config.name; let is_incremental_build = compiler_state.has_processed_changes() - && !compiler_state.has_breaking_schema_change(project_name) + && !compiler_state.has_breaking_schema_change(project_name, project_config) && if let Some(base) = project_config.base { - !compiler_state.has_breaking_schema_change(base) + !compiler_state.has_breaking_schema_change(base, project_config) } else { true }; diff --git a/compiler/crates/relay-compiler/src/compiler_state.rs b/compiler/crates/relay-compiler/src/compiler_state.rs index d2876dccd5eee..2422ac20410c8 100644 --- a/compiler/crates/relay-compiler/src/compiler_state.rs +++ b/compiler/crates/relay-compiler/src/compiler_state.rs @@ -6,7 +6,7 @@ */ use crate::artifact_map::ArtifactMap; -use crate::config::Config; +use crate::config::{Config, ProjectConfig}; use crate::errors::{Error, Result}; use crate::file_source::{ categorize_files, extract_graphql_strings_from_file, read_file_to_string, Clock, File, @@ -341,7 +341,7 @@ impl CompilerState { .any(|sources| !sources.processed.is_empty()) } - fn is_change_safe(&self, sources: &SchemaSources) -> bool { + fn is_change_safe(&self, sources: &SchemaSources, project_config: &ProjectConfig) -> bool { let previous = sources .get_old_sources() .into_iter() @@ -363,7 +363,7 @@ impl CompilerState { ¤t, &Vec::<(&str, SourceLocationKey)>::new(), ) { - Ok(schema) => schema_change.is_safe(&schema), + Ok(schema) => schema_change.is_safe(&schema, project_config.node_interface_id_field), Err(_) => false, } } @@ -381,14 +381,14 @@ impl CompilerState { } /// This method is looking at the pending schema changes to see if they may be breaking (removed types, renamed field, etc) - pub fn has_breaking_schema_change(&self, project_name: StringKey) -> bool { + pub fn has_breaking_schema_change(&self, project_name: StringKey, project_config: &ProjectConfig) -> bool { if let Some(extension) = self.extensions.get(&project_name) { if !extension.pending.is_empty() { return true; } } if let Some(schema) = self.schemas.get(&project_name) { - if !(schema.pending.is_empty() || self.is_change_safe(schema)) { + if !(schema.pending.is_empty() || self.is_change_safe(schema, project_config)) { return true; } } diff --git a/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs b/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs index a4a6c6bbd9d28..3ef18a36bbbc8 100644 --- a/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs +++ b/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs @@ -342,9 +342,9 @@ impl bool { + pub fn is_safe(self: &SchemaChange, schema: &SDLSchema, node_interface_id_field: Option) -> bool { match self { SchemaChange::None => true, SchemaChange::GenericChange => false, @@ -30,7 +30,7 @@ impl SchemaChange { } => { if !interfaces_added.is_empty() || !interfaces_removed.is_empty() - || !is_field_changes_safe(added, removed, changed) + || !is_field_changes_safe(node_interface_id_field, added, removed, changed) { return false; } @@ -41,12 +41,12 @@ impl SchemaChange { removed, .. } => { - if !is_field_changes_safe(added, removed, changed) { + if !is_field_changes_safe(node_interface_id_field, added, removed, changed) { return false; } } DefinitionChange::ObjectAdded(name) => { - if !is_object_add_safe(*name, schema) { + if !is_object_add_safe(*name, schema, node_interface_id_field) { return false; } } @@ -70,7 +70,6 @@ impl SchemaChange { } lazy_static! { - static ref ID_FIELD_KEY: StringKey = "id".intern(); static ref JS_FIELD_KEY: StringKey = "js".intern(); static ref NODE_INTERFACE_KEY: StringKey = "Node".intern(); } @@ -84,13 +83,15 @@ lazy_static! { /// } /// But we have a special case for `Node`. The `id` field is automatically /// added to the selection for all types that implements `Node`. -fn is_object_add_safe(name: StringKey, schema: &SDLSchema) -> bool { +fn is_object_add_safe(name: StringKey, schema: &SDLSchema, node_interface_id_field: Option) -> bool { + let id_name = node_interface_id_field.unwrap_or("id".intern()); + if let Some(schema::Type::Object(id)) = schema.get_type(name) { let object = schema.object(id); if object .fields .iter() - .any(|id| schema.field(*id).name.item == *ID_FIELD_KEY) + .any(|id| schema.field(*id).name.item == id_name) && object .interfaces .iter() @@ -108,10 +109,13 @@ fn is_object_add_safe(name: StringKey, schema: &SDLSchema) -> bool { } fn is_field_changes_safe( + node_interface_id_field: Option, added: &[TypeChange], removed: &[TypeChange], changed: &[ArgumentChange], ) -> bool { + let id_name = node_interface_id_field.unwrap_or("id".intern()); + if !removed.is_empty() { return false; } @@ -121,7 +125,7 @@ fn is_field_changes_safe( // - `js` field added to a type might change 3D code generation if added .iter() - .any(|add| add.name == *ID_FIELD_KEY || add.name == *JS_FIELD_KEY) + .any(|add| add.name == id_name || add.name == *JS_FIELD_KEY) { return false; } From 9539251b85ae09c783f285e24af9470b9a2007e2 Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Fri, 12 Nov 2021 16:29:56 -0800 Subject: [PATCH 4/7] Remove changes to test project --- compiler/test-project/relay.json | 3 +- compiler/test-project/src/App.js | 23 +- compiler/test-project/src/Component.js | 2 +- .../AppFriendsListComponent_user.graphql.js | 182 ------------- .../FriendsListPaginationQuery.graphql.js | 248 ------------------ .../testschema.graphql | 26 +- 6 files changed, 17 insertions(+), 467 deletions(-) delete mode 100644 compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js delete mode 100644 compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js diff --git a/compiler/test-project/relay.json b/compiler/test-project/relay.json index ea0225f2c61a5..de7cee9f83957 100644 --- a/compiler/test-project/relay.json +++ b/compiler/test-project/relay.json @@ -13,8 +13,7 @@ "test": { "customScalarTypes": {}, "enumModuleSuffix": ".test", - "schema": "packages/relay-test-utils-internal/testschema.graphql", - "nodeInterfaceIdField": "_id" + "schema": "packages/relay-test-utils-internal/testschema.graphql" } } } diff --git a/compiler/test-project/src/App.js b/compiler/test-project/src/App.js index 9aa9e657ee656..4da06fbf854d7 100644 --- a/compiler/test-project/src/App.js +++ b/compiler/test-project/src/App.js @@ -8,28 +8,9 @@ */ graphql` - query AppQuery($count: Int, $cursor: ID) { - node(_id: "test") { + query AppQuery { + node(id: "test") { ...Component_node } - me { - ...AppFriendsListComponent_user - } } `; - -graphql` - fragment AppFriendsListComponent_user on User - @refetchable(queryName: "FriendsListPaginationQuery") { - name - friends(first: $count, after: $cursor) - @connection(key: "FriendsList_user_friends") { - edges { - node { - name - } - } - } - } - `, - diff --git a/compiler/test-project/src/Component.js b/compiler/test-project/src/Component.js index 562015f5a8ed6..02adec0ea5d1e 100644 --- a/compiler/test-project/src/Component.js +++ b/compiler/test-project/src/Component.js @@ -9,6 +9,6 @@ graphql` fragment Component_node on Node { - _id + id } `; diff --git a/compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js b/compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js deleted file mode 100644 index a03512ad24888..0000000000000 --- a/compiler/test-project/src/__generated__/AppFriendsListComponent_user.graphql.js +++ /dev/null @@ -1,182 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated SignedSource<<76b058b1f7b0810b5e62f46733815296>> - * @flow - * @lightSyntaxTransform - * @nogrep - */ - -/* eslint-disable */ - -'use strict'; - -/*:: -import type { ReaderFragment } from 'relay-runtime'; -import type { FragmentReference } from "relay-runtime"; -type AppFriendsListComponent_user$ref = any; -type AppFriendsListComponent_user$fragmentType = any; -export type { AppFriendsListComponent_user$ref, AppFriendsListComponent_user$fragmentType }; -export type AppFriendsListComponent_user = {| - +name: ?string, - +friends: ?{| - +edges: ?$ReadOnlyArray, - |}, - +_id: string, - +$refType: AppFriendsListComponent_user$ref, -|}; -export type AppFriendsListComponent_user$data = AppFriendsListComponent_user; -export type AppFriendsListComponent_user$key = { - +$data?: AppFriendsListComponent_user$data, - +$fragmentRefs: AppFriendsListComponent_user$ref, - ... -}; -*/ - -var node/*: ReaderFragment*/ = (function(){ -var v0 = [ - "friends" -], -v1 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}; -return { - "argumentDefinitions": [ - { - "kind": "RootArgument", - "name": "count" - }, - { - "kind": "RootArgument", - "name": "cursor" - } - ], - "kind": "Fragment", - "metadata": { - "connection": [ - { - "count": "count", - "cursor": "cursor", - "direction": "forward", - "path": (v0/*: any*/) - } - ], - "refetch": { - "connection": { - "forward": { - "count": "count", - "cursor": "cursor" - }, - "backward": null, - "path": (v0/*: any*/) - }, - "fragmentPathInResult": [ - "node" - ], - "operation": require('./FriendsListPaginationQuery.graphql'), - "identifierField": "_id" - } - }, - "name": "AppFriendsListComponent_user", - "selections": [ - (v1/*: any*/), - { - "alias": "friends", - "args": null, - "concreteType": "FriendsConnection", - "kind": "LinkedField", - "name": "__FriendsList_user_friends_connection", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "FriendsEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "User", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v1/*: any*/), - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "_id", - "storageKey": null - } - ], - "type": "User", - "abstractKey": null -}; -})(); - -(node/*: any*/).hash = "d818fa52dd21a91c8e1460b88de07bd9"; - -module.exports = node; diff --git a/compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js b/compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js deleted file mode 100644 index 812248b6fd62f..0000000000000 --- a/compiler/test-project/src/__generated__/FriendsListPaginationQuery.graphql.js +++ /dev/null @@ -1,248 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated SignedSource<<1546f284d932f3845de358bcad3f16c3>> - * @flow - * @lightSyntaxTransform - * @nogrep - */ - -/* eslint-disable */ - -'use strict'; - -/*:: -import type { ConcreteRequest } from 'relay-runtime'; -import type { FragmentReference } from "relay-runtime"; -declare export opaque type AppFriendsListComponent_user$ref: FragmentReference; -declare export opaque type AppFriendsListComponent_user$fragmentType: AppFriendsListComponent_user$ref; -export type FriendsListPaginationQueryVariables = {| - count?: ?number, - cursor?: ?string, - _id: string, -|}; -export type FriendsListPaginationQueryResponse = {| - +node: ?{| - +$fragmentRefs: AppFriendsListComponent_user$ref, - |}, -|}; -export type FriendsListPaginationQuery = {| - variables: FriendsListPaginationQueryVariables, - response: FriendsListPaginationQueryResponse, -|}; -*/ - -var node/*: ConcreteRequest*/ = (function(){ -var v0 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "_id" -}, -v1 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "count" -}, -v2 = { - "defaultValue": null, - "kind": "LocalArgument", - "name": "cursor" -}, -v3 = [ - { - "kind": "Variable", - "name": "_id", - "variableName": "_id" - } -], -v4 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "__typename", - "storageKey": null -}, -v5 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "_id", - "storageKey": null -}, -v6 = { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "name", - "storageKey": null -}, -v7 = [ - { - "kind": "Variable", - "name": "after", - "variableName": "cursor" - }, - { - "kind": "Variable", - "name": "first", - "variableName": "count" - } -]; -return { - "fragment": { - "argumentDefinitions": [ - (v0/*: any*/), - (v1/*: any*/), - (v2/*: any*/) - ], - "kind": "Fragment", - "metadata": null, - "name": "FriendsListPaginationQuery", - "selections": [ - { - "alias": null, - "args": (v3/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - { - "args": null, - "kind": "FragmentSpread", - "name": "AppFriendsListComponent_user" - } - ], - "storageKey": null - } - ], - "type": "Query", - "abstractKey": null - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [ - (v1/*: any*/), - (v2/*: any*/), - (v0/*: any*/) - ], - "kind": "Operation", - "name": "FriendsListPaginationQuery", - "selections": [ - { - "alias": null, - "args": (v3/*: any*/), - "concreteType": null, - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v4/*: any*/), - (v5/*: any*/), - { - "kind": "InlineFragment", - "selections": [ - (v6/*: any*/), - { - "alias": null, - "args": (v7/*: any*/), - "concreteType": "FriendsConnection", - "kind": "LinkedField", - "name": "friends", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "FriendsEdge", - "kind": "LinkedField", - "name": "edges", - "plural": true, - "selections": [ - { - "alias": null, - "args": null, - "concreteType": "User", - "kind": "LinkedField", - "name": "node", - "plural": false, - "selections": [ - (v6/*: any*/), - (v5/*: any*/), - (v4/*: any*/) - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "cursor", - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": null, - "concreteType": "PageInfo", - "kind": "LinkedField", - "name": "pageInfo", - "plural": false, - "selections": [ - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "endCursor", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "hasNextPage", - "storageKey": null - } - ], - "storageKey": null - } - ], - "storageKey": null - }, - { - "alias": null, - "args": (v7/*: any*/), - "filters": null, - "handle": "connection", - "key": "FriendsList_user_friends", - "kind": "LinkedHandle", - "name": "friends" - } - ], - "type": "User", - "abstractKey": null - } - ], - "storageKey": null - } - ] - }, - "params": { - "cacheID": "48e7e53c894c3797ec3f3480d209c212", - "id": null, - "metadata": {}, - "name": "FriendsListPaginationQuery", - "operationKind": "query", - "text": "query FriendsListPaginationQuery(\n $count: Int\n $cursor: ID\n $_id: ID!\n) {\n node(_id: $_id) {\n __typename\n ...AppFriendsListComponent_user\n _id\n }\n}\n\nfragment AppFriendsListComponent_user on User {\n name\n friends(first: $count, after: $cursor) {\n edges {\n node {\n name\n _id\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n _id\n}\n" - } -}; -})(); - -(node/*: any*/).hash = "d818fa52dd21a91c8e1460b88de07bd9"; - -module.exports = node; diff --git a/packages/relay-test-utils-internal/testschema.graphql b/packages/relay-test-utils-internal/testschema.graphql index 072743a6f102c..f6af83a1ea71e 100644 --- a/packages/relay-test-utils-internal/testschema.graphql +++ b/packages/relay-test-utils-internal/testschema.graphql @@ -46,7 +46,7 @@ type Query { neverNode: NeverNode named: Named me: User - node(_id: ID): Node + node(id: ID): Node node_id_required(id: ID!): Node nodes(ids: [ID!]): [Node] settings(environment: Environment): Settings @@ -77,7 +77,7 @@ interface AllConcreteTypesImplementNode { } type FakeNode { - _id: ID! + id: ID! } type NonNode { @@ -301,7 +301,7 @@ type Comment implements Node { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -454,7 +454,7 @@ type Feedback implements Node & HasJsField { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -487,7 +487,7 @@ interface FeedUnit { actor: Actor actorCount: Int feedback: Feedback - _id: ID! + id: ID! message: Text tracking: String actor_key: ID! @@ -583,7 +583,7 @@ interface Node { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -621,7 +621,7 @@ interface Actor { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String name: String nameRenderer(supported: [String!]): UserNameRenderer @@ -676,7 +676,7 @@ type Page implements Node & Actor & Entity { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -749,7 +749,7 @@ type NonNodeStory implements FeedUnit @fetchable(field_name: "fetch_id") { actor: Actor actorCount: Int feedback: Feedback - _id: ID! + id: ID! fetch_id: ID! message: Text tracking: String @@ -807,7 +807,7 @@ type PhotoStory implements FeedUnit & Node { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -870,7 +870,7 @@ type Story implements FeedUnit & Node & MaybeNodeInterface { traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! lastName: String likers(first: Int): LikersOfContentConnection likeSentence: Text @@ -1043,7 +1043,7 @@ type User implements Named & Node & Actor & HasJsField & Entity & AllConcreteTyp traits: [PersonalityTraits] ): FriendsConnection hometown: Page - _id: ID! + id: ID! js(module: String!, id: String): JSDependency lastName: String likers(first: Int): LikersOfContentConnection @@ -1220,7 +1220,7 @@ type IDFieldTests { object: IDFieldIsObject } type IDFieldIsIDNonNull { - _id: ID! + id: ID! } type IDFieldIsID { id: ID From 6d2b0d8454754df881c8901a0e7f6dd8c6017a6b Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Wed, 15 Dec 2021 17:37:38 -0500 Subject: [PATCH 5/7] Fix bad rebase --- compiler/crates/relay-transforms/src/apply_transforms.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/crates/relay-transforms/src/apply_transforms.rs b/compiler/crates/relay-transforms/src/apply_transforms.rs index 3619209795799..5f880b514a889 100644 --- a/compiler/crates/relay-transforms/src/apply_transforms.rs +++ b/compiler/crates/relay-transforms/src/apply_transforms.rs @@ -134,7 +134,7 @@ fn apply_common_transforms( connection_interface: &ConnectionInterface, feature_flags: Arc, node_interface_id_field: Option, - base_fragment_names: Arc>, + base_fragment_names: Arc, perf_logger: Arc, ) -> DiagnosticsResult> { let log_event = perf_logger.create_event("apply_common_transforms"); @@ -402,12 +402,8 @@ fn apply_typegen_transforms( project_name: StringKey, program: Arc, feature_flags: Arc, -<<<<<<< HEAD - base_fragment_names: Arc, -======= node_interface_id_field: Option, - base_fragment_names: Arc>, ->>>>>>> d4315a7d83d (Mostly working configurable node interface ID) + base_fragment_names: Arc, perf_logger: Arc, ) -> DiagnosticsResult> { let log_event = perf_logger.create_event("apply_typegen_transforms"); From 323c9998811c2bb08c29ea352d9e5f4589a66579 Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Wed, 15 Dec 2021 17:52:48 -0500 Subject: [PATCH 6/7] Migrate to using FeatureFlags for configuration --- compiler/crates/common/src/feature_flags.rs | 4 ++++ .../relay-compiler/src/build_project/mod.rs | 1 - .../relay-compiler/src/compiler_state.rs | 2 +- compiler/crates/relay-compiler/src/config.rs | 11 ----------- .../crates/relay-lsp/src/graphql_tools/mod.rs | 1 - .../relay-transforms/src/apply_transforms.rs | 19 +++++++------------ .../relay-transforms/src/generate_id_field.rs | 2 +- .../fetchable_query_generator.rs | 2 +- .../node_query_generator.rs | 4 ++-- compiler/crates/schema-diff/src/check.rs | 4 ++-- 10 files changed, 18 insertions(+), 32 deletions(-) diff --git a/compiler/crates/common/src/feature_flags.rs b/compiler/crates/common/src/feature_flags.rs index c818ee3addd5c..47cbb2944aeba 100644 --- a/compiler/crates/common/src/feature_flags.rs +++ b/compiler/crates/common/src/feature_flags.rs @@ -49,6 +49,10 @@ pub struct FeatureFlags { #[serde(default)] pub enable_provided_variables: FeatureFlag, + + /// The name of the `id` field that exists on the `Node` interface. + #[serde(default)] + pub node_interface_id_field: Option, } #[derive(Debug, Deserialize, Clone, Serialize)] diff --git a/compiler/crates/relay-compiler/src/build_project/mod.rs b/compiler/crates/relay-compiler/src/build_project/mod.rs index 182c3af02ad5a..e0a3e7278405b 100644 --- a/compiler/crates/relay-compiler/src/build_project/mod.rs +++ b/compiler/crates/relay-compiler/src/build_project/mod.rs @@ -134,7 +134,6 @@ pub fn transform_program( base_fragment_names, &config.connection_interface, Arc::clone(&project_config.feature_flags), - project_config.node_interface_id_field, &project_config.test_path_regex, perf_logger, Some(print_stats), diff --git a/compiler/crates/relay-compiler/src/compiler_state.rs b/compiler/crates/relay-compiler/src/compiler_state.rs index 2422ac20410c8..b5f4904ea9c21 100644 --- a/compiler/crates/relay-compiler/src/compiler_state.rs +++ b/compiler/crates/relay-compiler/src/compiler_state.rs @@ -363,7 +363,7 @@ impl CompilerState { ¤t, &Vec::<(&str, SourceLocationKey)>::new(), ) { - Ok(schema) => schema_change.is_safe(&schema, project_config.node_interface_id_field), + Ok(schema) => schema_change.is_safe(&schema, project_config.feature_flags.node_interface_id_field), Err(_) => false, } } diff --git a/compiler/crates/relay-compiler/src/config.rs b/compiler/crates/relay-compiler/src/config.rs index d6703093998c0..f2231bc97099e 100644 --- a/compiler/crates/relay-compiler/src/config.rs +++ b/compiler/crates/relay-compiler/src/config.rs @@ -273,7 +273,6 @@ impl Config { skip_types_for_artifact: None, rollout: config_file_project.rollout, js_module_format: config_file_project.js_module_format, - node_interface_id_field: config_file_project.node_interface_id_field, }; Ok((project_name, project_config)) }) @@ -518,7 +517,6 @@ pub struct ProjectConfig { pub skip_types_for_artifact: Option bool) + Send + Sync>>, pub rollout: Rollout, pub js_module_format: JsModuleFormat, - pub node_interface_id_field: Option, } impl Debug for ProjectConfig { @@ -543,7 +541,6 @@ impl Debug for ProjectConfig { skip_types_for_artifact, rollout, js_module_format, - node_interface_id_field, } = self; f.debug_struct("ProjectConfig") .field("name", name) @@ -579,7 +576,6 @@ impl Debug for ProjectConfig { ) .field("rollout", rollout) .field("js_module_format", js_module_format) - .field("node_interface_id_field", node_interface_id_field) .finish() } } @@ -683,9 +679,6 @@ pub struct SingleProjectConfigFile { /// It contains URL and addition parameters that will be included /// with the request (think API_KEY, APP_ID, etc...) pub persist_config: Option, - - /// The name of the `id` field that exists on the `Node` interface. - pub node_interface_id_field: Option, } impl Default for SingleProjectConfigFile { @@ -701,7 +694,6 @@ impl Default for SingleProjectConfigFile { custom_scalars: Default::default(), eager_es_modules: false, persist_config: None, - node_interface_id_field: None, } } } @@ -910,9 +902,6 @@ struct ConfigFileProject { #[serde(default)] js_module_format: JsModuleFormat, - - #[serde(default)] - pub node_interface_id_field: Option, } #[derive(Debug, Serialize, Deserialize)] diff --git a/compiler/crates/relay-lsp/src/graphql_tools/mod.rs b/compiler/crates/relay-lsp/src/graphql_tools/mod.rs index b37ac564565ba..3a586a31c83ed 100644 --- a/compiler/crates/relay-lsp/src/graphql_tools/mod.rs +++ b/compiler/crates/relay-lsp/src/graphql_tools/mod.rs @@ -134,7 +134,6 @@ fn transform_program( Default::default(), &config.connection_interface, Arc::clone(&project_config.feature_flags), - project_config.node_interface_id_field, &None, perf_logger, None, diff --git a/compiler/crates/relay-transforms/src/apply_transforms.rs b/compiler/crates/relay-transforms/src/apply_transforms.rs index 5f880b514a889..8ec8783ce9eb4 100644 --- a/compiler/crates/relay-transforms/src/apply_transforms.rs +++ b/compiler/crates/relay-transforms/src/apply_transforms.rs @@ -29,7 +29,6 @@ pub fn apply_transforms( base_fragment_names: Arc, connection_interface: &ConnectionInterface, feature_flags: Arc, - node_interface_id_field: Option, test_path_regex: &Option, perf_logger: Arc, print_stats: Option ()>, @@ -56,7 +55,6 @@ where Arc::clone(&program), connection_interface, Arc::clone(&feature_flags), - node_interface_id_field, Arc::clone(&base_fragment_names), Arc::clone(&perf_logger), )?; @@ -66,7 +64,7 @@ where let operation_program = apply_operation_transforms( project_name, Arc::clone(&common_program), - node_interface_id_field, + Arc::clone(&feature_flags), connection_interface, Arc::clone(&base_fragment_names), Arc::clone(&perf_logger), @@ -111,7 +109,6 @@ where project_name, Arc::clone(&program), Arc::clone(&feature_flags), - node_interface_id_field, Arc::clone(&base_fragment_names), Arc::clone(&perf_logger), ) @@ -133,7 +130,6 @@ fn apply_common_transforms( program: Arc, connection_interface: &ConnectionInterface, feature_flags: Arc, - node_interface_id_field: Option, base_fragment_names: Arc, perf_logger: Arc, ) -> DiagnosticsResult> { @@ -153,10 +149,10 @@ fn apply_common_transforms( transform_subscriptions(&program) })?; program = log_event.time("transform_refetchable_fragment", || { - transform_refetchable_fragment(&program, node_interface_id_field, &base_fragment_names, false) + transform_refetchable_fragment(&program, feature_flags.node_interface_id_field, &base_fragment_names, false) })?; - program = log_event.time("client_edges", || client_edges(&program, node_interface_id_field))?; + program = log_event.time("client_edges", || client_edges(&program, feature_flags.node_interface_id_field))?; program = log_event.time("relay_resolvers", || { relay_resolvers(&program, feature_flags.enable_relay_resolver_transform) })?; @@ -229,7 +225,7 @@ fn apply_reader_transforms( fn apply_operation_transforms( project_name: StringKey, program: Arc, - node_interface_id_field: Option, + feature_flags: Arc, connection_interface: &ConnectionInterface, base_fragment_names: Arc, perf_logger: Arc, @@ -244,7 +240,7 @@ fn apply_operation_transforms( program = log_event.time("split_module_import", || { split_module_import(&program, &base_fragment_names) }); - program = log_event.time("generate_id_field", || generate_id_field(&program, node_interface_id_field)); + program = log_event.time("generate_id_field", || generate_id_field(&program, feature_flags.node_interface_id_field)); program = log_event.time("declarative_connection", || { transform_declarative_connection(&program, connection_interface) })?; @@ -402,7 +398,6 @@ fn apply_typegen_transforms( project_name: StringKey, program: Arc, feature_flags: Arc, - node_interface_id_field: Option, base_fragment_names: Arc, perf_logger: Arc, ) -> DiagnosticsResult> { @@ -417,7 +412,7 @@ fn apply_typegen_transforms( transform_subscriptions(&program) })?; program = log_event.time("required_directive", || required_directive(&program))?; - program = log_event.time("client_edges", || client_edges(&program, node_interface_id_field))?; + program = log_event.time("client_edges", || client_edges(&program, feature_flags.node_interface_id_field))?; program = log_event.time( "transform_assignable_fragment_spreads_in_regular_queries", || transform_assignable_fragment_spreads_in_regular_queries(&program), @@ -430,7 +425,7 @@ fn apply_typegen_transforms( })?; log_event.time("flatten", || flatten(&mut program, false, false))?; program = log_event.time("transform_refetchable_fragment", || { - transform_refetchable_fragment(&program, node_interface_id_field, &base_fragment_names, true) + transform_refetchable_fragment(&program, feature_flags.node_interface_id_field, &base_fragment_names, true) })?; program = log_event.time("remove_base_fragments", || { remove_base_fragments(&program, base_fragment_names) diff --git a/compiler/crates/relay-transforms/src/generate_id_field.rs b/compiler/crates/relay-transforms/src/generate_id_field.rs index 187d2dec1ca52..bc55768eac131 100644 --- a/compiler/crates/relay-transforms/src/generate_id_field.rs +++ b/compiler/crates/relay-transforms/src/generate_id_field.rs @@ -114,7 +114,7 @@ impl<'s> Transformer for GenerateIDFieldTransform<'s> { impl<'s> GenerateIDFieldTransform<'s> { fn new(program: &'s Program, node_interface_id_field: Option) -> Self { - let id_name = node_interface_id_field.unwrap_or("id".intern()); + let id_name = node_interface_id_field.unwrap_or_else(|| "id".intern()); let schema = &program.schema; let node_interface = match schema.get_type("Node".intern()) { diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs index 6d1e4543eb919..7037b6c170516 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/fetchable_query_generator.rs @@ -27,7 +27,7 @@ fn build_refetch_operation( query_name: StringKey, variables_map: &VariableMap, ) -> DiagnosticsResult> { - let id_name = node_interface_id_field.unwrap_or("id".intern()); + let id_name = node_interface_id_field.unwrap_or_else(|| "id".intern()); if let Some(identifier_field_name) = get_fetchable_field_name(fragment, schema)? { let identifier_field_id = get_identifier_field_id(fragment, schema, identifier_field_name)?; diff --git a/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs b/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs index c38e702340ef3..4a76c508fbffa 100644 --- a/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs +++ b/compiler/crates/relay-transforms/src/refetchable_fragment/node_query_generator.rs @@ -27,7 +27,7 @@ fn build_refetch_operation( query_name: StringKey, variables_map: &VariableMap, ) -> DiagnosticsResult> { - let id_name = node_interface_id_field.unwrap_or("id".intern()); + let id_name = node_interface_id_field.unwrap_or_else(|| "id".intern()); let node_interface_id = schema.get_type(CONSTANTS.node_type_name).and_then(|type_| { if let Type::Interface(id) = type_ { @@ -185,7 +185,7 @@ fn enforce_selections_with_id_field( id_field_id: FieldID, node_interface_id: Option, ) -> Vec { - let id_name = node_interface_id_field.unwrap_or("id".intern()); + let id_name = node_interface_id_field.unwrap_or_else(|| "id".intern()); let mut next_selections = fragment.selections.clone(); let has_id_field = next_selections.iter().any(|sel| { if let Selection::ScalarField(field) = sel { diff --git a/compiler/crates/schema-diff/src/check.rs b/compiler/crates/schema-diff/src/check.rs index fd622da07a58d..5ea92129c658a 100644 --- a/compiler/crates/schema-diff/src/check.rs +++ b/compiler/crates/schema-diff/src/check.rs @@ -84,7 +84,7 @@ lazy_static! { /// But we have a special case for `Node`. The `id` field is automatically /// added to the selection for all types that implements `Node`. fn is_object_add_safe(name: StringKey, schema: &SDLSchema, node_interface_id_field: Option) -> bool { - let id_name = node_interface_id_field.unwrap_or("id".intern()); + let id_name = node_interface_id_field.unwrap_or_else(|| "id".intern()); if let Some(schema::Type::Object(id)) = schema.get_type(name) { let object = schema.object(id); @@ -114,7 +114,7 @@ fn is_field_changes_safe( removed: &[TypeChange], changed: &[ArgumentChange], ) -> bool { - let id_name = node_interface_id_field.unwrap_or("id".intern()); + let id_name = node_interface_id_field.unwrap_or_else(|| "id".intern()); if !removed.is_empty() { return false; From ae8a1bcd13e22556d842ffd410990cbdbc03b775 Mon Sep 17 00:00:00 2001 From: Jordan Gensler Date: Wed, 15 Dec 2021 18:36:00 -0500 Subject: [PATCH 7/7] Fix tests --- .../crates/relay-compiler/tests/compile_relay_artifacts/mod.rs | 2 +- compiler/crates/relay-transforms/tests/generate_id_field/mod.rs | 2 +- .../crates/relay-transforms/tests/refetchable_fragment/mod.rs | 2 +- compiler/crates/relay-typegen/tests/generate_flow/mod.rs | 1 - compiler/crates/relay-typegen/tests/generate_typescript/mod.rs | 1 - compiler/crates/schema-diff/tests/diff_schema_tests.rs | 2 +- 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs index fd920d7be718d..b1a4b5f689b3e 100644 --- a/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs +++ b/compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs @@ -81,6 +81,7 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { text_artifacts: FeatureFlag::Disabled, enable_client_edges: FeatureFlag::Enabled, enable_provided_variables: FeatureFlag::Enabled, + node_interface_id_field: None, }; // TODO pass base fragment names @@ -90,7 +91,6 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { Default::default(), &connection_interface, Arc::new(feature_flags), - None, &None, Arc::new(ConsoleLogger), None, diff --git a/compiler/crates/relay-transforms/tests/generate_id_field/mod.rs b/compiler/crates/relay-transforms/tests/generate_id_field/mod.rs index a0e65aae6d05c..1ec7b34b86992 100644 --- a/compiler/crates/relay-transforms/tests/generate_id_field/mod.rs +++ b/compiler/crates/relay-transforms/tests/generate_id_field/mod.rs @@ -10,5 +10,5 @@ use graphql_test_helpers::apply_transform_for_test; use relay_transforms::generate_id_field; pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { - apply_transform_for_test(fixture, |program| Ok(generate_id_field(program))) + apply_transform_for_test(fixture, |program| Ok(generate_id_field(program, None))) } diff --git a/compiler/crates/relay-transforms/tests/refetchable_fragment/mod.rs b/compiler/crates/relay-transforms/tests/refetchable_fragment/mod.rs index 69880ffc744d8..d9bd2cc217f5d 100644 --- a/compiler/crates/relay-transforms/tests/refetchable_fragment/mod.rs +++ b/compiler/crates/relay-transforms/tests/refetchable_fragment/mod.rs @@ -16,6 +16,6 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { apply_transform_for_test(fixture, |program| { let program = transform_connections(program, &ConnectionInterface::default()); let base_fragments = Default::default(); - transform_refetchable_fragment(&program, &base_fragments, false) + transform_refetchable_fragment(&program, None, &base_fragments, false) }) } diff --git a/compiler/crates/relay-typegen/tests/generate_flow/mod.rs b/compiler/crates/relay-typegen/tests/generate_flow/mod.rs index 393053b758417..f5339b608ea0d 100644 --- a/compiler/crates/relay-typegen/tests/generate_flow/mod.rs +++ b/compiler/crates/relay-typegen/tests/generate_flow/mod.rs @@ -54,7 +54,6 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { Default::default(), &ConnectionInterface::default(), Arc::new(feature_flags), - None, &None, Arc::new(ConsoleLogger), None, diff --git a/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs b/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs index 37b725c01a04c..50373dac7fa97 100644 --- a/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs +++ b/compiler/crates/relay-typegen/tests/generate_typescript/mod.rs @@ -42,7 +42,6 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result { Default::default(), &ConnectionInterface::default(), Arc::new(FeatureFlags::default()), - None, &None, Arc::new(ConsoleLogger), None, diff --git a/compiler/crates/schema-diff/tests/diff_schema_tests.rs b/compiler/crates/schema-diff/tests/diff_schema_tests.rs index 55022f96e394a..6596c4a72a19a 100644 --- a/compiler/crates/schema-diff/tests/diff_schema_tests.rs +++ b/compiler/crates/schema-diff/tests/diff_schema_tests.rs @@ -20,7 +20,7 @@ fn diff(current: &str, previous: &str) -> SchemaChange { fn is_safe(current: &str, previous: &str) -> bool { let schema = build_schema(current).unwrap(); let change = detect_changes(&[current], &[previous]); - change.is_safe(&schema) + change.is_safe(&schema, None) } #[test]