Skip to content

Commit

Permalink
runtime: refactor two printer logics into one
Browse files Browse the repository at this point in the history
  • Loading branch information
uhyo committed Dec 26, 2023
1 parent 85955a4 commit 0467702
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 92 deletions.
3 changes: 3 additions & 0 deletions crates/printer/src/operation_js_printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ use crate::{operation_base_printer::OperationPrinter, OperationJSPrinterOptions}
use self::visitor::OperationJSPrinterVisitor;

pub mod options;
mod printers;
mod tests;
pub mod visitor;

pub use printers::{print_fragment_runtime, print_operation_runtime};

/// Print a JavaScript module for given operation document.
pub fn print_js_for_operation_document(
options: OperationJSPrinterOptions,
Expand Down
59 changes: 59 additions & 0 deletions crates/printer/src/operation_js_printer/printers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::collections::HashMap;

use crate::{
json_printer::{print_to_json_string, ExecutableDefinitionRef},
utils::fragment_names_in_selection_set,
};
use nitrogql_ast::operation::{FragmentDefinition, OperationDefinition};
use sourcemap_writer::SourceMapWriter;

/// Print the runtime value of given operation.
pub fn print_operation_runtime(
writer: &mut impl SourceMapWriter,
operation: &OperationDefinition,
fragments: &HashMap<&str, &FragmentDefinition>,
) {
let fragments_to_include = fragment_names_in_selection_set(&operation.selection_set, |name| {
fragments.get(name).copied()
})
.into_iter()
.map(|name| {
ExecutableDefinitionRef::FragmentDefinition(
fragments.get(name).expect("fragment not found"),
)
});
let this_document = vec![ExecutableDefinitionRef::OperationDefinition(operation)]
.into_iter()
.chain(fragments_to_include)
.collect::<Vec<_>>();
writer.write(&print_to_json_string(&this_document[..]));
}

/// Print the runtime value of given fragment.
pub fn print_fragment_runtime(
writer: &mut impl SourceMapWriter,
fragment: &FragmentDefinition,
fragments: &HashMap<&str, &FragmentDefinition>,
) {
let fragments_to_include = fragment_names_in_selection_set(&fragment.selection_set, |name| {
fragments.get(name).copied()
})
.into_iter()
.filter(|f| {
// Filter out the fragment we are currently processing
*f != fragment.name.name
})
.map(|name| {
ExecutableDefinitionRef::FragmentDefinition(
fragments.get(name).expect("fragment not found"),
)
});
// Generated document is the collection of all relevant fragments,
// and the fragment we are currently processing
// comes first in the list
let this_document = vec![ExecutableDefinitionRef::FragmentDefinition(fragment)]
.into_iter()
.chain(fragments_to_include)
.collect::<Vec<_>>();
writer.write(&print_to_json_string(&this_document[..]));
}
54 changes: 6 additions & 48 deletions crates/printer/src/operation_js_printer/visitor.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use sourcemap_writer::SourceMapWriter;

use crate::{
json_printer::{print_to_json_string, ExecutableDefinitionRef},
operation_base_printer::{
OperationPrinterVisitor, PrintFragmentContext, PrintOperationContext,
},
utils::fragment_names_in_selection_set,
use crate::operation_base_printer::{
OperationPrinterVisitor, PrintFragmentContext, PrintOperationContext,
};

use super::printers::{print_fragment_runtime, print_operation_runtime};

pub struct OperationJSPrinterVisitor {}

impl OperationJSPrinterVisitor {
Expand All @@ -34,24 +32,7 @@ impl OperationPrinterVisitor for OperationJSPrinterVisitor {
&operation.name_pos(),
);
writer.write(" = ");
let fragments_to_include =
fragment_names_in_selection_set(&operation.selection_set, |name| {
context.fragments.get(name).copied()
})
.into_iter()
.map(|name| {
ExecutableDefinitionRef::FragmentDefinition(
context.fragments.get(name).expect("fragment not found"),
)
});
// To follow the community conventions, generated JSON has only one operation in it
let this_document = vec![ExecutableDefinitionRef::OperationDefinition(
context.operation,
)]
.into_iter()
.chain(fragments_to_include)
.collect::<Vec<_>>();
writer.write(&print_to_json_string(&this_document[..]));
print_operation_runtime(writer, operation, context.fragments);
writer.write(";\n\n");
}

Expand All @@ -69,30 +50,7 @@ impl OperationPrinterVisitor for OperationJSPrinterVisitor {

writer.write_for(context.var_name, fragment);
writer.write(" = ");

let fragments_to_include =
fragment_names_in_selection_set(&fragment.selection_set, |name| {
context.fragments.get(name).copied()
})
.into_iter()
.filter(|f| {
// Filter out the fragment we are currently processing
*f != fragment.name.name
})
.map(|name| {
ExecutableDefinitionRef::FragmentDefinition(
context.fragments.get(name).expect("fragment not found"),
)
});

// Generated document is the collection of all relevant fragments,
// and the fragment we are currently processing
// comes first in the list
let this_document = vec![ExecutableDefinitionRef::FragmentDefinition(fragment)]
.into_iter()
.chain(fragments_to_include)
.collect::<Vec<_>>();
writer.write(&print_to_json_string(&this_document[..]));
print_fragment_runtime(writer, fragment, context.fragments);
writer.write(";\n\n");
}
fn print_default_exported_operation_definition(
Expand Down
47 changes: 3 additions & 44 deletions crates/printer/src/operation_type_printer/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ use nitrogql_utils::clone_into;
use sourcemap_writer::SourceMapWriter;

use crate::{
json_printer::{print_to_json_string, ExecutableDefinitionRef},
operation_base_printer::{
options::OperationBasePrinterOptions, OperationPrinterVisitor, PrintFragmentContext,
PrintOperationContext,
},
operation_js_printer::{print_fragment_runtime, print_operation_runtime},
ts_types::TSType,
utils::fragment_names_in_selection_set,
};

use super::type_printer::{
Expand Down Expand Up @@ -215,24 +214,7 @@ impl<'a, 'src> OperationPrinterVisitor for OperationTypePrinterVisitor<'a, 'src>
return;
}
writer.write("> = ");
let fragments_to_include =
fragment_names_in_selection_set(&operation.selection_set, |name| {
context.fragments.get(name).copied()
})
.into_iter()
.map(|name| {
ExecutableDefinitionRef::FragmentDefinition(
context.fragments.get(name).expect("fragment not found"),
)
});
// To follow the community conventions, generated JSON has only one operation in it
let this_document = vec![ExecutableDefinitionRef::OperationDefinition(
context.operation,
)]
.into_iter()
.chain(fragments_to_include)
.collect::<Vec<_>>();
writer.write(&print_to_json_string(&this_document[..]));
print_operation_runtime(writer, operation, context.fragments);
// Use the `as unknown as` technique to avoid the type system complaining about
// the type of the JSON object not matching the type of the TypedDocumentNode
// (because of the use of enums in the TypedDocumentNode type)
Expand Down Expand Up @@ -306,30 +288,7 @@ impl<'a, 'src> OperationPrinterVisitor for OperationTypePrinterVisitor<'a, 'src>
return;
}
writer.write(" = ");

let fragments_to_include =
fragment_names_in_selection_set(&fragment.selection_set, |name| {
context.fragments.get(name).copied()
})
.into_iter()
.filter(|f| {
// Filter out the fragment we are currently processing
*f != fragment.name.name
})
.map(|name| {
ExecutableDefinitionRef::FragmentDefinition(
context.fragments.get(name).expect("fragment not found"),
)
});

// Generated document is the collection of all relevant fragments,
// and the fragment we are currently processing
// comes first in the list
let this_document = vec![ExecutableDefinitionRef::FragmentDefinition(fragment)]
.into_iter()
.chain(fragments_to_include)
.collect::<Vec<_>>();
writer.write(&print_to_json_string(&this_document[..]));
print_fragment_runtime(writer, fragment, context.fragments);
writer.write(" as unknown as TypedDocumentNode<");
writer.write_for(&fragment_type_name, fragment);
writer.write(", never>;\n\n");
Expand Down

0 comments on commit 0467702

Please sign in to comment.