Skip to content

Commit

Permalink
A RelayResolverValue generic
Browse files Browse the repository at this point in the history
Reviewed By: evanyeung

Differential Revision: D58156313

fbshipit-source-id: 776c27e1f120e808320cbe0f789f2f808900d816
  • Loading branch information
tyao1 authored and facebook-github-bot committed Jun 5, 2024
1 parent 722b18f commit 8cce449
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 3 deletions.
16 changes: 15 additions & 1 deletion compiler/crates/relay-schema-generation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ fn return_type_to_type_annotation(
source_location: SourceLocationKey,
return_type: &FlowTypeAnnotation,
) -> DiagnosticsResult<TypeAnnotation> {
let (return_type, is_optional) = schema_extractor::unwrap_nullable_type(return_type);
let (return_type, mut is_optional) = schema_extractor::unwrap_nullable_type(return_type);
let location = to_location(source_location, return_type);
let type_annotation = match return_type {
FlowTypeAnnotation::GenericTypeAnnotation(node) => {
Expand Down Expand Up @@ -871,6 +871,20 @@ fn return_type_to_type_annotation(
)]);
}
}
"RelayResolverValue" => {
// Special case for `RelayResolverValue`, it is always optional
is_optional = true;
TypeAnnotation::Named(NamedTypeAnnotation {
name: Identifier {
span: location.span(),
token: Token {
span: location.span(),
kind: TokenKind::Identifier,
},
value: intern!("RelayResolverValue"),
},
})
}
_ => {
return Err(vec![Diagnostic::error(
SchemaGenerationError::UnSupportedGeneric {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
==================================== INPUT ====================================
//- module.js

/**
* 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.
*/

import type CatFlowType from 'Cat';

import type { RelayResolverValue } from 'relay-runtime';

/**
* @RelayResolver
*/
export function Cat(id: DataID): CatFlowType {
return {};
}

/**
* @RelayResolver
*/
export function complexValue(cat: CatFlowType): RelayResolverValue<{a: 1, b: 2}> {
return {a: 1, b: 2};
}

/**
* @RelayResolver
*/
export function optionalRelayResolverValue(cat: CatFlowType): ?RelayResolverValue<{a: 1, b: 2}> {
return null;
}

/**
* @RelayResolver
*/
export function relayResolveValueOverridesAllOtherAnnotation(cat: CatFlowType): ?RelayResolverValue<IdOf<"Cat">> {
return {id: '1'};
}
==================================== OUTPUT ===================================
Field(
TerseRelayResolver(
TerseRelayResolverIr {
field: FieldDefinition {
name: Identifier {
span: 419:431,
token: Token {
span: 419:431,
kind: Identifier,
},
value: "complexValue",
},
type_: Named(
NamedTypeAnnotation {
name: Identifier {
span: 451:483,
token: Token {
span: 451:483,
kind: Identifier,
},
value: "RelayResolverValue",
},
},
),
arguments: None,
directives: [],
description: None,
hack_source: None,
span: 419:431,
},
type_: WithLocation {
location: <generated>:330:333,
item: "Cat",
},
root_fragment: None,
deprecated: None,
semantic_non_null: None,
live: None,
location: module.js:419:431,
fragment_arguments: None,
source_hash: ResolverSourceHash(
"fc15c065174264428a3632fe9cf329d6",
),
},
),
)
extend type Cat {
complexValue: RelayResolverValue @relay_resolver(fragment_name: "Cat____relay_model_instance", generated_fragment: true, inject_fragment_data: "__relay_model_instance", has_output_type: true, import_name: "complexValue", import_path: "module.js") @resolver_source_hash(value: "fc15c065174264428a3632fe9cf329d6")
}


Field(
TerseRelayResolver(
TerseRelayResolverIr {
field: FieldDefinition {
name: Identifier {
span: 554:580,
token: Token {
span: 554:580,
kind: Identifier,
},
value: "optionalRelayResolverValue",
},
type_: Named(
NamedTypeAnnotation {
name: Identifier {
span: 601:633,
token: Token {
span: 601:633,
kind: Identifier,
},
value: "RelayResolverValue",
},
},
),
arguments: None,
directives: [],
description: None,
hack_source: None,
span: 554:580,
},
type_: WithLocation {
location: <generated>:330:333,
item: "Cat",
},
root_fragment: None,
deprecated: None,
semantic_non_null: None,
live: None,
location: module.js:554:580,
fragment_arguments: None,
source_hash: ResolverSourceHash(
"fc15c065174264428a3632fe9cf329d6",
),
},
),
)
extend type Cat {
optionalRelayResolverValue: RelayResolverValue @relay_resolver(fragment_name: "Cat____relay_model_instance", generated_fragment: true, inject_fragment_data: "__relay_model_instance", has_output_type: true, import_name: "optionalRelayResolverValue", import_path: "module.js") @resolver_source_hash(value: "fc15c065174264428a3632fe9cf329d6")
}


Field(
TerseRelayResolver(
TerseRelayResolverIr {
field: FieldDefinition {
name: Identifier {
span: 696:740,
token: Token {
span: 696:740,
kind: Identifier,
},
value: "relayResolveValueOverridesAllOtherAnnotation",
},
type_: Named(
NamedTypeAnnotation {
name: Identifier {
span: 761:792,
token: Token {
span: 761:792,
kind: Identifier,
},
value: "RelayResolverValue",
},
},
),
arguments: None,
directives: [],
description: None,
hack_source: None,
span: 696:740,
},
type_: WithLocation {
location: <generated>:330:333,
item: "Cat",
},
root_fragment: None,
deprecated: None,
semantic_non_null: None,
live: None,
location: module.js:696:740,
fragment_arguments: None,
source_hash: ResolverSourceHash(
"fc15c065174264428a3632fe9cf329d6",
),
},
),
)
extend type Cat {
relayResolveValueOverridesAllOtherAnnotation: RelayResolverValue @relay_resolver(fragment_name: "Cat____relay_model_instance", generated_fragment: true, inject_fragment_data: "__relay_model_instance", has_output_type: true, import_name: "relayResolveValueOverridesAllOtherAnnotation", import_path: "module.js") @resolver_source_hash(value: "fc15c065174264428a3632fe9cf329d6")
}


Type(
StrongObjectResolver(
StrongObjectIr {
type_name: Identifier {
span: 330:333,
token: Token {
span: 330:333,
kind: Identifier,
},
value: "Cat",
},
rhs_location: module.js:330:333,
root_fragment: WithLocation {
location: module.js:330:333,
item: FragmentDefinitionName(
"Cat__id",
),
},
description: None,
deprecated: None,
live: None,
semantic_non_null: None,
location: module.js:330:333,
implements_interfaces: [],
source_hash: ResolverSourceHash(
"fc15c065174264428a3632fe9cf329d6",
),
},
),
)
type Cat @__RelayResolverModel {
id: ID!
__relay_model_instance: RelayResolverValue! @relay_resolver(generated_fragment: true, fragment_name: "Cat__id", import_name: "Cat", import_path: "module.js", inject_fragment_data: "id") @resolver_source_hash(value: "fc15c065174264428a3632fe9cf329d6") @unselectable(reason: "This field is intended only for Relay's internal use")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//- module.js

/**
* 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.
*/

import type CatFlowType from 'Cat';

import type { RelayResolverValue } from 'relay-runtime';

/**
* @RelayResolver
*/
export function Cat(id: DataID): CatFlowType {
return {};
}

/**
* @RelayResolver
*/
export function complexValue(cat: CatFlowType): RelayResolverValue<{a: 1, b: 2}> {
return {a: 1, b: 2};
}

/**
* @RelayResolver
*/
export function optionalRelayResolverValue(cat: CatFlowType): ?RelayResolverValue<{a: 1, b: 2}> {
return null;
}

/**
* @RelayResolver
*/
export function relayResolveValueOverridesAllOtherAnnotation(cat: CatFlowType): ?RelayResolverValue<IdOf<"Cat">> {
return {id: '1'};
}
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<<8ea8d4359f6e14415e193be12974b772>>
* @generated SignedSource<<4de8fcba1c45e8cec09648c0767a6efe>>
*/

mod docblock;
Expand Down Expand Up @@ -103,6 +103,13 @@ async fn return_optional_weak_object() {
test_fixture(transform_fixture, file!(), "return-optional-weak-object.input", "docblock/fixtures/return-optional-weak-object.expected", input, expected).await;
}

#[tokio::test]
async fn return_relay_resolver_value() {
let input = include_str!("docblock/fixtures/return-relay-resolver-value.input");
let expected = include_str!("docblock/fixtures/return-relay-resolver-value.expected");
test_fixture(transform_fixture, file!(), "return-relay-resolver-value.input", "docblock/fixtures/return-relay-resolver-value.expected", input, expected).await;
}

#[tokio::test]
async fn root_fragment() {
let input = include_str!("docblock/fixtures/root-fragment.input");
Expand Down
5 changes: 5 additions & 0 deletions packages/relay-runtime/experimental.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ import type {DataID} from './util/RelayRuntimeTypes';

const resolverDataInjector = require('./store/experimental-live-resolvers/resolverDataInjector');

// Annotates a strong object return type, where `A` is the GraphQL typename
// eslint-disable-next-line no-unused-vars
export type IdOf<A> = DataID;

// Annotates a `RelayResolverValue` GraphQL return type
// eslint-disable-next-line no-unused-vars
export type RelayResolverValue<A> = A;

module.exports = {
resolverDataInjector,
};
2 changes: 1 addition & 1 deletion packages/relay-runtime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export type {Local3DPayload} from './util/createPayloadFor3DField';
export type {Direction} from './util/getPaginationVariables';
export type {RequestIdentifier} from './util/getRequestIdentifier';
export type {ResolverFunction} from './util/ReaderNode';
export type {IdOf} from './experimental';
export type {IdOf, RelayResolverValue} from './experimental';

// As early as possible, check for the existence of the JavaScript globals which
// Relay Runtime relies upon, and produce a clear message if they do not exist.
Expand Down

0 comments on commit 8cce449

Please sign in to comment.