From 76d6d77532fa1850f436b547eaa98f49c95bfa7d Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Fri, 19 Apr 2024 16:37:58 -0700 Subject: [PATCH] Demonstrate using custom scalar to replace RelayResolverValue Reviewed By: monicatang Differential Revision: D56368057 fbshipit-source-id: 83ee49749998eee59c8293c7cb5088a14ef45652 --- ...n_interface_returns_custom_scalar.expected | 392 ++++++++++++++++++ ...r_on_interface_returns_custom_scalar.input | 64 +++ .../tests/relay_compiler_integration_test.rs | 9 +- 3 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.expected create mode 100644 compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.input diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.expected b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.expected new file mode 100644 index 0000000000000..5bc2d2438307c --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.expected @@ -0,0 +1,392 @@ +==================================== INPUT ==================================== +//- PersonComponent.js +graphql`fragment PersonComponentFragment on IPerson { + someComplexObject +}` + +//- UserTypeResolvers.js +/** + * @RelayResolver User implements IPerson + */ +// Implementation omitted for test + +/** + * @RelayResolver User.someComplexObject: SomeComplexObject + */ +// Implementation omitted for test + +//- AdminTypeResolvers.js +/** + * @RelayResolver Admin implements IPerson + */ +// Implementation omitted for test + +/** + * @RelayResolver Admin.someComplexObject: SomeComplexObject + */ +// Implementation omitted for test + +//- SomeComplexObjectFlowTypeModule.js + +export type SomeComplexObjectFlowType { + // ... Many fields here perhaps +} + +//- relay.config.json +{ + "language": "flow", + "jsModuleFormat": "haste", + "schema": "schema.graphql", + "schemaExtensions": [ + "schema-extensions" + ], + "customScalarTypes": { + "SomeComplexObject": { + "name": "SomeComplexObjectFlowType", + "path": "SomeComplexObjectFlowTypeModule" + } + }, + "featureFlags": { + "enable_relay_resolver_transform": true, + "enable_resolver_normalization_ast": true, + "relay_resolver_enable_interface_output_type": { "kind": "enabled" } + } +} + +//- schema.graphql +# Empty server schema + +//- schema-extensions/extension.graphql +scalar SomeComplexObject + +interface IPerson { + id: ID! + someComplexObject: SomeComplexObject +} +==================================== OUTPUT =================================== +//- __generated__/Admin____relay_model_instance.graphql.js +/** + * SignedSource<<7fbe3989595c55397f4bcc5c81ec30b2>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { Fragment, ReaderFragment } from 'relay-runtime'; +import type { Admin__id$data } from "Admin__id.graphql"; +import type { FragmentType } from "relay-runtime"; +import {Admin as adminRelayModelInstanceResolverType} from "AdminTypeResolvers"; +// Type assertion validating that `adminRelayModelInstanceResolverType` resolver is correctly implemented. +// A type error here indicates that the type signature of the resolver module is incorrect. +(adminRelayModelInstanceResolverType: ( + id: Admin__id$data['id'], +) => mixed); +declare export opaque type Admin____relay_model_instance$fragmentType: FragmentType; +export type Admin____relay_model_instance$data = {| + +__relay_model_instance: $NonMaybeType>, + +$fragmentType: Admin____relay_model_instance$fragmentType, +|}; +export type Admin____relay_model_instance$key = { + +$data?: Admin____relay_model_instance$data, + +$fragmentSpreads: Admin____relay_model_instance$fragmentType, + ... +}; +*/ + +var node/*: ReaderFragment*/ = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "Admin____relay_model_instance", + "selections": [ + { + "alias": null, + "args": null, + "fragment": { + "args": null, + "kind": "FragmentSpread", + "name": "Admin__id" + }, + "kind": "RelayResolver", + "name": "__relay_model_instance", + "resolverModule": require('relay-runtime/experimental').resolverDataInjector(require('Admin__id.graphql'), require('AdminTypeResolvers').Admin, 'id', true), + "path": "__relay_model_instance" + } + ], + "type": "Admin", + "abstractKey": null +}; + +module.exports = ((node/*: any*/)/*: Fragment< + Admin____relay_model_instance$fragmentType, + Admin____relay_model_instance$data, +>*/); + +//- __generated__/Admin__id.graphql.js +/** + * SignedSource<<29acfbf1d6f559b8b77e9cd1f35218c0>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { Fragment, ReaderFragment } from 'relay-runtime'; +import type { FragmentType } from "relay-runtime"; +declare export opaque type Admin__id$fragmentType: FragmentType; +export type Admin__id$data = {| + +id: string, + +$fragmentType: Admin__id$fragmentType, +|}; +export type Admin__id$key = { + +$data?: Admin__id$data, + +$fragmentSpreads: Admin__id$fragmentType, + ... +}; +*/ + +var node/*: ReaderFragment*/ = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "Admin__id", + "selections": [ + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + } + ] + } + ], + "type": "Admin", + "abstractKey": null +}; + +module.exports = ((node/*: any*/)/*: Fragment< + Admin__id$fragmentType, + Admin__id$data, +>*/); + +//- __generated__/PersonComponentFragment.graphql.js +/** + * SignedSource<<5a351d5a9beb2093277e17f6efa94c15>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { Fragment, ReaderFragment } from 'relay-runtime'; +import type { SomeComplexObjectFlowType } from "SomeComplexObjectFlowTypeModule"; +import type { FragmentType } from "relay-runtime"; +declare export opaque type PersonComponentFragment$fragmentType: FragmentType; +export type PersonComponentFragment$data = {| + +someComplexObject: ?SomeComplexObjectFlowType, + +$fragmentType: PersonComponentFragment$fragmentType, +|}; +export type PersonComponentFragment$key = { + +$data?: PersonComponentFragment$data, + +$fragmentSpreads: PersonComponentFragment$fragmentType, + ... +}; +*/ + +var node/*: ReaderFragment*/ = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "PersonComponentFragment", + "selections": [ + { + "kind": "ClientExtension", + "selections": [ + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "fragment": { + "args": null, + "kind": "FragmentSpread", + "name": "Admin____relay_model_instance" + }, + "kind": "RelayResolver", + "name": "someComplexObject", + "resolverModule": require('relay-runtime/experimental').resolverDataInjector(require('Admin____relay_model_instance.graphql'), require('AdminTypeResolvers').someComplexObject, '__relay_model_instance', true), + "path": "someComplexObject" + } + ], + "type": "Admin", + "abstractKey": null + }, + { + "kind": "InlineFragment", + "selections": [ + { + "alias": null, + "args": null, + "fragment": { + "args": null, + "kind": "FragmentSpread", + "name": "User____relay_model_instance" + }, + "kind": "RelayResolver", + "name": "someComplexObject", + "resolverModule": require('relay-runtime/experimental').resolverDataInjector(require('User____relay_model_instance.graphql'), require('UserTypeResolvers').someComplexObject, '__relay_model_instance', true), + "path": "someComplexObject" + } + ], + "type": "User", + "abstractKey": null + } + ] + } + ], + "type": "IPerson", + "abstractKey": "__isIPerson" +}; + +(node/*: any*/).hash = "d8e63d57ea12bd6248ca0a69e440f37c"; + +module.exports = ((node/*: any*/)/*: Fragment< + PersonComponentFragment$fragmentType, + PersonComponentFragment$data, +>*/); + +//- __generated__/User____relay_model_instance.graphql.js +/** + * SignedSource<<7ffabc2a97c3589cbfd20a23b3b608ca>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { Fragment, ReaderFragment } from 'relay-runtime'; +import type { User__id$data } from "User__id.graphql"; +import type { FragmentType } from "relay-runtime"; +import {User as userRelayModelInstanceResolverType} from "UserTypeResolvers"; +// Type assertion validating that `userRelayModelInstanceResolverType` resolver is correctly implemented. +// A type error here indicates that the type signature of the resolver module is incorrect. +(userRelayModelInstanceResolverType: ( + id: User__id$data['id'], +) => mixed); +declare export opaque type User____relay_model_instance$fragmentType: FragmentType; +export type User____relay_model_instance$data = {| + +__relay_model_instance: $NonMaybeType>, + +$fragmentType: User____relay_model_instance$fragmentType, +|}; +export type User____relay_model_instance$key = { + +$data?: User____relay_model_instance$data, + +$fragmentSpreads: User____relay_model_instance$fragmentType, + ... +}; +*/ + +var node/*: ReaderFragment*/ = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "User____relay_model_instance", + "selections": [ + { + "alias": null, + "args": null, + "fragment": { + "args": null, + "kind": "FragmentSpread", + "name": "User__id" + }, + "kind": "RelayResolver", + "name": "__relay_model_instance", + "resolverModule": require('relay-runtime/experimental').resolverDataInjector(require('User__id.graphql'), require('UserTypeResolvers').User, 'id', true), + "path": "__relay_model_instance" + } + ], + "type": "User", + "abstractKey": null +}; + +module.exports = ((node/*: any*/)/*: Fragment< + User____relay_model_instance$fragmentType, + User____relay_model_instance$data, +>*/); + +//- __generated__/User__id.graphql.js +/** + * SignedSource<<0a0f39eb34bfc882d28378a0b05b3c17>> + * @flow + * @lightSyntaxTransform + * @nogrep + */ + +/* eslint-disable */ + +'use strict'; + +/*:: +import type { Fragment, ReaderFragment } from 'relay-runtime'; +import type { FragmentType } from "relay-runtime"; +declare export opaque type User__id$fragmentType: FragmentType; +export type User__id$data = {| + +id: string, + +$fragmentType: User__id$fragmentType, +|}; +export type User__id$key = { + +$data?: User__id$data, + +$fragmentSpreads: User__id$fragmentType, + ... +}; +*/ + +var node/*: ReaderFragment*/ = { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "User__id", + "selections": [ + { + "kind": "ClientExtension", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "id", + "storageKey": null + } + ] + } + ], + "type": "User", + "abstractKey": null +}; + +module.exports = ((node/*: any*/)/*: Fragment< + User__id$fragmentType, + User__id$data, +>*/); diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.input b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.input new file mode 100644 index 0000000000000..68b026ac10f79 --- /dev/null +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.input @@ -0,0 +1,64 @@ +//- PersonComponent.js +graphql`fragment PersonComponentFragment on IPerson { + someComplexObject +}` + +//- UserTypeResolvers.js +/** + * @RelayResolver User implements IPerson + */ +// Implementation omitted for test + +/** + * @RelayResolver User.someComplexObject: SomeComplexObject + */ +// Implementation omitted for test + +//- AdminTypeResolvers.js +/** + * @RelayResolver Admin implements IPerson + */ +// Implementation omitted for test + +/** + * @RelayResolver Admin.someComplexObject: SomeComplexObject + */ +// Implementation omitted for test + +//- SomeComplexObjectFlowTypeModule.js + +export type SomeComplexObjectFlowType { + // ... Many fields here perhaps +} + +//- relay.config.json +{ + "language": "flow", + "jsModuleFormat": "haste", + "schema": "schema.graphql", + "schemaExtensions": [ + "schema-extensions" + ], + "customScalarTypes": { + "SomeComplexObject": { + "name": "SomeComplexObjectFlowType", + "path": "SomeComplexObjectFlowTypeModule" + } + }, + "featureFlags": { + "enable_relay_resolver_transform": true, + "enable_resolver_normalization_ast": true, + "relay_resolver_enable_interface_output_type": { "kind": "enabled" } + } +} + +//- schema.graphql +# Empty server schema + +//- schema-extensions/extension.graphql +scalar SomeComplexObject + +interface IPerson { + id: ID! + someComplexObject: SomeComplexObject +} diff --git a/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs b/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs index 000045cc60b5d..9969b29107dd0 100644 --- a/compiler/crates/relay-compiler/tests/relay_compiler_integration_test.rs +++ b/compiler/crates/relay-compiler/tests/relay_compiler_integration_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<> + * @generated SignedSource<> */ mod relay_compiler_integration; @@ -131,6 +131,13 @@ async fn resolver_on_interface_of_all_weak_model_type() { test_fixture(transform_fixture, file!(), "resolver_on_interface_of_all_weak_model_type.input", "relay_compiler_integration/fixtures/resolver_on_interface_of_all_weak_model_type.expected", input, expected).await; } +#[tokio::test] +async fn resolver_on_interface_returns_custom_scalar() { + let input = include_str!("relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.input"); + let expected = include_str!("relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.expected"); + test_fixture(transform_fixture, file!(), "resolver_on_interface_returns_custom_scalar.input", "relay_compiler_integration/fixtures/resolver_on_interface_returns_custom_scalar.expected", input, expected).await; +} + #[tokio::test] async fn resolver_returns_enum() { let input = include_str!("relay_compiler_integration/fixtures/resolver_returns_enum.input");