graphql_schema_diff/
patch.rs1mod directives;
2mod paths;
3mod schema_definitions;
4mod type_definitions;
5
6use self::paths::Paths;
7use crate::{Change, ChangeKind};
8
9const INDENTATION: &str = " ";
10
11pub fn patch<S>(source: &str, diff: &[Change], resolved_spans: &[S]) -> Result<PatchedSchema, cynic_parser::Error>
13where
14 S: AsRef<str>,
15{
16 let parsed = Some(source)
17 .filter(|source| !source.trim().is_empty()) .map(cynic_parser::parse_type_system_document)
19 .transpose()?
20 .unwrap_or_default();
21
22 let mut schema = String::with_capacity(source.len() / 2);
23 let paths = Paths::new(diff, resolved_spans, source);
24
25 for change in paths.iter_top_level() {
26 match change.kind() {
27 ChangeKind::AddSchemaDefinition
28 | ChangeKind::AddObjectType
29 | ChangeKind::AddUnion
30 | ChangeKind::AddEnum
31 | ChangeKind::AddScalar
32 | ChangeKind::AddInterface
33 | ChangeKind::AddDirectiveDefinition
34 | ChangeKind::AddInputObject => {
35 schema.push_str(change.resolved_str());
36 schema.push_str("\n\n");
37 }
38 ChangeKind::AddSchemaExtension => {
39 schema.push_str("extend ");
40 schema.push_str(change.resolved_str());
41 schema.push_str("\n\n");
42 }
43 _ => (),
44 }
45 }
46
47 for definition in parsed.definitions() {
48 match definition {
49 cynic_parser::type_system::Definition::Schema(def) => {
50 schema_definitions::patch_schema_definition(
51 def,
52 DefinitionOrExtension::Definition,
53 &mut schema,
54 &paths,
55 );
56 }
57 cynic_parser::type_system::Definition::SchemaExtension(def) => {
58 schema_definitions::patch_schema_definition(def, DefinitionOrExtension::Extension, &mut schema, &paths);
59 }
60 cynic_parser::type_system::Definition::Type(ty) => {
61 type_definitions::patch_type_definition(ty, DefinitionOrExtension::Definition, &mut schema, &paths);
62 }
63 cynic_parser::type_system::Definition::TypeExtension(ty) => {
64 type_definitions::patch_type_definition(ty, DefinitionOrExtension::Extension, &mut schema, &paths);
65 }
66 cynic_parser::type_system::Definition::Directive(directive_definition) => {
67 directives::patch_directive_definition(directive_definition, &mut schema, &paths);
68 }
69 }
70 }
71
72 Ok(PatchedSchema { schema })
73}
74
75enum DefinitionOrExtension {
76 Extension,
77 Definition,
78}
79
80impl DefinitionOrExtension {
81 #[must_use]
85 fn is_extension(&self) -> bool {
86 matches!(self, Self::Extension)
87 }
88
89 #[must_use]
93 fn is_definition(&self) -> bool {
94 matches!(self, Self::Definition)
95 }
96}
97
98pub struct PatchedSchema {
100 schema: String,
101}
102
103impl PatchedSchema {
104 pub fn into_schema(self) -> String {
106 self.schema
107 }
108
109 pub fn schema(&self) -> &str {
111 &self.schema
112 }
113}