Skip to content

Commit

Permalink
Allow resolvers with @rootFragment on model types
Browse files Browse the repository at this point in the history
Reviewed By: davidmccabe

Differential Revision: D45199425

fbshipit-source-id: 9096deaedcca3652488554117c32a5936d8d57a2
  • Loading branch information
captbaritone authored and facebook-github-bot committed Apr 25, 2023
1 parent 123dd0a commit fccb3c8
Show file tree
Hide file tree
Showing 11 changed files with 630 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
==================================== INPUT ====================================
query resolverWithRootFragmentOnModelType_Query {
my_type {
my_field
}
}

fragment resolverWithRootFragmentOnModelTypeRootFragment on MyType {
id
}

# %extensions%

type MyType @__RelayResolverModel {
id: ID!
__relay_model_instance: Int
@relay_resolver(
import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js"
fragment_name: "MyType__id"
inject_fragment_data: "id"
import_name: "MyType"
)
@unselectable(
reason: "This field is intended only for Relay's internal use"
)
}

extend type MyType {
my_field: String
@relay_resolver(
import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js"
fragment_name: "resolverWithRootFragmentOnModelTypeRootFragment"
has_output_type: true
import_name: "my_field"
)
}

extend type Query {
my_type: MyType
}
==================================== OUTPUT ===================================
{
"fragment": {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "resolverWithRootFragmentOnModelType_Query",
"selections": [
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "MyType",
"kind": "LinkedField",
"name": "my_type",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"fragment": {
"args": null,
"kind": "FragmentSpread",
"name": "resolverWithRootFragmentOnModelTypeRootFragment"
},
"kind": "RelayResolver",
"name": "my_field",
"resolverModule": require('terse-relay-resolver-with-root-fragment-on-model').my_field,
"path": "my_type.my_field"
}
],
"storageKey": null
}
]
}
],
"type": "Query",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": [],
"kind": "Operation",
"name": "resolverWithRootFragmentOnModelType_Query",
"selections": [
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "MyType",
"kind": "LinkedField",
"name": "my_type",
"plural": false,
"selections": [
{
"name": "my_field",
"args": null,
"fragment": {
"kind": "InlineFragment",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"type": "MyType",
"abstractKey": null
},
"kind": "RelayResolver",
"storageKey": null,
"isOutputType": true
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
],
"storageKey": null
}
]
}
]
},
"params": {
"cacheID": "6a469c8af9ccbc6879fcb39a2bff5b2e",
"id": null,
"metadata": {},
"name": "resolverWithRootFragmentOnModelType_Query",
"operationKind": "query",
"text": null
}
}

QUERY:

Query Text is Empty.

{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyType____relay_model_instance",
"selections": [
{
"alias": null,
"args": null,
"fragment": {
"args": null,
"kind": "FragmentSpread",
"name": "MyType__id"
},
"kind": "RelayResolver",
"name": "__relay_model_instance",
"resolverModule": require('relay-runtime/experimental').resolverDataInjector(require('MyType__id.graphql'), require('terse-relay-resolver-with-root-fragment-on-model').MyType, 'id', true),
"path": "__relay_model_instance"
}
],
"type": "MyType",
"abstractKey": null
}

{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyType__id",
"selections": [
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
]
}
],
"type": "MyType",
"abstractKey": null
}

{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "resolverWithRootFragmentOnModelTypeRootFragment",
"selections": [
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
}
]
}
],
"type": "MyType",
"abstractKey": null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
query resolverWithRootFragmentOnModelType_Query {
my_type {
my_field
}
}

fragment resolverWithRootFragmentOnModelTypeRootFragment on MyType {
id
}

# %extensions%

type MyType @__RelayResolverModel {
id: ID!
__relay_model_instance: Int
@relay_resolver(
import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js"
fragment_name: "MyType__id"
inject_fragment_data: "id"
import_name: "MyType"
)
@unselectable(
reason: "This field is intended only for Relay's internal use"
)
}

