Skip to content

Commit

Permalink
@preloadable Support (#4515)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tobias-tengler authored and facebook-github-bot committed Jan 9, 2024
1 parent 88c40b3 commit 40fe615
Show file tree
Hide file tree
Showing 18 changed files with 741 additions and 30 deletions.
3 changes: 3 additions & 0 deletions compiler/crates/relay-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use intern::string_key::Intern;
use log::error;
use log::info;
use relay_compiler::build_project::artifact_writer::ArtifactValidationWriter;
use relay_compiler::build_project::generate_extra_artifacts::default_generate_extra_artifacts_fn;
use relay_compiler::compiler::Compiler;
use relay_compiler::config::Config;
use relay_compiler::errors::Error as CompilerError;
Expand Down Expand Up @@ -296,6 +297,8 @@ async fn handle_compiler_command(command: CompileCommand) -> Result<(), Error> {
);
}

config.generate_extra_artifacts = Some(Box::new(default_generate_extra_artifacts_fn));

let compiler = Compiler::new(Arc::new(config), Arc::new(ConsoleLogger));

if command.watch {
Expand Down
10 changes: 10 additions & 0 deletions compiler/crates/relay-codegen/src/build_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ pub fn build_request(
}))
}

pub fn build_preloadable_request(
ast_builder: &mut AstBuilder,
request_parameters: AstKey,
) -> AstKey {
ast_builder.intern(Ast::Object(object! {
kind: Primitive::String(CODEGEN_CONSTANTS.preloadable_concrete_request),
params: Primitive::Key(request_parameters),
}))
}

