Skip to content

Commit 40fe615

Browse files
tobias-tenglerfacebook-github-bot
authored andcommitted
@preloadable Support (#4515)
Summary: This is based on an earlier implementation done by tomgasson in #4110 Companion PR for `types/relay-runtime`: DefinitelyTyped/DefinitelyTyped#68144 An example application using this can be found [here](https://github.com/tobias-tengler/nextjs-relay-entrypoints) Pull Request resolved: #4515 Reviewed By: tyao1 Differential Revision: D52608572 Pulled By: alunyov fbshipit-source-id: d75f904d0f20a89d3542fabf789c6c9d3c8595ce
1 parent 88c40b3 commit 40fe615

18 files changed

+741
-30
lines changed

compiler/crates/relay-bin/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use intern::string_key::Intern;
1818
use log::error;
1919
use log::info;
2020
use relay_compiler::build_project::artifact_writer::ArtifactValidationWriter;
21+
use relay_compiler::build_project::generate_extra_artifacts::default_generate_extra_artifacts_fn;
2122
use relay_compiler::compiler::Compiler;
2223
use relay_compiler::config::Config;
2324
use relay_compiler::errors::Error as CompilerError;
@@ -296,6 +297,8 @@ async fn handle_compiler_command(command: CompileCommand) -> Result<(), Error> {
296297
);
297298
}
298299

300+
config.generate_extra_artifacts = Some(Box::new(default_generate_extra_artifacts_fn));
301+
299302
let compiler = Compiler::new(Arc::new(config), Arc::new(ConsoleLogger));
300303

301304
if command.watch {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,16 @@ pub fn build_request(
158158
}))
159159
}
160160

