Skip to content

Commit cf30bf4

Browse files
voideanvaluefacebook-github-bot
authored andcommitted
upstream resolvers_schema_module from fb-relay-compiler
Reviewed By: alunyov Differential Revision: D51596083 fbshipit-source-id: 0da1e2e1a6b786583872abc1b92776c33219fe00
1 parent e16e911 commit cf30bf4

File tree

15 files changed

+492
-17
lines changed

15 files changed

+492
-17
lines changed

compiler/crates/common/src/feature_flags.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ pub struct FeatureFlags {
6969
#[serde(default)]
7070
pub enable_resolver_normalization_ast: bool,
7171

72-
/// Fully build the schema resolvers artifact
73-
#[serde(default)]
74-
pub generate_resolvers_schema_module: bool,
75-
7672
/// Enforce strict flavors for relay resolvers and disallow mixing flavors
7773
#[serde(default)]
7874
pub relay_resolvers_enable_strict_resolver_flavors: FeatureFlag,

compiler/crates/relay-codegen/src/build_ast.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -651,11 +651,7 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {
651651
resolver_metadata: &RelayResolverMetadata,
652652
inline_fragment: Option<Primitive>,
653653
) -> Primitive {
654-
if self
655-
.project_config
656-
.feature_flags
657-
.generate_resolvers_schema_module
658-
{
654+
if self.project_config.resolvers_schema_module.is_some() {
659655
self.build_normalization_relay_resolver_execution_time_for_worker(resolver_metadata)
660656
} else if self
661657
.project_config

compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@ use graphql_text_printer::OperationPrinter;
1717
use graphql_text_printer::PrinterOptions;
1818
use intern::string_key::StringKey;
1919
use intern::Lookup;
20+
use relay_config::ResolversSchemaModuleConfig;
2021
use relay_transforms::ArtifactSourceKeyData;
2122
use relay_transforms::ClientEdgeGeneratedQueryMetadataDirective;
2223
use relay_transforms::Programs;
2324
use relay_transforms::RawResponseGenerationMode;
2425
use relay_transforms::RefetchableDerivedFromMetadata;
2526
use relay_transforms::SplitOperationMetadata;
2627
use relay_transforms::UPDATABLE_DIRECTIVE;
28+
use schema::SDLSchema;
2729

2830
pub use super::artifact_content::ArtifactContent;
2931
use super::build_ir::SourceHashes;
32+
use super::resolvers_schema_module::generate_resolvers_schema_module;
3033
use crate::artifact_map::ArtifactSourceKey;
3134
use crate::config::Config;
3235
use crate::config::ProjectConfig;
@@ -44,8 +47,9 @@ pub struct Artifact {
4447
}
4548

4649
pub fn generate_artifacts(
47-
_config: &Config,
50+
config: &Config,
4851
project_config: &ProjectConfig,
52+
schema: &SDLSchema,
4953
programs: &Programs,
5054
source_hashes: Arc<SourceHashes>,
5155
) -> Vec<Artifact> {
@@ -187,6 +191,15 @@ pub fn generate_artifacts(
187191
artifact_source_keys,
188192
)
189193
}))
194+
.chain(
195+
match project_config.resolvers_schema_module {
196+
Some(ResolversSchemaModuleConfig { ref path }) =>
197+
vec![
198+
generate_resolvers_schema_module(config, project_config, schema, path.clone()).unwrap()
199+
],
200+
_ => vec![],
201+
}
202+
)
190203
.collect();
191204
}
192205

compiler/crates/relay-compiler/src/build_project/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod get_artifacts_file_hash_map;
1919
mod log_program_stats;
2020
mod persist_operations;
2121
mod project_asts;
22+
mod resolvers_schema_module;
2223
mod source_control;
2324
mod validate;
2425