pub fn build_request_params(operation: &OperationDefinition) -> RequestParameters<'_> {
RequestParameters {
name: operation.name.item.0,
Expand Down
2 changes: 2 additions & 0 deletions compiler/crates/relay-codegen/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub struct CodegenConstants {
pub passing_value: StringKey,
pub path: StringKey,
pub plural: StringKey,
pub preloadable_concrete_request: StringKey,
pub provided_variables: StringKey,
pub provider: StringKey,
pub query: StringKey,
Expand Down Expand Up @@ -203,6 +204,7 @@ lazy_static! {
passing_value: "passingValue".intern(),
path: "path".intern(),
plural: "plural".intern(),
preloadable_concrete_request: "PreloadableConcreteRequest".intern(),
provided_variables: "providedVariables".intern(),
provider: "provider".intern(),
query: "query".intern(),
Expand Down
21 changes: 21 additions & 0 deletions compiler/crates/relay-codegen/src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use crate::ast::RequestParameters;
use crate::ast::ResolverModuleReference;
use crate::build_ast::build_fragment;
use crate::build_ast::build_operation;
use crate::build_ast::build_preloadable_request;
use crate::build_ast::build_provided_variables;
use crate::build_ast::build_request;
use crate::build_ast::build_request_params;
Expand Down Expand Up @@ -227,6 +228,26 @@ impl<'p> Printer<'p> {
printer.print(key, self.dedupe)
}

pub fn print_preloadable_request(
&mut self,
schema: &SDLSchema,
request_parameters: RequestParameters<'_>,
operation: &OperationDefinition,
top_level_statements: &mut TopLevelStatements,
) -> String {
let request_parameters = build_request_params_ast_key(
schema,
request_parameters,
&mut self.builder,
operation,
operation.name.map(|x| x.0),
self.project_config,
);
let key = build_preloadable_request(&mut self.builder, request_parameters);
let printer = JSONPrinter::new(&self.builder, self.project_config, top_level_statements);
printer.print(key, self.dedupe)
}

pub fn print_operation(
&mut self,
schema: &SDLSchema,
Expand Down
163 changes: 142 additions & 21 deletions compiler/crates/relay-compiler/src/artifact_content/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,115 @@ use super::content_section::GenericSection;
use crate::config::Config;
use crate::config::ProjectConfig;

pub fn generate_preloadable_query_parameters(
config: &Config,
project_config: &ProjectConfig,
printer: &mut Printer<'_>,
schema: &SDLSchema,
normalization_operation: &OperationDefinition,
query_id: &QueryID,
) -> Result<Vec<u8>, FmtError> {
let mut request_parameters = build_request_params(normalization_operation);
let cloned_query_id = Some(query_id.clone());
request_parameters.id = &cloned_query_id;

let mut content_sections = ContentSections::default();

// -- Begin Docblock Section --
let extra_annotations = match query_id {
QueryID::Persisted { text_hash, .. } => vec![format!("@relayHash {}", text_hash)],
_ => vec![],
};
content_sections.push(ContentSection::Docblock(generate_docblock_section(
config,
project_config,
extra_annotations,
)?));
// -- End Docblock Section --

// -- Begin Disable Lint Section --
content_sections.push(ContentSection::Generic(generate_disable_lint_section(
&project_config.typegen_config.language,
)?));
// -- End Disable Lint Section --

// -- Begin Use Strict Section --
content_sections.push(ContentSection::Generic(generate_use_strict_section(
&project_config.typegen_config.language,
)?));
// -- End Use Strict Section --

// -- Begin Metadata Annotations Section --
let mut section = CommentAnnotationsSection::default();
if let Some(QueryID::Persisted { id, .. }) = &request_parameters.id {
writeln!(section, "@relayRequestID {}", id)?;
}
content_sections.push(ContentSection::CommentAnnotations(section));
// -- End Metadata Annotations Section --

// -- Begin Types Section --
let mut section = GenericSection::default();
if project_config.typegen_config.language == TypegenLanguage::Flow {
writeln!(section, "/*::")?;
}

write_import_type_from(
project_config,
&mut section,
"PreloadableConcreteRequest",
"relay-runtime",
)?;
write_import_type_from(
project_config,
&mut section,
&normalization_operation.name.item.0.to_string(),
&format!("./{}.graphql", normalization_operation.name.item.0),
)?;

if project_config.typegen_config.language == TypegenLanguage::Flow {
writeln!(section, "*/")?;
}
content_sections.push(ContentSection::Generic(section));
// -- End Types Section --

// -- Begin Query Node Section --
let preloadable_request = printer.print_preloadable_request(
schema,
request_parameters,
normalization_operation,
&mut Default::default(),
);
let mut section = GenericSection::default();

let node_type = format!(
"PreloadableConcreteRequest<{}>",
normalization_operation.name.item.0
);

write_variable_value_with_type(
&project_config.typegen_config.language,
&mut section,
"node",
&node_type,
&preloadable_request,
)?;
content_sections.push(ContentSection::Generic(section));
// -- End Query Node Section --

// -- Begin Export Section --
let mut section = GenericSection::default();
write_export_generated_node(
&project_config.typegen_config,
&mut section,
"node",
Some(node_type),
)?;
content_sections.push(ContentSection::Generic(section));
// -- End Export Section --

content_sections.into_signed_bytes()
}

#[allow(clippy::too_many_arguments)]
pub fn generate_updatable_query(
config: &Config,
Expand Down Expand Up @@ -200,14 +309,14 @@ pub fn generate_operation(
let mut content_sections = ContentSections::default();

// -- Begin Docblock Section --
let v = match id_and_text_hash {
let extra_annotations = match id_and_text_hash {
Some(QueryID::Persisted { text_hash, .. }) => vec![format!("@relayHash {}", text_hash)],
_ => vec![],
};
content_sections.push(ContentSection::Docblock(generate_docblock_section(
config,
project_config,
v,
extra_annotations,
)?));
// -- End Docblock Section --

Expand Down Expand Up @@ -328,26 +437,38 @@ pub fn generate_operation(
if is_operation_preloadable(normalization_operation) && id_and_text_hash.is_some() {
match project_config.typegen_config.language {
TypegenLanguage::Flow => {
writeln!(
section,
"require('relay-runtime').PreloadableQueryRegistry.set((node.params/*: any*/).id, node);",
)?;
if project_config.typegen_config.eager_es_modules {
writeln!(
section,
"import {{ PreloadableQueryRegistry }} from 'relay-runtime';",
)?;
writeln!(
section,
"PreloadableQueryRegistry.set((node.params/*: any*/).id, node);",
)?;
} else {
writeln!(
section,
"require('relay-runtime').PreloadableQueryRegistry.set((node.params/*: any*/).id, node);",
)?;
}
}
TypegenLanguage::JavaScript => {
writeln!(
section,
"require('relay-runtime').PreloadableQueryRegistry.set(node.params.id, node);",
)?;
}
TypegenLanguage::TypeScript => {
writeln!(
section,
"import {{ PreloadableQueryRegistry }} from 'relay-runtime';",
)?;
writeln!(
section,
"PreloadableQueryRegistry.set(node.params.id, node);",
)?;
TypegenLanguage::JavaScript | TypegenLanguage::TypeScript => {
if project_config.typegen_config.eager_es_modules {
writeln!(
section,
"import {{ PreloadableQueryRegistry }} from 'relay-runtime';",
)?;
writeln!(
section,
"PreloadableQueryRegistry.set(node.params.id, node);",
)?;
} else {
writeln!(
section,
"require('relay-runtime').PreloadableQueryRegistry.set(node.params.id, node);",
)?;
}
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions compiler/crates/relay-compiler/src/artifact_content/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use relay_codegen::QueryID;
use relay_typegen::FragmentLocations;
use schema::SDLSchema;

use self::content::generate_preloadable_query_parameters;
use crate::config::Config;
use crate::config::ProjectConfig;

Expand All @@ -41,6 +42,10 @@ pub enum ArtifactContent {
typegen_operation: Arc<OperationDefinition>,
source_hash: String,
},
PreloadableQueryParameters {
normalization_operation: Arc<OperationDefinition>,
query_id: QueryID,
},
Fragment {
reader_fragment: Arc<FragmentDefinition>,
typegen_fragment: Arc<FragmentDefinition>,
Expand Down Expand Up @@ -113,6 +118,18 @@ impl ArtifactContent {
fragment_locations,
)
.unwrap(),
ArtifactContent::PreloadableQueryParameters {
normalization_operation,
query_id,
} => generate_preloadable_query_parameters(
config,
project_config,
printer,
schema,
normalization_operation,
query_id,
)
.unwrap(),
ArtifactContent::SplitOperation {
normalization_operation,
typegen_operation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use graphql_text_printer::OperationPrinter;
use graphql_text_printer::PrinterOptions;
use intern::string_key::StringKey;
use intern::Lookup;
use relay_codegen::QueryID;
use relay_config::ResolversSchemaModuleConfig;
use relay_transforms::ArtifactSourceKeyData;
use relay_transforms::ClientEdgeGeneratedQueryMetadataDirective;
Expand Down Expand Up @@ -228,6 +229,30 @@ fn generate_normalization_artifact(
}
}

pub fn generate_preloadable_query_parameters_artifact(
project_config: &ProjectConfig,
normalization: &Arc<OperationDefinition>,
id_and_text_hash: &Option<QueryID>,
source_keys: Vec<ArtifactSourceKey>,
source_file: SourceLocationKey,
) -> Artifact {
let query_id = id_and_text_hash
.clone()
.expect("Expected operation artifact to have an `id`. Ensure a `persistConfig` is setup for the current project.");

let artifact_name = normalization.name.item.0.to_string() + "$parameters";

Artifact {
artifact_source_keys: source_keys,
path: project_config.path_for_language_specific_artifact(source_file, artifact_name),
content: ArtifactContent::PreloadableQueryParameters {
normalization_operation: Arc::clone(normalization),
query_id,
},
source_file,
}
}

fn generate_updatable_query_artifact(
artifact_source: ArtifactSourceKey,
project_config: &ProjectConfig,
Expand Down

0 comments on commit 40fe615

Please sign in to comment.