161+
pub fn build_preloadable_request(
162+
ast_builder: &mut AstBuilder,
163+
request_parameters: AstKey,
164+
) -> AstKey {
165+
ast_builder.intern(Ast::Object(object! {
166+
kind: Primitive::String(CODEGEN_CONSTANTS.preloadable_concrete_request),
167+
params: Primitive::Key(request_parameters),
168+
}))
169+
}
170+
161171
pub fn build_request_params(operation: &OperationDefinition) -> RequestParameters<'_> {
162172
RequestParameters {
163173
name: operation.name.item.0,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ pub struct CodegenConstants {
9191
pub passing_value: StringKey,
9292
pub path: StringKey,
9393
pub plural: StringKey,
94+
pub preloadable_concrete_request: StringKey,
9495
pub provided_variables: StringKey,
9596
pub provider: StringKey,
9697
pub query: StringKey,
@@ -203,6 +204,7 @@ lazy_static! {
203204
passing_value: "passingValue".intern(),
204205
path: "path".intern(),
205206
plural: "plural".intern(),
207+
preloadable_concrete_request: "PreloadableConcreteRequest".intern(),
206208
provided_variables: "providedVariables".intern(),
207209
provider: "provider".intern(),
208210
query: "query".intern(),

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use crate::ast::RequestParameters;
3737
use crate::ast::ResolverModuleReference;
3838
use crate::build_ast::build_fragment;
3939
use crate::build_ast::build_operation;
40+
use crate::build_ast::build_preloadable_request;
4041
use crate::build_ast::build_provided_variables;
4142
use crate::build_ast::build_request;
4243
use crate::build_ast::build_request_params;
@@ -227,6 +228,26 @@ impl<'p> Printer<'p> {
227228
printer.print(key, self.dedupe)
228229
}
229230

231+
pub fn print_preloadable_request(
232+
&mut self,
233+
schema: &SDLSchema,
234+
request_parameters: RequestParameters<'_>,
235+
operation: &OperationDefinition,
236+
top_level_statements: &mut TopLevelStatements,
237+
) -> String {
238+
let request_parameters = build_request_params_ast_key(
239+
schema,
240+
request_parameters,
241+
&mut self.builder,
242+
operation,
243+
operation.name.map(|x| x.0),
244+
self.project_config,
245+
);
246+
let key = build_preloadable_request(&mut self.builder, request_parameters);
247+
let printer = JSONPrinter::new(&self.builder, self.project_config, top_level_statements);
248+
printer.print(key, self.dedupe)
249+
}
250+
230251
pub fn print_operation(
231252
&mut self,
232253
schema: &SDLSchema,

compiler/crates/relay-compiler/src/artifact_content/content.rs

Lines changed: 142 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,115 @@ use super::content_section::GenericSection;
3939
use crate::config::Config;
4040
use crate::config::ProjectConfig;
4141

42+
pub fn generate_preloadable_query_parameters(
43+
config: &Config,
44+
project_config: &ProjectConfig,
45+
printer: &mut Printer<'_>,
46+
schema: &SDLSchema,
47+
normalization_operation: &OperationDefinition,
48+
query_id: &QueryID,
49+
) -> Result<Vec<u8>, FmtError> {
50+
let mut request_parameters = build_request_params(normalization_operation);
51+
let cloned_query_id = Some(query_id.clone());
52+
request_parameters.id = &cloned_query_id;
53+
54+
let mut content_sections = ContentSections::default();
55+
56+
// -- Begin Docblock Section --
57+
let extra_annotations = match query_id {
58+
QueryID::Persisted { text_hash, .. } => vec![format!("@relayHash {}", text_hash)],
59+
_ => vec![],
60+
};
61+
content_sections.push(ContentSection::Docblock(generate_docblock_section(
62+
config,
63+
project_config,
64+
extra_annotations,
65+
)?));
66+
// -- End Docblock Section --
67+
68+
// -- Begin Disable Lint Section --
69+
content_sections.push(ContentSection::Generic(generate_disable_lint_section(
70+
&project_config.typegen_config.language,
71+
)?));
72+
// -- End Disable Lint Section --
73+
74+
// -- Begin Use Strict Section --
75+
content_sections.push(ContentSection::Generic(generate_use_strict_section(
76+
&project_config.typegen_config.language,
77+
)?));
78+
// -- End Use Strict Section --
79+
80+
// -- Begin Metadata Annotations Section --
81+
let mut section = CommentAnnotationsSection::default();
82+
if let Some(QueryID::Persisted { id, .. }) = &request_parameters.id {
83+
writeln!(section, "@relayRequestID {}", id)?;
84+
}
85+
content_sections.push(ContentSection::CommentAnnotations(section));
86+
// -- End Metadata Annotations Section --
87+
88+
// -- Begin Types Section --
89+
let mut section = GenericSection::default();
90+
if project_config.typegen_config.language == TypegenLanguage::Flow {
91+
writeln!(section, "/*::")?;
92+
}
93+
94+
write_import_type_from(
95+
project_config,
96+
&mut section,
97+
"PreloadableConcreteRequest",
98+
"relay-runtime",
99+
)?;
100+
write_import_type_from(
101+
project_config,
102+
&mut section,
103+
&normalization_operation.name.item.0.to_string(),
104+
&format!("./{}.graphql", normalization_operation.name.item.0),
105+
)?;
106+
107+
if project_config.typegen_config.language == TypegenLanguage::Flow {
108+
writeln!(section, "*/")?;
109+
}
110+
content_sections.push(ContentSection::Generic(section));
111+
// -- End Types Section --
112+
113+
// -- Begin Query Node Section --
114+
let preloadable_request = printer.print_preloadable_request(
115+
schema,
116+
request_parameters,
117+
normalization_operation,
118+
&mut Default::default(),
119+
);
120+
let mut section = GenericSection::default();
121+
122+
let node_type = format!(
123+
"PreloadableConcreteRequest<{}>",
124+
normalization_operation.name.item.0
125+
);
126+
127+
write_variable_value_with_type(
128+
&project_config.typegen_config.language,
129+
&mut section,
130+
"node",
131+
&node_type,
132+
&preloadable_request,
133+
)?;
134+
content_sections.push(ContentSection::Generic(section));
135+
// -- End Query Node Section --
136+
137+
// -- Begin Export Section --
138+
let mut section = GenericSection::default();
139+
write_export_generated_node(
140+
&project_config.typegen_config,
141+
&mut section,
142+
"node",
143+
Some(node_type),
144+
)?;
145+
content_sections.push(ContentSection::Generic(section));
146+
// -- End Export Section --
147+
148+
content_sections.into_signed_bytes()
149+
}
150+
42151
#[allow(clippy::too_many_arguments)]
43152
pub fn generate_updatable_query(
44153
config: &Config,
@@ -200,14 +309,14 @@ pub fn generate_operation(
200309
let mut content_sections = ContentSections::default();
201310

202311
// -- Begin Docblock Section --
203-
let v = match id_and_text_hash {
312+
let extra_annotations = match id_and_text_hash {
204313
Some(QueryID::Persisted { text_hash, .. }) => vec![format!("@relayHash {}", text_hash)],
205314
_ => vec![],
206315
};
207316
content_sections.push(ContentSection::Docblock(generate_docblock_section(
208317
config,
209318
project_config,
210-
v,
319+
extra_annotations,
211320
)?));
212321
// -- End Docblock Section --
213322

@@ -328,26 +437,38 @@ pub fn generate_operation(
328437
if is_operation_preloadable(normalization_operation) && id_and_text_hash.is_some() {
329438
match project_config.typegen_config.language {
330439
TypegenLanguage::Flow => {
331-
writeln!(
332-
section,
333-
"require('relay-runtime').PreloadableQueryRegistry.set((node.params/*: any*/).id, node);",
334-
)?;
440+
if project_config.typegen_config.eager_es_modules {
441+
writeln!(
442+
section,
443+
"import {{ PreloadableQueryRegistry }} from 'relay-runtime';",
444+
)?;
445+
writeln!(
446+
section,
447+
"PreloadableQueryRegistry.set((node.params/*: any*/).id, node);",
448+
)?;
449+
} else {
450+
writeln!(
451+
section,
452+
"require('relay-runtime').PreloadableQueryRegistry.set((node.params/*: any*/).id, node);",
453+
)?;
454+
}
335455
}
336-
TypegenLanguage::JavaScript => {
337-
writeln!(
338-
section,
339-
"require('relay-runtime').PreloadableQueryRegistry.set(node.params.id, node);",
340-
)?;
341-
}
342-
TypegenLanguage::TypeScript => {
343-
writeln!(
344-
section,
345-
"import {{ PreloadableQueryRegistry }} from 'relay-runtime';",
346-
)?;
347-
writeln!(
348-
section,
349-
"PreloadableQueryRegistry.set(node.params.id, node);",
350-
)?;
456+
TypegenLanguage::JavaScript | TypegenLanguage::TypeScript => {
457+
if project_config.typegen_config.eager_es_modules {
458+
writeln!(
459+
section,
460+
"import {{ PreloadableQueryRegistry }} from 'relay-runtime';",
461+
)?;
462+
writeln!(
463+
section,
464+
"PreloadableQueryRegistry.set(node.params.id, node);",
465+
)?;
466+
} else {
467+
writeln!(
468+
section,
469+
"require('relay-runtime').PreloadableQueryRegistry.set(node.params.id, node);",
470+
)?;
471+
}
351472
}
352473
}
353474
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use relay_codegen::QueryID;
2323
use relay_typegen::FragmentLocations;
2424
use schema::SDLSchema;
2525

26+
use self::content::generate_preloadable_query_parameters;
2627
use crate::config::Config;
2728
use crate::config::ProjectConfig;
2829

@@ -41,6 +42,10 @@ pub enum ArtifactContent {
4142
typegen_operation: Arc<OperationDefinition>,
4243
source_hash: String,
4344
},
45+
PreloadableQueryParameters {
46+
normalization_operation: Arc<OperationDefinition>,
47+
query_id: QueryID,
48+
},
4449
Fragment {
4550
reader_fragment: Arc<FragmentDefinition>,
4651
typegen_fragment: Arc<FragmentDefinition>,
@@ -113,6 +118,18 @@ impl ArtifactContent {
113118
fragment_locations,
114119
)
115120
.unwrap(),
121+
ArtifactContent::PreloadableQueryParameters {
122+
normalization_operation,
123+
query_id,
124+
} => generate_preloadable_query_parameters(
125+
config,
126+
project_config,
127+
printer,
128+
schema,
129+
normalization_operation,
130+
query_id,
131+
)
132+
.unwrap(),
116133
ArtifactContent::SplitOperation {
117134
normalization_operation,
118135
typegen_operation,

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use graphql_text_printer::OperationPrinter;
1717
use graphql_text_printer::PrinterOptions;
1818
use intern::string_key::StringKey;
1919
use intern::Lookup;
20+
use relay_codegen::QueryID;
2021
use relay_config::ResolversSchemaModuleConfig;
2122
use relay_transforms::ArtifactSourceKeyData;
2223
use relay_transforms::ClientEdgeGeneratedQueryMetadataDirective;
@@ -228,6 +229,30 @@ fn generate_normalization_artifact(
228229
}
229230
}
230231

232+
pub fn generate_preloadable_query_parameters_artifact(
233+
project_config: &ProjectConfig,
234+
normalization: &Arc<OperationDefinition>,
235+
id_and_text_hash: &Option<QueryID>,
236+
source_keys: Vec<ArtifactSourceKey>,
237+
source_file: SourceLocationKey,
238+
) -> Artifact {
239+
let query_id = id_and_text_hash
240+
.clone()
241+
.expect("Expected operation artifact to have an `id`. Ensure a `persistConfig` is setup for the current project.");
242+
243+
let artifact_name = normalization.name.item.0.to_string() + "$parameters";
244+
245+
Artifact {
246+
artifact_source_keys: source_keys,
247+
path: project_config.path_for_language_specific_artifact(source_file, artifact_name),
248+
content: ArtifactContent::PreloadableQueryParameters {
249+
normalization_operation: Arc::clone(normalization),
250+
query_id,
251+
},
252+
source_file,
253+
}
254+
}
255+
231256
fn generate_updatable_query_artifact(
232257
artifact_source: ArtifactSourceKey,
233258
project_config: &ProjectConfig,

0 commit comments

Comments
 (0)