Skip to content

Commit

Permalink
Reuse TypegenConfig for SingleProjectConfigFile (#4585)
Browse files Browse the repository at this point in the history
Summary:
There are some slight discrepancies between multi- and single-project configs at the moment, with some options only being configurable from multi-project configs, even though the compiler could read and support the same settings from both type of configs (examples: `use_import_type_syntax`, `require_custom_scalar_types`, etc.).

## Changes

- Flatten `TypegenConfig` in `SingleProjectConfigFile` and remove duplicated options
- Inlines `no_future_proof_enums` from `FlowTypegenConfig` into `TypegenConfig` and removes `FlowTypegenConfig` as it's now no longer required
- When parsing of the config file fails, show the single-project config error first, since that is the configuration most people use

## ⚠️ Breaking change

This change is a breaking change, as the `custom_scalars` config option in the single-project config must now be specified as `custom_scalar_types`.

Pull Request resolved: #4585

Test Plan:
captbaritone: I've confirmed that WWW still compiles without error

I validated that omitting `language` still results in an error (it is now consistent and both single or multi project configs require the `language` field. {F1318391525}

Reviewed By: alunyov

Differential Revision: D52806277

Pulled By: captbaritone

fbshipit-source-id: 02d889833a1d0979c28037cf48b5ae9fa129448d
  • Loading branch information
tobias-tengler authored and facebook-github-bot committed Jan 19, 2024
1 parent 5718ca9 commit 4e68155
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 77 deletions.
63 changes: 7 additions & 56 deletions compiler/crates/relay-compiler/src/config.rs
Expand Up @@ -16,7 +16,6 @@ use std::vec;
use async_trait::async_trait;
use common::FeatureFlags;
use common::Rollout;
use common::ScalarName;
use dunce::canonicalize;
use fnv::FnvBuildHasher;
use fnv::FnvHashSet;
Expand All @@ -29,10 +28,8 @@ use log::warn;
use persist_query::PersistError;
use rayon::prelude::*;
use regex::Regex;
use relay_config::CustomScalarType;
use relay_config::DiagnosticReportConfig;
pub use relay_config::ExtraArtifactsConfig;
use relay_config::FlowTypegenConfig;
use relay_config::JsModuleFormat;
pub use relay_config::LocalPersistConfig;
use relay_config::ModuleImportConfig;
Expand Down Expand Up @@ -694,21 +691,8 @@ pub struct SingleProjectConfigFile {
/// List of directories with schema extensions.
pub schema_extensions: Vec<PathBuf>,

/// This option controls whether or not a catch-all entry is added to enum type definitions
/// for values that may be added in the future. Enabling this means you will have to update
/// your application whenever the GraphQL server schema adds new enum values to prevent it
/// from breaking.
pub no_future_proof_enums: bool,

/// The name of the language plugin (?) used for input files and artifacts
pub language: Option<TypegenLanguage>,

/// Mappings from custom scalars in your schema to built-in GraphQL
/// types, for type emission purposes.
pub custom_scalars: FnvIndexMap<ScalarName, CustomScalarType>,

/// This option enables emitting es modules artifacts.
pub eager_es_modules: bool,
#[serde(flatten)]
pub typegen_config: TypegenConfig,

/// Query Persist Configuration
/// It contains URL and addition parameters that will be included
Expand Down Expand Up @@ -740,12 +724,6 @@ pub struct SingleProjectConfigFile {
#[serde(default)]
pub feature_flags: Option<FeatureFlags>,

/// Keep the previous compiler behavior by outputting an union
/// of the raw type and null, and not the **correct** behavior
/// of an union with the raw type, null and undefined.
#[serde(default)]
pub typescript_exclude_undefined_from_nullable_union: bool,

#[serde(default)]
pub resolvers_schema_module: Option<ResolversSchemaModuleConfig>,
}
Expand All @@ -761,18 +739,14 @@ impl Default for SingleProjectConfigFile {
extensions: vec![],
excludes: get_default_excludes(),
schema_extensions: vec![],
no_future_proof_enums: false,
language: None,
custom_scalars: Default::default(),
schema_config: Default::default(),
eager_es_modules: false,
typegen_config: Default::default(),
persist_config: None,
is_dev_variable_name: None,
codegen_command: None,
js_module_format: JsModuleFormat::CommonJS,
typegen_phase: None,
feature_flags: None,
typescript_exclude_undefined_from_nullable_union: false,
module_import_config: Default::default(),
resolvers_schema_module: Default::default(),
}
Expand Down Expand Up @@ -853,18 +827,6 @@ impl SingleProjectConfigFile {
}
})?;

let language = self.language.ok_or_else(|| {
let mut variants = vec![];
for lang in TypegenLanguage::get_variants_as_string() {
variants.push(format!(r#" "language": "{}""#, lang));
}

Error::ConfigError {
details: format!("The `language` option is missing in the Relay configuration file. Please, specify one of the following options:\n{}", variants.join("\n")),
}
}
)?;

let project_config = ConfigFileProject {
output: self.artifact_directory.map(|dir| {
normalize_path_from_config(current_dir.clone(), common_root_dir.clone(), dir)
Expand All @@ -887,18 +849,7 @@ impl SingleProjectConfigFile {
})
.collect(),
persist: self.persist_config,
typegen_config: TypegenConfig {
language,
custom_scalar_types: self.custom_scalars.clone(),
eager_es_modules: self.eager_es_modules,
flow_typegen: FlowTypegenConfig {
no_future_proof_enums: self.no_future_proof_enums,
..Default::default()
},
typescript_exclude_undefined_from_nullable_union: self
.typescript_exclude_undefined_from_nullable_union,
..Default::default()
},
typegen_config: self.typegen_config,
js_module_format: self.js_module_format,
feature_flags: self.feature_flags,
module_import_config: self.module_import_config,
Expand Down Expand Up @@ -948,12 +899,12 @@ impl<'de> Deserialize<'de> for ConfigFile {
Ok(single_project_config) => Ok(ConfigFile::SingleProject(single_project_config)),
Err(single_project_error) => {
let error_message = format!(
r#"The config file cannot be parsed as a multi-project config file due to:
r#"The config file cannot be parsed as a single-project config file due to:
- {:?}.
It also cannot be a single project config file due to:
It also cannot be a multi-project config file due to:
- {:?}."#,
multi_project_error, single_project_error
single_project_error, multi_project_error,
);

Err(DeError::custom(error_message))
Expand Down
1 change: 0 additions & 1 deletion compiler/crates/relay-config/src/lib.rs
Expand Up @@ -40,6 +40,5 @@ pub use project_name::ProjectName;
pub use resolvers_schema_module_config::ResolversSchemaModuleConfig;
pub use typegen_config::CustomScalarType;
pub use typegen_config::CustomScalarTypeImport;
pub use typegen_config::FlowTypegenConfig;
pub use typegen_config::TypegenConfig;
pub use typegen_config::TypegenLanguage;
38 changes: 20 additions & 18 deletions compiler/crates/relay-config/src/typegen_config.rs
Expand Up @@ -34,12 +34,6 @@ pub enum TypegenLanguage {
Flow,
}

impl Default for TypegenLanguage {
fn default() -> Self {
Self::JavaScript
}
}

impl TypegenLanguage {
pub fn get_variants_as_string() -> Vec<String> {
let mut res = vec![];
Expand All @@ -64,7 +58,7 @@ pub struct CustomScalarTypeImport {
pub path: PathBuf,
}

#[derive(Debug, Serialize, Deserialize, Default)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct TypegenConfig {
/// The desired output language, "flow" or "typescript".
Expand Down Expand Up @@ -101,9 +95,12 @@ pub struct TypegenConfig {
#[serde(default)]
pub require_custom_scalar_types: bool,

/// Work in progress new Flow type definitions
/// This option controls whether or not a catch-all entry is added to enum type definitions
/// for values that may be added in the future. Enabling this means you will have to update
/// your application whenever the GraphQL server schema adds new enum values to prevent it
/// from breaking.
#[serde(default)]
pub flow_typegen: FlowTypegenConfig,
pub no_future_proof_enums: bool,

/// This option enables emitting es modules artifacts.
#[serde(default)]
Expand All @@ -116,13 +113,18 @@ pub struct TypegenConfig {
pub typescript_exclude_undefined_from_nullable_union: bool,
}

#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy)]
#[serde(deny_unknown_fields, tag = "phase")]
pub struct FlowTypegenConfig {
/// This option controls whether or not a catch-all entry is added to enum type definitions
/// for values that may be added in the future. Enabling this means you will have to update
/// your application whenever the GraphQL server schema adds new enum values to prevent it
/// from breaking.
#[serde(default)]
pub no_future_proof_enums: bool,
impl Default for TypegenConfig {
fn default() -> Self {
TypegenConfig {
language: TypegenLanguage::JavaScript,
enum_module_suffix: Default::default(),
optional_input_fields: Default::default(),
use_import_type_syntax: Default::default(),
custom_scalar_types: Default::default(),
require_custom_scalar_types: Default::default(),
no_future_proof_enums: Default::default(),
eager_es_modules: Default::default(),
typescript_exclude_undefined_from_nullable_union: Default::default(),
}
}
}
1 change: 0 additions & 1 deletion compiler/crates/relay-typegen/src/write.rs
Expand Up @@ -655,7 +655,6 @@ fn write_enum_definitions(
if !typegen_context
.project_config
.typegen_config
.flow_typegen
.no_future_proof_enums
{
members.push(AST::StringLiteral(StringLiteral(*FUTURE_ENUM_VALUE)));
Expand Down
Expand Up @@ -81,7 +81,6 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String>
typegen_config: TypegenConfig {
language: TypegenLanguage::Flow,
custom_scalar_types,
flow_typegen: Default::default(),
..Default::default()
},
..Default::default()
Expand Down

0 comments on commit 4e68155

Please sign in to comment.