in compiler/crates/relay-compiler/src/config.rs [212:351]
fn from_struct(
config_path: PathBuf,
config_file: ConfigFile,
validate_fs: bool,
) -> Result<Self> {
let mut hash = Sha1::new();
serde_json::to_writer(&mut hash, &config_file).unwrap();
let config_file = match config_file {
ConfigFile::MultiProject(config) => *config,
ConfigFile::SingleProject(config) => {
config.create_multi_project_config(&config_path)?
}
};
let MultiProjectConfigFile {
feature_flags: config_file_feature_flags,
projects,
..
} = config_file;
let projects = projects
.into_iter()
.map(|(project_name, config_file_project)| {
let schema_location =
match (config_file_project.schema, config_file_project.schema_dir) {
(Some(schema_file), None) => Ok(SchemaLocation::File(schema_file)),
(None, Some(schema_dir)) => Ok(SchemaLocation::Directory(schema_dir)),
_ => Err(Error::ConfigFileValidation {
config_path: config_path.clone(),
validation_errors: vec![
ConfigValidationError::ProjectNeedsSchemaXorSchemaDir {
project_name,
},
],
}),
}?;
let shard_strip_regex = config_file_project
.shard_strip_regex
.map(|s| Regex::new(&s))
.transpose()
.map_err(|error| Error::ConfigFileValidation {
config_path: config_path.clone(),
validation_errors: vec![ConfigValidationError::InvalidRegex {
key: "shardStripRegex",
project_name,
error,
}],
})?;
let test_path_regex = config_file_project
.test_path_regex
.map(|s| Regex::new(&s))
.transpose()
.map_err(|error| Error::ConfigFileValidation {
config_path: config_path.clone(),
validation_errors: vec![ConfigValidationError::InvalidRegex {
key: "testDirectoryRegex",
project_name,
error,
}],
})?;
let project_config = ProjectConfig {
name: project_name,
base: config_file_project.base,
enabled: true,
schema_extensions: config_file_project.schema_extensions,
output: config_file_project.output,
extra_artifacts_output: config_file_project.extra_artifacts_output,
shard_output: config_file_project.shard_output,
shard_strip_regex,
schema_location,
schema_config: config_file_project.schema_config,
typegen_config: config_file_project.typegen_config,
persist: config_file_project.persist,
variable_names_comment: config_file_project.variable_names_comment,
extra: config_file_project.extra,
test_path_regex,
feature_flags: Arc::new(
config_file_project
.feature_flags
.unwrap_or_else(|| config_file_feature_flags.clone()),
),
filename_for_artifact: None,
skip_types_for_artifact: None,
rollout: config_file_project.rollout,
js_module_format: config_file_project.js_module_format,
};
Ok((project_name, project_config))
})
.collect::<Result<FnvIndexMap<_, _>>>()?;
let config_file_dir = config_path.parent().unwrap();
let root_dir = if let Some(config_root) = config_file.root {
config_file_dir.join(config_root).canonicalize().unwrap()
} else {
config_file_dir.to_owned()
};
let config = Self {
name: config_file.name,
artifact_writer: Box::new(ArtifactFileWriter::new(None, root_dir.clone())),
status_reporter: Box::new(ConsoleStatusReporter::new(root_dir.clone())),
root_dir,
sources: config_file.sources,
excludes: config_file.excludes,
projects,
header: config_file.header,
codegen_command: config_file.codegen_command,
load_saved_state_file: None,
generate_extra_artifacts: None,
generate_virtual_id_file_name: None,
saved_state_config: config_file.saved_state_config,
saved_state_loader: None,
saved_state_version: hex::encode(hash.result()),
create_operation_persister: None,
compile_everything: false,
repersist_operations: false,
post_artifacts_write: None,
additional_validations: None,
is_dev_variable_name: config_file.is_dev_variable_name,
file_source_config: FileSourceKind::Watchman,
custom_transforms: None,
};
let mut validation_errors = Vec::new();
config.validate_consistency(&mut validation_errors);
if validate_fs {
config.validate_paths(&mut validation_errors);
}
if validation_errors.is_empty() {
Ok(config)
} else {
Err(Error::ConfigFileValidation {
config_path,
validation_errors,
})
}
}