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 = {