Skip to content

Commit

Permalink
Use client schema extension enum values as source of truth for Flow t…
Browse files Browse the repository at this point in the history
…ypes

Reviewed By: monicatang

Differential Revision: D56365733

fbshipit-source-id: 283f01839ec7243ee0b9b5ac55bcbd2a8f8bc8c7
  • Loading branch information
captbaritone authored and facebook-github-bot committed Apr 23, 2024
1 parent b2cf404 commit 349b5a8
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ enum Status {
==================================== OUTPUT ===================================
//- __generated__/SomeComponentFragment.graphql.js
/**
* <auto-generated> SignedSource<<5f1eb0560c62a91c8a4ca0dbf2963b85>>
* <auto-generated> SignedSource<<f6f0388cfc79b6eeaed86875ad2cffd1>>
* @flow
* @lightSyntaxTransform
* @nogrep
Expand All @@ -57,7 +57,7 @@ enum Status {
/*::
import type { Fragment, ReaderFragment } from 'relay-runtime';
import type { User____relay_model_instance$data } from "User____relay_model_instance.graphql";
export type Status = "ADMIN" | "USER" | "%future added value";
export type Status = "ADMIN" | "USER";
import type { FragmentType } from "relay-runtime";
import {status as userStatusResolverType} from "UserTypeResolvers";
// Type assertion validating that `userStatusResolverType` resolver is correctly implemented.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ enum Status {
==================================== OUTPUT ===================================
//- __generated__/SomeComponentFragment.graphql.js
/**
* <auto-generated> SignedSource<<19d9d78bd05aabfe1298f8b3a0c3ae01>>
* <auto-generated> SignedSource<<f6f0388cfc79b6eeaed86875ad2cffd1>>
* @flow
* @lightSyntaxTransform
* @nogrep
Expand All @@ -58,7 +58,7 @@ enum Status {
/*::
import type { Fragment, ReaderFragment } from 'relay-runtime';
import type { User____relay_model_instance$data } from "User____relay_model_instance.graphql";
import type { Status } from "Status.LOL_WHAT";
export type Status = "ADMIN" | "USER";
import type { FragmentType } from "relay-runtime";
import {status as userStatusResolverType} from "UserTypeResolvers";
// Type assertion validating that `userStatusResolverType` resolver is correctly implemented.
Expand Down
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<<be9e021bfe875928b8f65310c8e413a7>>
* @generated SignedSource<<276e2284c38de688261ae6c3a87e49ee>>
*/

mod relay_compiler_integration;
Expand Down Expand Up @@ -139,10 +139,10 @@ async fn resolver_on_interface_returns_custom_scalar() {
}

#[tokio::test]
async fn resolver_returns_enum() {
let input = include_str!("relay_compiler_integration/fixtures/resolver_returns_enum.input");
let expected = include_str!("relay_compiler_integration/fixtures/resolver_returns_enum.expected");
test_fixture(transform_fixture, file!(), "resolver_returns_enum.input", "relay_compiler_integration/fixtures/resolver_returns_enum.expected", input, expected).await;
async fn resolver_returns_client_schema_extension_enum() {
let input = include_str!("relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.input");
let expected = include_str!("relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected");
test_fixture(transform_fixture, file!(), "resolver_returns_client_schema_extension_enum.input", "relay_compiler_integration/fixtures/resolver_returns_client_schema_extension_enum.expected", input, expected).await;
}

#[tokio::test]
Expand Down
33 changes: 23 additions & 10 deletions compiler/crates/relay-typegen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,16 +636,18 @@ fn write_enum_definitions(
writer: &mut Box<dyn Writer>,
) -> FmtResult {
let enum_ids = encountered_enums.into_sorted_vec(typegen_context.schema);
let maybe_suffix = &typegen_context
.project_config
.typegen_config
.enum_module_suffix;
for enum_id in enum_ids {
let enum_type = typegen_context.schema.enum_(enum_id);
if let Some(enum_module_suffix) = &typegen_context
.project_config
.typegen_config
.enum_module_suffix
{
if !enum_type.is_extension && maybe_suffix.is_some() {
// We can't chain `if let` statements, so we need to unwrap here.
let suffix = maybe_suffix.as_ref().unwrap();
writer.write_import_type(
&[enum_type.name.item.lookup()],
&format!("{}{}", enum_type.name.item, enum_module_suffix),
&format!("{}{}", enum_type.name.item, suffix),
)?;
} else {
let mut members: Vec<AST> = enum_type
Expand All @@ -654,10 +656,21 @@ fn write_enum_definitions(
.map(|enum_value| AST::StringLiteral(StringLiteral(enum_value.value)))
.collect();

if !typegen_context
.project_config
.typegen_config
.no_future_proof_enums
// Users can specify a config option to disable the inclusion of
// FUTURE_ENUM_VALUE in the enum union. Additionally we want to avoid
// emitting FUTURE_ENUM_VALUE if the enum is actually defined on the
// client. For example in Client Schema Extensions or (some day)
// Relay Resolvers.
//
// In the case of a client defined enum, we don't need to enforce
// the breaking change semantics dictated by the GraphQL spec
// because new fields added to the client schema will simply result
// in fixable Flow/TypeScript errors elsewhere in the codebase.
if !(enum_type.is_extension
|| typegen_context
.project_config
.typegen_config
.no_future_proof_enums)
{
members.push(AST::StringLiteral(StringLiteral(*FUTURE_ENUM_VALUE)));
}
Expand Down

0 comments on commit 349b5a8

Please sign in to comment.