From d036d496eb4f3c5ed96f98572d2a2a0ae120facd Mon Sep 17 00:00:00 2001 From: Evan Yeung Date: Tue, 22 Oct 2024 13:07:34 -0700 Subject: [PATCH] Update normalization artifacts for exec time resolver strong ids Summary: This diff updates artifact generation for exec time resolvers to include the resolver module in the normalization AST. It's fairly similar to how the reader AST is built but we need far less information at normalization time. This is the most basic version of the artifact and we may need to add additional fields as the feature continues to be built. Reviewed By: captbaritone Differential Revision: D64635272 fbshipit-source-id: 3627fbb51570e4559bf98a0334b136d11d0f0de1 --- .../crates/relay-codegen/src/build_ast.rs | 101 ++++++++++++++++-- .../relay-codegen/tests/client_edges.rs | 18 ++-- .../client-edge-backed-by-resolver.expected | 4 +- .../client-edge-exec-time-resolver.expected | 86 +++++++++++++++ .../client-edge-exec-time-resolver.graphql | 25 +++++ .../relay-codegen/tests/client_edges_test.rs | 9 +- ..._interface_of_all_live_model_type.expected | 84 ++++++++++----- ...rns_interface_of_all_live_model_type.input | 1 - ...nterface_of_all_strong_model_type.expected | 84 ++++++++++----- ...s_interface_of_all_strong_model_type.input | 1 - ...l_strong_model_type_including_cse.expected | 82 +++++++++----- ..._all_strong_model_type_including_cse.input | 1 - ...ve_and_non_live_strong_model_type.expected | 84 ++++++++++----- ..._live_and_non_live_strong_model_type.input | 1 - ..._returns_union_of_strong_resolver.expected | 67 ++++++++---- ...ver_returns_union_of_strong_resolver.input | 1 - .../relay-runtime/util/NormalizationNode.js | 7 ++ 17 files changed, 513 insertions(+), 143 deletions(-) create mode 100644 compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.expected create mode 100644 compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.graphql diff --git a/compiler/crates/relay-codegen/src/build_ast.rs b/compiler/crates/relay-codegen/src/build_ast.rs index fc15095b32fa4..ebf59befc5a01 100644 --- a/compiler/crates/relay-codegen/src/build_ast.rs +++ b/compiler/crates/relay-codegen/src/build_ast.rs @@ -1343,17 +1343,51 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> { let type_name = model_resolver.type_name.item.0; ObjectEntry { key: type_name, - value: self.build_client_edge_model_resolver( - model_resolver.type_name, - model_resolver.is_live, - relay_resolver_metadata, - ), + value: match self.variant { + CodegenVariant::Reader => self.build_reader_client_edge_model_resolver( + model_resolver.type_name, + model_resolver.is_live, + relay_resolver_metadata, + ), + CodegenVariant::Normalization => self + .build_normalization_client_edge_model_resolver( + model_resolver.type_name, + relay_resolver_metadata, + ), + }, } }) .collect() } - fn build_client_edge_model_resolver( + fn build_normalization_client_edge_model_resolver( + &mut self, + type_name: WithLocation, + relay_resolver_metadata: &RelayResolverMetadata, + ) -> Primitive { + let import_path = self.project_config.js_module_import_identifier( + &self + .project_config + .artifact_path_for_definition(self.definition_source_location), + &PathBuf::from(type_name.location.source_location().path()), + ); + let variable_name = relay_resolver_metadata.generate_local_resolver_name(self.schema); + let resolver_module = JSModuleDependency { + path: import_path, + import_name: ModuleImportName::Named { + name: type_name.item.0, + import_as: Some(variable_name), + }, + }; + + let object_props = object! { + resolver_module: Primitive::JSModuleDependency(resolver_module), + }; + + Primitive::Key(self.object(object_props)) + } + + fn build_reader_client_edge_model_resolver( &mut self, type_name: WithLocation, is_live: bool, @@ -1705,12 +1739,57 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> { } let backing_field = backing_field_primitives.into_iter().next().unwrap(); + let client_edge_model_resolvers = match &client_edge_metadata.metadata_directive { + ClientEdgeMetadataDirective::ClientObject { + model_resolvers, .. + } => { + let field_directives = match &client_edge_metadata.backing_field { + Selection::ScalarField(field) => Some(&field.directives), + // Although the reader checks for FragmentSpreads on the backing field, the normalization + // transforms inline the fragment spread so we match an InlineFragment here + Selection::InlineFragment(inline_frag) => Some(&inline_frag.directives), + _ => panic!( + "Expected Client Edge backing field to be a Relay Resolver. {:?}", + client_edge_metadata.backing_field + ), + }; + field_directives.and_then(|field_directives| { + let resolver_metadata = RelayResolverMetadata::find(field_directives).unwrap(); + let is_weak_resolver = matches!( + resolver_metadata.output_type_info, + ResolverOutputTypeInfo::Composite(_) + ); + let model_resolver_primitives = if !is_weak_resolver { + self.build_client_edge_model_resolvers(model_resolvers, resolver_metadata) + } else { + vec![] + }; + if model_resolver_primitives.is_empty() { + None + } else { + Some(Primitive::Key(self.object(model_resolver_primitives))) + } + }) + } + ClientEdgeMetadataDirective::ServerObject { .. } => None, + }; + let selections_item = self.build_linked_field(context, client_edge_metadata.linked_field); - Primitive::Key(self.object(object! { - kind: Primitive::String(CODEGEN_CONSTANTS.client_edge_to_client_object), - client_edge_backing_field_key: backing_field, - client_edge_selections_key: selections_item, - })) + + let obj = match client_edge_model_resolvers { + Some(model_resolvers) => object! { + kind: Primitive::String(CODEGEN_CONSTANTS.client_edge_to_client_object), + client_edge_model_resolvers: model_resolvers, + client_edge_backing_field_key: backing_field, + client_edge_selections_key: selections_item, + }, + None => object! { + kind: Primitive::String(CODEGEN_CONSTANTS.client_edge_to_client_object), + client_edge_backing_field_key: backing_field, + client_edge_selections_key: selections_item, + }, + }; + Primitive::Key(self.object(obj)) } fn build_normalization_client_edge( diff --git a/compiler/crates/relay-codegen/tests/client_edges.rs b/compiler/crates/relay-codegen/tests/client_edges.rs index a2265dc53922b..db162bd034f03 100644 --- a/compiler/crates/relay-codegen/tests/client_edges.rs +++ b/compiler/crates/relay-codegen/tests/client_edges.rs @@ -22,7 +22,6 @@ use relay_config::ProjectName; use relay_test_schema::get_test_schema_with_extensions; use relay_transforms::client_edges; use relay_transforms::relay_resolvers; -use relay_transforms::sort_selections; pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result { let parts: Vec<_> = fixture.content.split("%extensions%").collect(); @@ -41,17 +40,16 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result }; let feature_flags = Arc::new(FeatureFlags { relay_resolver_enable_interface_output_type, + enable_exec_time_resolvers_directive: true, ..Default::default() }); let project_config: ProjectConfig = ProjectConfig { feature_flags, ..Default::default() }; - let next_program = sort_selections( - &client_edges(&program, &project_config, &Default::default()) - .and_then(|program| relay_resolvers(ProjectName::default(), &program)) - .unwrap(), - ); + let next_program = &client_edges(&program, &project_config, &Default::default()) + .and_then(|program| relay_resolvers(ProjectName::default(), &program)) + .unwrap(); let mut result = next_program .fragments() .map(|def| { @@ -61,6 +59,10 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result def, &ProjectConfig { js_module_format: JsModuleFormat::Haste, + feature_flags: Arc::new(FeatureFlags { + enable_exec_time_resolvers_directive: true, + ..Default::default() + }), ..Default::default() }, &mut import_statements, @@ -74,6 +76,10 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result def, &ProjectConfig { js_module_format: JsModuleFormat::Haste, + feature_flags: Arc::new(FeatureFlags { + enable_exec_time_resolvers_directive: true, + ..Default::default() + }), ..Default::default() }, &mut import_statements, diff --git a/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-backed-by-resolver.expected b/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-backed-by-resolver.expected index 8343ea2b9104c..33ec043b650f4 100644 --- a/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-backed-by-resolver.expected +++ b/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-backed-by-resolver.expected @@ -139,14 +139,14 @@ extend type User { "alias": null, "args": null, "kind": "ScalarField", - "name": "id", + "name": "name", "storageKey": null }, { "alias": null, "args": null, "kind": "ScalarField", - "name": "name", + "name": "id", "storageKey": null } ], diff --git a/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.expected b/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.expected new file mode 100644 index 0000000000000..545905d984432 --- /dev/null +++ b/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.expected @@ -0,0 +1,86 @@ +==================================== INPUT ==================================== +query Foo @exec_time_resolvers { + me { + pet { + name + } + } +} + +# %extensions% + +directive @exec_time_resolvers on QUERY + +type Cat @__RelayResolverModel { + name: String + @relay_resolver(import_name: "name", import_path: "CatNameResolver") + __relay_model_instance: RelayResolverValue! + @relay_resolver(import_name: "Cat") + @unselectable( + reason: "This field is intended only for Relay's internal use" + ) +} + +extend type User { + pet: Cat @relay_resolver(import_name: "Pet", import_path: "PetResolver") +} +==================================== OUTPUT =================================== +{ + "argumentDefinitions": [], + "kind": "Operation", + "name": "Foo", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "User", + "kind": "LinkedField", + "name": "me", + "plural": false, + "selections": [ + { + "kind": "ClientEdgeToClientObject", + "modelResolvers": { + "Cat": { + "resolverModule": require('').Cat + } + }, + "backingField": { + "name": "pet", + "args": null, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false, + "resolverInfo": { + "resolverFunction": require('PetResolver').Pet, + "rootFragment": null + } + }, + "linkedField": { + "alias": null, + "args": null, + "concreteType": "Cat", + "kind": "LinkedField", + "name": "pet", + "plural": false, + "selections": [ + { + "name": "name", + "args": null, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false, + "resolverInfo": { + "resolverFunction": require('CatNameResolver').name, + "rootFragment": null + } + } + ], + "storageKey": null + } + } + ], + "storageKey": null + } + ] +} diff --git a/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.graphql b/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.graphql new file mode 100644 index 0000000000000..56ffec403eda9 --- /dev/null +++ b/compiler/crates/relay-codegen/tests/client_edges/fixtures/client-edge-exec-time-resolver.graphql @@ -0,0 +1,25 @@ +query Foo @exec_time_resolvers { + me { + pet { + name + } + } +} + +# %extensions% + +directive @exec_time_resolvers on QUERY + +type Cat @__RelayResolverModel { + name: String + @relay_resolver(import_name: "name", import_path: "CatNameResolver") + __relay_model_instance: RelayResolverValue! + @relay_resolver(import_name: "Cat") + @unselectable( + reason: "This field is intended only for Relay's internal use" + ) +} + +extend type User { + pet: Cat @relay_resolver(import_name: "Pet", import_path: "PetResolver") +} diff --git a/compiler/crates/relay-codegen/tests/client_edges_test.rs b/compiler/crates/relay-codegen/tests/client_edges_test.rs index ff863e9645370..fc30bb91c7be5 100644 --- a/compiler/crates/relay-codegen/tests/client_edges_test.rs +++ b/compiler/crates/relay-codegen/tests/client_edges_test.rs @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<47f77ebc1507bbe5e60146b25f042c50>> + * @generated SignedSource<<5873fe295d3d76246e0125a0b8a37f15>> */ mod client_edges; @@ -19,6 +19,13 @@ async fn client_edge_backed_by_resolver() { test_fixture(transform_fixture, file!(), "client-edge-backed-by-resolver.graphql", "client_edges/fixtures/client-edge-backed-by-resolver.expected", input, expected).await; } +#[tokio::test] +async fn client_edge_exec_time_resolver() { + let input = include_str!("client_edges/fixtures/client-edge-exec-time-resolver.graphql"); + let expected = include_str!("client_edges/fixtures/client-edge-exec-time-resolver.expected"); + test_fixture(transform_fixture, file!(), "client-edge-exec-time-resolver.graphql", "client_edges/fixtures/client-edge-exec-time-resolver.expected", input, expected).await; +} + #[tokio::test] async fn client_edge_to_client_object() { let input = include_str!("client_edges/fixtures/client-edge-to-client-object.graphql"); diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.expected index 5c80d3ea1ec4e..28bfd4f81360d 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.expected @@ -40,7 +40,6 @@ graphql`query QueryComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } @@ -176,7 +175,7 @@ module.exports = ((node/*: any*/)/*: Fragment< //- __generated__/QueryComponentQuery.graphql.js /** - * SignedSource<<750533be4ec90cc3f3f7cccb2bf849f4>> + * SignedSource<> * @flow * @lightSyntaxTransform * @nogrep @@ -208,7 +207,18 @@ export type QueryComponentQuery = {| |}; */ -var node/*: ClientRequest*/ = { +var node/*: ClientRequest*/ = (function(){ +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v1 = [ + (v0/*: any*/) +]; +return { "fragment": { "argumentDefinitions": [], "kind": "Fragment", @@ -324,13 +334,10 @@ var node/*: ClientRequest*/ = { "backingField": { "name": "person", "args": null, + "fragment": null, "kind": "RelayResolver", "storageKey": null, - "isOutputType": false, - "resolverInfo": { - "resolverFunction": require('QueryResolvers').person, - "rootFragment": null - } + "isOutputType": false }, "linkedField": { "alias": null, @@ -353,13 +360,29 @@ var node/*: ClientRequest*/ = { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "Admin", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "Admin", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('AdminTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "Admin", @@ -371,25 +394,35 @@ var node/*: ClientRequest*/ = { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "User", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "User", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('UserTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "User", "abstractKey": null }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } + (v0/*: any*/) ], "storageKey": null } @@ -405,6 +438,7 @@ var node/*: ClientRequest*/ = { "text": null } }; +})(); (node/*: any*/).hash = "cc7b67152b1dce33f04a61bea084084f"; diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.input index 2982227f3181e..743c8447422f9 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.input +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_live_model_type.input @@ -39,7 +39,6 @@ graphql`query QueryComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.expected index 97fa6dbdec540..f6758dae84bdb 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.expected @@ -38,7 +38,6 @@ graphql`query PersonComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } @@ -174,7 +173,7 @@ module.exports = ((node/*: any*/)/*: Fragment< //- __generated__/PersonComponentQuery.graphql.js /** - * SignedSource<> + * SignedSource<> * @flow * @lightSyntaxTransform * @nogrep @@ -206,7 +205,18 @@ export type PersonComponentQuery = {| |}; */ -var node/*: ClientRequest*/ = { +var node/*: ClientRequest*/ = (function(){ +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v1 = [ + (v0/*: any*/) +]; +return { "fragment": { "argumentDefinitions": [], "kind": "Fragment", @@ -322,13 +332,10 @@ var node/*: ClientRequest*/ = { "backingField": { "name": "person", "args": null, + "fragment": null, "kind": "RelayResolver", "storageKey": null, - "isOutputType": false, - "resolverInfo": { - "resolverFunction": require('QueryResolvers').person, - "rootFragment": null - } + "isOutputType": false }, "linkedField": { "alias": null, @@ -351,13 +358,29 @@ var node/*: ClientRequest*/ = { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "Admin", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "Admin", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('AdminTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "Admin", @@ -369,25 +392,35 @@ var node/*: ClientRequest*/ = { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "User", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "User", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('UserTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "User", "abstractKey": null }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } + (v0/*: any*/) ], "storageKey": null } @@ -403,6 +436,7 @@ var node/*: ClientRequest*/ = { "text": null } }; +})(); (node/*: any*/).hash = "6f362dca4e4d03f5759795a4ce89dee2"; diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.input index 879bb679dab5b..f4c7aadf897f3 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.input +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type.input @@ -37,7 +37,6 @@ graphql`query PersonComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.expected index 009ac5ef58d07..5de176d4401a0 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.expected @@ -38,7 +38,6 @@ graphql`query PersonComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } @@ -179,7 +178,7 @@ module.exports = ((node/*: any*/)/*: Fragment< //- __generated__/PersonComponentQuery.graphql.js /** - * SignedSource<> + * SignedSource<<3a0314e8be13b513500cffb4650eab31>> * @flow * @lightSyntaxTransform * @nogrep @@ -225,7 +224,17 @@ var v0 = { ], "type": "Visitor", "abstractKey": null -}; +}, +v1 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v2 = [ + (v1/*: any*/) +]; return { "fragment": { "argumentDefinitions": [], @@ -343,13 +352,10 @@ return { "backingField": { "name": "person", "args": null, + "fragment": null, "kind": "RelayResolver", "storageKey": null, - "isOutputType": false, - "resolverInfo": { - "resolverFunction": require('QueryResolvers').person, - "rootFragment": null - } + "isOutputType": false }, "linkedField": { "alias": null, @@ -373,13 +379,29 @@ return { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v2/*: any*/), + "type": "Admin", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "Admin", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('AdminTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "Admin", @@ -391,25 +413,35 @@ return { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v2/*: any*/), + "type": "User", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "User", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('UserTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "User", "abstractKey": null }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } + (v1/*: any*/) ], "storageKey": null } diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.input index facf3f75bc911..b92c6d99153b5 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.input +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_all_strong_model_type_including_cse.input @@ -37,7 +37,6 @@ graphql`query PersonComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.expected index dbbf3fecaeb29..077c8b5868038 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.expected @@ -39,7 +39,6 @@ graphql`query QueryComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } @@ -175,7 +174,7 @@ module.exports = ((node/*: any*/)/*: Fragment< //- __generated__/QueryComponentQuery.graphql.js /** - * SignedSource<> + * SignedSource<<13ee77f43acb40f084c4d45dd85f37d8>> * @flow * @lightSyntaxTransform * @nogrep @@ -207,7 +206,18 @@ export type QueryComponentQuery = {| |}; */ -var node/*: ClientRequest*/ = { +var node/*: ClientRequest*/ = (function(){ +var v0 = { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null +}, +v1 = [ + (v0/*: any*/) +]; +return { "fragment": { "argumentDefinitions": [], "kind": "Fragment", @@ -323,13 +333,10 @@ var node/*: ClientRequest*/ = { "backingField": { "name": "person", "args": null, + "fragment": null, "kind": "RelayResolver", "storageKey": null, - "isOutputType": false, - "resolverInfo": { - "resolverFunction": require('QueryResolvers').person, - "rootFragment": null - } + "isOutputType": false }, "linkedField": { "alias": null, @@ -352,13 +359,29 @@ var node/*: ClientRequest*/ = { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "Admin", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "Admin", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('AdminTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "Admin", @@ -370,25 +393,35 @@ var node/*: ClientRequest*/ = { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "User", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "User", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('UserTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true } ], "type": "User", "abstractKey": null }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "id", - "storageKey": null - } + (v0/*: any*/) ], "storageKey": null } @@ -404,6 +437,7 @@ var node/*: ClientRequest*/ = { "text": null } }; +})(); (node/*: any*/).hash = "cc7b67152b1dce33f04a61bea084084f"; diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.input index dbe605a4e6773..35d5ba27eb175 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.input +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_interface_of_live_and_non_live_strong_model_type.input @@ -38,7 +38,6 @@ graphql`query QueryComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.expected index f74ba5a06836e..5257d7382bf8c 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.expected +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.expected @@ -43,7 +43,6 @@ graphql`query PersonComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } @@ -177,7 +176,7 @@ module.exports = ((node/*: any*/)/*: Fragment< //- __generated__/PersonComponentQuery.graphql.js /** - * SignedSource<> + * SignedSource<> * @flow * @lightSyntaxTransform * @nogrep @@ -230,7 +229,10 @@ var v0 = { "kind": "ScalarField", "name": "id", "storageKey": null -}; +}, +v1 = [ + (v0/*: any*/) +]; return { "fragment": { "argumentDefinitions": [], @@ -347,13 +349,10 @@ return { "backingField": { "name": "person", "args": null, + "fragment": null, "kind": "RelayResolver", "storageKey": null, - "isOutputType": false, - "resolverInfo": { - "resolverFunction": require('QueryResolvers').person, - "rootFragment": null - } + "isOutputType": false }, "linkedField": { "alias": null, @@ -376,13 +375,29 @@ return { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "User", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "User", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('UserTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true }, (v0/*: any*/) ], @@ -395,13 +410,29 @@ return { { "name": "name", "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": [ + { + "name": "__relay_model_instance", + "args": null, + "fragment": { + "kind": "InlineFragment", + "selections": (v1/*: any*/), + "type": "Admin", + "abstractKey": null + }, + "kind": "RelayResolver", + "storageKey": null, + "isOutputType": false + } + ], + "type": "Admin", + "abstractKey": null + }, "kind": "RelayResolver", "storageKey": null, - "isOutputType": true, - "resolverInfo": { - "resolverFunction": require('AdminTypeResolvers').name, - "rootFragment": null - } + "isOutputType": true }, (v0/*: any*/) ], diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.input index 8a785084bf870..db997cdb4cd82 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.input +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_returns_union_of_strong_resolver.input @@ -42,7 +42,6 @@ graphql`query PersonComponentQuery { "schema-extensions" ], "featureFlags": { - "enable_resolver_normalization_ast": true, "relay_resolver_enable_interface_output_type": { "kind": "enabled" } } } diff --git a/packages/relay-runtime/util/NormalizationNode.js b/packages/relay-runtime/util/NormalizationNode.js index c2f190bde9136..c7015fe927031 100644 --- a/packages/relay-runtime/util/NormalizationNode.js +++ b/packages/relay-runtime/util/NormalizationNode.js @@ -200,10 +200,17 @@ export type NormalizationLiveResolverField = { ...ResolverData, }; +export type NormalizationModelResolvers = { + [string]: { + +resolverModule: ResolverModule, + }, +}; + export type NormalizationClientEdgeToClientObject = { +kind: 'ClientEdgeToClientObject', +linkedField: NormalizationLinkedField, +backingField: NormalizationResolverField | NormalizationLiveResolverField, + +modelResolvers?: NormalizationModelResolvers | null, }; export type NormalizationClientComponent = {