extend type MyType {
my_field: String
@relay_resolver(
import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js"
fragment_name: "resolverWithRootFragmentOnModelTypeRootFragment"
has_output_type: true
import_name: "my_field"
)
}

extend type Query {
my_type: MyType
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<<ee27cc847ad47c04e69070e0dd743220>>
* @generated SignedSource<<f102f3a35dc23f176e3d4b53f6db4c2e>>
*/

mod compile_relay_artifacts;
Expand Down Expand Up @@ -1272,6 +1272,13 @@ fn required_directive() {
test_fixture(transform_fixture, "required-directive.graphql", "compile_relay_artifacts/fixtures/required-directive.expected", input, expected);
}

#[test]
fn resolver_with_root_fragment_on_model_type() {
let input = include_str!("compile_relay_artifacts/fixtures/resolver-with-root-fragment-on-model-type.graphql");
let expected = include_str!("compile_relay_artifacts/fixtures/resolver-with-root-fragment-on-model-type.expected");
test_fixture(transform_fixture, "resolver-with-root-fragment-on-model-type.graphql", "compile_relay_artifacts/fixtures/resolver-with-root-fragment-on-model-type.expected", input, expected);
}

#[test]
fn same_fields_with_different_args_invalid() {
let input = include_str!("compile_relay_artifacts/fixtures/same-fields-with-different-args.invalid.graphql");
Expand Down
7 changes: 4 additions & 3 deletions compiler/crates/relay-docblock/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,12 +665,12 @@ impl ResolverIr for TerseRelayResolverIr {
object: Option<&Object>,
_: SchemaInfo<'_, '_>,
) -> Option<RootFragment> {
get_root_fragment_for_object(object).or_else(|| {
self.root_fragment.map(|fragment| RootFragment {
self.root_fragment
.map(|fragment| RootFragment {
fragment,
inject_fragment_data: None,
})
})
.or_else(|| get_root_fragment_for_object(object))
}

fn output_type(&self) -> Option<OutputType> {
Expand Down Expand Up @@ -1320,6 +1320,7 @@ fn dummy_token(span: Span) -> Token {
}
}

// Here
fn get_root_fragment_for_object(object: Option<&Object>) -> Option<RootFragment> {
if object?
.directives
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
==================================== INPUT ====================================
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @RelayResolver MyType
*/

/**
* @RelayResolver MyType.my_field: String
* @rootFragment myRootFragment
*/

graphql`
fragment myRootFragment on MyType {
id
}
`
==================================== OUTPUT ===================================
type MyType @__RelayResolverModel {
id: ID!
__relay_model_instance: Int @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js", fragment_name: "MyType__id", inject_fragment_data: "id", import_name: "MyType") @unselectable(reason: "This field is intended only for Relay's internal use")
}


extend type MyType {
my_field: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "my_field")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

/**
* @RelayResolver MyType
*/

/**
* @RelayResolver MyType.my_field: String
* @rootFragment myRootFragment
*/

graphql`
fragment myRootFragment on MyType {
id
}
`
9 changes: 8 additions & 1 deletion compiler/crates/relay-docblock/tests/to_schema_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<<8c829590b9a20caf63439cd36a113237>>
* @generated SignedSource<<2e5845b82e759855402d5ec1f62cd56f>>
*/

mod to_schema;
Expand Down Expand Up @@ -243,6 +243,13 @@ fn terse_relay_resolver_with_output_type() {
test_fixture(transform_fixture, "terse-relay-resolver-with-output-type.js", "to_schema/fixtures/terse-relay-resolver-with-output-type.expected", input, expected);
}

#[test]
fn terse_relay_resolver_with_root_fragment_on_model() {
let input = include_str!("to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.js");
let expected = include_str!("to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.expected");
test_fixture(transform_fixture, "terse-relay-resolver-with-root-fragment-on-model.js", "to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.expected", input, expected);
}

#[test]
fn terse_resolver_duplicated_invalid() {
let input = include_str!("to_schema/fixtures/terse-resolver-duplicated.invalid.js");
Expand Down
Loading

0 comments on commit fccb3c8

Please sign in to comment.