Skip to content

Commit 0d93ac9

Browse files
authored
Introduce minify_query (#67)
Useful to reduce the size of payload
1 parent 64fb5af commit 0d93ac9

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,6 @@ pub mod schema;
105105

106106
pub use crate::query::parse_query;
107107
pub use crate::schema::parse_schema;
108+
pub use crate::query::minify_query;
108109
pub use crate::position::Pos;
109110
pub use crate::format::Style;

src/query/minify.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use crate::tokenizer::{Kind, Token, TokenStream};
2+
use combine::StreamOnce;
3+
use thiserror::Error;
4+
5+
/// Error minifying query
6+
#[derive(Error, Debug)]
7+
#[error("query minify error: {}", _0)]
8+
pub struct MinifyError(String);
9+
10+
pub fn minify_query<'a>(source: String) -> Result<String, MinifyError> {
11+
let mut bits: Vec<&str> = Vec::new();
12+
let mut stream = TokenStream::new(source.as_str());
13+
let mut prev_was_punctuator = false;
14+
15+
loop {
16+
match stream.uncons() {
17+
Ok(x) => {
18+
let token: Token = x;
19+
let is_non_punctuator = token.kind != Kind::Punctuator;
20+
21+
if prev_was_punctuator {
22+
if is_non_punctuator {
23+
bits.push(" ");
24+
}
25+
}
26+
27+
bits.push(token.value);
28+
prev_was_punctuator = is_non_punctuator;
29+
}
30+
Err(ref e) if e == &combine::easy::Error::end_of_input() => break,
31+
Err(e) => return Err(MinifyError(e.to_string())),
32+
}
33+
}
34+
35+
Ok(bits.join(""))
36+
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
#[test]
41+
fn strip_ignored_characters() {
42+
let source = "
43+
query SomeQuery($foo: String!, $bar: String) {
44+
someField(foo: $foo, bar: $bar) {
45+
a
46+
b {
47+
... on B {
48+
c
49+
d
50+
}
51+
}
52+
}
53+
}
54+
";
55+
56+
let minified = super::minify_query(source.to_string()).expect("minification failed");
57+
58+
assert_eq!(
59+
&minified,
60+
"query SomeQuery($foo:String!$bar:String){someField(foo:$foo bar:$bar){a b{...on B{c d}}}}"
61+
);
62+
}
63+
64+
#[test]
65+
fn unexpected_token() {
66+
let source = "
67+
query foo {
68+
bar;
69+
}
70+
";
71+
72+
let minified = super::minify_query(source.to_string());
73+
74+
assert_eq!(
75+
minified.is_err(),
76+
true
77+
);
78+
79+
assert_eq!(
80+
minified.unwrap_err().to_string(),
81+
"query minify error: Unexpected `unexpected character ';'`"
82+
);
83+
}
84+
}

src/query/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ mod ast;
44
mod error;
55
mod format;
66
mod grammar;
7-
7+
mod minify;
88

99
pub use self::grammar::{parse_query, consume_definition};
1010
pub use self::error::ParseError;
1111
pub use self::ast::*;
12+
pub use self::minify::minify_query;

0 commit comments

Comments
 (0)