@@ -291,6 +292,7 @@ pub fn build_project(
291292
let artifacts = generate_artifacts(
292293
config,
293294
project_config,
295+
&schema,
294296
&programs,
295297
Arc::clone(&source_hashes),
296298
);
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#![warn(clippy::all)]
9+
10+
use std::fmt::Error;
11+
use std::fmt::Write;
12+
use std::path::PathBuf;
13+
14+
use common::NamedItem;
15+
use common::SourceLocationKey;
16+
use intern::Lookup;
17+
use relay_codegen::printer::get_module_path;
18+
use relay_transforms::generate_relay_resolvers_model_fragments::get_resolver_source_hash;
19+
use relay_transforms::get_fragment_filename;
20+
use relay_transforms::get_resolver_fragment_dependency_name;
21+
use relay_transforms::relay_resolvers::get_resolver_info;
22+
use relay_transforms::relay_resolvers::ResolverInfo;
23+
use relay_transforms::RESOLVER_BELONGS_TO_BASE_SCHEMA_DIRECTIVE;
24+
use relay_typegen::TypegenLanguage;
25+
use schema::SDLSchema;
26+
use schema::Schema;
27+
use schema::Type;
28+
use signedsource::sign_file;
29+
30+
use super::artifact_content::content::generate_docblock_section;
31+
use super::artifact_content::content::write_export_generated_node;
32+
use super::artifact_content::content_section::GenericSection;
33+
use crate::config::Config;
34+
use crate::config::ProjectConfig;
35+
use crate::Artifact;
36+
use crate::ArtifactContent;
37+
use crate::ArtifactSourceKey;
38+
39+
pub fn generate_resolvers_schema_module(
40+
config: &Config,
41+
project_config: &ProjectConfig,
42+
schema: &SDLSchema,
43+
output_path: PathBuf,
44+
) -> Result<Artifact, Error> {
45+
let mut artifact_source_keys = vec![];
46+
let content = generate_resolvers_schema_module_content(
47+
config,
48+
project_config,
49+
schema,
50+
&output_path,
51+
&mut artifact_source_keys,
52+
)?;
53+
Ok(Artifact {
54+
artifact_source_keys,
55+
path: output_path,
56+
content: ArtifactContent::Generic {
57+
content: sign_file(&content).into_bytes(),
58+
},
59+
source_file: SourceLocationKey::generated(),
60+
})
61+
}
62+
63+
fn generate_resolvers_schema_module_content(
64+
config: &Config,
65+
project_config: &ProjectConfig,
66+
schema: &SDLSchema,
67+
artifact_path: &PathBuf,
68+
artifact_source_keys: &mut Vec<ArtifactSourceKey>,
69+
) -> Result<String, Error> {
70+
let mut content = String::new();
71+
72+
let docblock = generate_docblock_section(config, project_config, vec![])?;
73+
writeln!(content, "{}", docblock)?;
74+
75+
let mut schema_resolvers_object = String::new();
76+
let mut schema_resolvers_type = String::new();
77+
let mut imports = String::new();
78+
79+
writeln!(schema_resolvers_type, "type SchemaResolvers = {{")?;
80+
if project_config.typegen_config.language == TypegenLanguage::Flow {
81+
writeln!(
82+
schema_resolvers_object,
83+
"var schema_resolvers /*:: : SchemaResolvers*/ = {{"
84+
)?;
85+
} else {
86+
writeln!(
87+
schema_resolvers_object,
88+
"const schema_resolvers: SchemaResolvers = {{"
89+
)?;
90+
}
91+
writeln!(
92+
imports,
93+
"import type {{NormalizationSplitOperation}} from 'relay-runtime';"
94+
)?;
95+
96+
for object in schema.get_objects() {
97+
let mut has_resolvers = false;
98+
99+
for field in object.fields.iter().map(|field_id| schema.field(*field_id)) {
100+
if let Some(Ok(ResolverInfo {
101+
import_path,
102+
import_name: Some(import_name),
103+
..
104+
})) = get_resolver_info(schema, field, field.name.location)
105+
{
106+
if field
107+
.directives
108+
.named(*RESOLVER_BELONGS_TO_BASE_SCHEMA_DIRECTIVE)
109+
.is_some()
110+
{
111+
continue;
112+
}
113+
114+
if !has_resolvers {
115+
has_resolvers = true;
116+
writeln!(
117+
schema_resolvers_type,
118+
"\t{object_name}: {{",
119+
object_name = object.name.item
120+
)?;
121+
writeln!(
122+
schema_resolvers_object,
123+
"\t{object_name}: {{",
124+
object_name = object.name.item
125+
)?;
126+
}
127+
if let Some(source_hash) = get_resolver_source_hash(field) {
128+
artifact_source_keys.push(ArtifactSourceKey::ResolverHash(source_hash));
129+
}
130+
131+
let js_import_path = project_config.js_module_import_identifier(
132+
artifact_path,
133+
&PathBuf::from(import_path.lookup()),
134+
);
135+
let js_import_path_without_suffix =
136+
get_module_path(project_config.js_module_format, js_import_path);
137+
138+
let parent_type = match field.parent_type.unwrap() {
139+
Type::Interface(interface_id) => schema.interface(interface_id).name.item.0,
140+
Type::Object(object_id) => schema.object(object_id).name.item.0,
141+
_ => panic!("Unexpected parent type for resolver."),
142+
};
143+
let type_name = format!("{}_{}", &parent_type, import_name);
144+
145+
writeln!(
146+
imports,
147+
"import typeof {{ {import_name} as {type_name} }} from '{import_path}';",
148+
import_path = js_import_path_without_suffix,
149+
import_name = import_name,
150+
type_name = type_name
151+
)?;
152+
153+
writeln!(schema_resolvers_type, "\t\t{}: {{", import_name)?;
154+
writeln!(
155+
schema_resolvers_type,
156+
"\t\t\tresolverFunction: {},",
157+
type_name
158+
)?;
159+
writeln!(
160+
schema_resolvers_type,
161+
"\t\t\trootFragment: ?NormalizationSplitOperation,"
162+
)?;
163+
writeln!(schema_resolvers_type, "\t\t}},",)?;
164+
165+
writeln!(schema_resolvers_object, "\t\t{}: {{", import_name)?;
166+
writeln!(
167+
schema_resolvers_object,
168+
"\t\t\tresolverFunction: require('{import_path}').{import_name},",
169+
import_path = js_import_path_without_suffix,
170+
import_name = import_name
171+
)?;
172+
writeln!(
173+
schema_resolvers_object,
174+
"\t\t\trootFragment: {}",
175+
match get_resolver_fragment_dependency_name(field) {
176+
None => "null".to_string(),
177+
Some(fragment_name) => {
178+
format!(
179+
"require('{import}')",
180+
import = get_fragment_filename(fragment_name)
181+
)
182+
}
183+
}
184+
)?;
185+
writeln!(schema_resolvers_object, "\t\t}},",)?;
186+
}
187+
}
188+
189+
if has_resolvers {
190+
writeln!(schema_resolvers_type, "\t}},")?;
191+
writeln!(schema_resolvers_object, "\t}},")?;
192+
}
193+
}
194+
195+
writeln!(schema_resolvers_type, "}};")?;
196+
writeln!(schema_resolvers_object, "}};")?;
197+
198+
if project_config.typegen_config.language == TypegenLanguage::Flow {
199+
writeln!(content, "/*::")?;
200+
}
201+
writeln!(content, "{}\n", imports)?;
202+
writeln!(content, "{}\n", schema_resolvers_type)?;
203+
if project_config.typegen_config.language == TypegenLanguage::Flow {
204+
writeln!(content, "*/")?;
205+
}
206+
writeln!(content, "{}\n", schema_resolvers_object)?;
207+
208+
let mut export = GenericSection::default();
209+
write_export_generated_node(
210+
&project_config.typegen_config,
211+
&mut export,
212+
"schema_resolvers",
213+
None,
214+
)?;
215+
writeln!(content, "{}", export)?;
216+
217+
Ok(content)
218+
}

compiler/crates/relay-compiler/src/config.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub use relay_config::PersistConfig;
3939
pub use relay_config::ProjectConfig;
4040
use relay_config::ProjectName;
4141
pub use relay_config::RemotePersistConfig;
42+
use relay_config::ResolversSchemaModuleConfig;
4243
use relay_config::SchemaConfig;
4344
pub use relay_config::SchemaLocation;
4445
use relay_config::TypegenConfig;
@@ -377,6 +378,7 @@ Example file:
377378
js_module_format: config_file_project.js_module_format,
378379
module_import_config: config_file_project.module_import_config,
379380
diagnostic_report_config: config_file_project.diagnostic_report_config,
381+
resolvers_schema_module: config_file_project.resolvers_schema_module,
380382
};
381383
Ok((project_name, project_config))
382384
})
@@ -740,6 +742,9 @@ pub struct SingleProjectConfigFile {
740742
/// of an union with the raw type, null and undefined.
741743
#[serde(default)]
742744
pub typescript_exclude_undefined_from_nullable_union: bool,
745+
746+
#[serde(default)]
747+
pub resolvers_schema_module: Option<ResolversSchemaModuleConfig>,
743748
}
744749

745750
impl Default for SingleProjectConfigFile {
@@ -766,6 +771,7 @@ impl Default for SingleProjectConfigFile {
766771
feature_flags: None,
767772
typescript_exclude_undefined_from_nullable_union: false,
768773
module_import_config: Default::default(),
774+
resolvers_schema_module: Default::default(),
769775
}
770776
}
771777
}
@@ -893,6 +899,7 @@ impl SingleProjectConfigFile {
893899
js_module_format: self.js_module_format,
894900
feature_flags: self.feature_flags,
895901
module_import_config: self.module_import_config,
902+
resolvers_schema_module: self.resolvers_schema_module,
896903
..Default::default()
897904
};
898905

@@ -1033,6 +1040,9 @@ pub struct ConfigFileProject {
10331040

10341041
#[serde(default)]
10351042
pub diagnostic_report_config: DiagnosticReportConfig,
1043+
1044+
#[serde(default)]
1045+
pub resolvers_schema_module: Option<ResolversSchemaModuleConfig>,
10361046
}
10371047

10381048
pub type PersistId = String;

compiler/crates/relay-compiler/tests/compile_relay_artifacts/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String>
118118
enable_resolver_normalization_ast: fixture
119119
.content
120120
.contains("# enable_resolver_normalization_ast"),
121-
generate_resolvers_schema_module: false,
122121
relay_resolvers_enable_strict_resolver_flavors: FeatureFlag::Disabled,
123122
relay_resolvers_allow_legacy_verbose_syntax: FeatureFlag::Disabled,
124123
enable_relay_resolver_mutations: false,

compiler/crates/relay-compiler/tests/compile_relay_artifacts_with_custom_id/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String>
9797
relay_resolver_enable_output_type: FeatureFlag::Disabled,
9898
relay_resolver_enable_interface_output_type: FeatureFlag::Disabled,
9999
enable_resolver_normalization_ast: false,
100-
generate_resolvers_schema_module: false,
101100
relay_resolvers_enable_strict_resolver_flavors: FeatureFlag::Disabled,
102101
relay_resolvers_allow_legacy_verbose_syntax: FeatureFlag::Disabled,
103102
enable_relay_resolver_mutations: false,

0 commit comments

Comments
 (0)