From d436cdbb951e8aabac9ee283b6452136847d447f Mon Sep 17 00:00:00 2001 From: Filip Pacanowski Date: Thu, 16 May 2024 16:26:25 +0200 Subject: [PATCH] Experimental Rust parser + benchmark --- .dockerignore | 1 + Dockerfile | 49 + Gemfile | 2 + benchmark/parser_benchmark.rb | 33 + benchmark/run.rb | 6 +- rust_graphql_parser/.gitignore | 17 + rust_graphql_parser/.rspec | 3 + rust_graphql_parser/.rubocop.yml | 13 + rust_graphql_parser/Cargo.lock | 419 ++ rust_graphql_parser/Cargo.toml | 7 + rust_graphql_parser/Gemfile | 23 + rust_graphql_parser/LICENSE.txt | 21 + rust_graphql_parser/README.md | 37 + rust_graphql_parser/Rakefile | 20 + rust_graphql_parser/benchmark.rb | 28 + rust_graphql_parser/bin/console | 15 + rust_graphql_parser/bin/setup | 8 + .../ext/rust_graphql_parser/Cargo.toml | 16 + .../ext/rust_graphql_parser/extconf.rb | 6 + .../ext/rust_graphql_parser/src/lib.rs | 49 + .../rust_graphql_parser/src/translation.rs | 454 ++ .../lib/rust_graphql_parser.rb | 15 + .../lib/rust_graphql_parser/version.rb | 5 + rust_graphql_parser/negotiate.gql | 3643 +++++++++++++++++ .../rust_graphql_parser.gemspec | 41 + .../sig/rust_graphql_parser.rbs | 4 + .../spec/data/big_query.graphql | 3643 +++++++++++++++++ .../spec/data/directive_args.graphql | 3 + .../data/directive_args_multiline.graphql | 9 + .../spec/data/field_arguments.graphql | 13 + .../spec/data/fragment.graphql | 3 + .../spec/data/fragment_spread.graphql | 6 + .../spec/data/inline_fragment.graphql | 8 + .../spec/data/inline_fragment_dir.graphql | 8 + .../spec/data/kitchen-sink.graphql | 59 + .../spec/data/kitchen-sink_canonical.graphql | 54 + rust_graphql_parser/spec/data/minimal.graphql | 3 + .../spec/data/minimal_mutation.graphql | 3 + .../spec/data/minimal_query.graphql | 3 + .../spec/data/mutation_directive.graphql | 3 + .../spec/data/mutation_nameless_vars.graphql | 4 + .../spec/data/named_query.graphql | 3 + .../spec/data/nested_field_arguments.graphql | 10 + .../spec/data/nested_selection.graphql | 5 + .../spec/data/query_aliases.graphql | 3 + .../spec/data/query_arguments.graphql | 3 + .../data/query_arguments_multiline.graphql | 9 + .../query_array_argument_multiline.graphql | 9 + .../spec/data/query_directive.graphql | 3 + .../spec/data/query_list_argument.graphql | 3 + .../spec/data/query_nameless_vars.graphql | 4 + ...uery_nameless_vars_multiple_fields.graphql | 16 + ...ess_vars_multiple_fields_canonical.graphql | 14 + .../spec/data/query_object_argument.graphql | 3 + .../query_object_argument_multiline.graphql | 9 + .../spec/data/query_var_default_float.graphql | 3 + .../spec/data/query_var_default_list.graphql | 3 + .../data/query_var_default_object.graphql | 3 + .../data/query_var_default_string.graphql | 3 + .../spec/data/query_var_defaults.graphql | 3 + .../spec/data/query_vars.graphql | 3 + .../spec/data/string_literal.graphql | 3 + .../spec/data/subscription_directive.graphql | 3 + .../spec/data/triple_quoted_literal.graphql | 6 + rust_graphql_parser/spec/data/types.graphql | 10 + rust_graphql_parser/spec/integration_spec.rb | 54 + rust_graphql_parser/spec/spec_helper.rb | 15 + 67 files changed, 8959 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 benchmark/parser_benchmark.rb create mode 100644 rust_graphql_parser/.gitignore create mode 100644 rust_graphql_parser/.rspec create mode 100644 rust_graphql_parser/.rubocop.yml create mode 100644 rust_graphql_parser/Cargo.lock create mode 100644 rust_graphql_parser/Cargo.toml create mode 100644 rust_graphql_parser/Gemfile create mode 100644 rust_graphql_parser/LICENSE.txt create mode 100644 rust_graphql_parser/README.md create mode 100644 rust_graphql_parser/Rakefile create mode 100644 rust_graphql_parser/benchmark.rb create mode 100755 rust_graphql_parser/bin/console create mode 100755 rust_graphql_parser/bin/setup create mode 100644 rust_graphql_parser/ext/rust_graphql_parser/Cargo.toml create mode 100644 rust_graphql_parser/ext/rust_graphql_parser/extconf.rb create mode 100644 rust_graphql_parser/ext/rust_graphql_parser/src/lib.rs create mode 100644 rust_graphql_parser/ext/rust_graphql_parser/src/translation.rs create mode 100644 rust_graphql_parser/lib/rust_graphql_parser.rb create mode 100644 rust_graphql_parser/lib/rust_graphql_parser/version.rb create mode 100644 rust_graphql_parser/negotiate.gql create mode 100644 rust_graphql_parser/rust_graphql_parser.gemspec create mode 100644 rust_graphql_parser/sig/rust_graphql_parser.rbs create mode 100644 rust_graphql_parser/spec/data/big_query.graphql create mode 100644 rust_graphql_parser/spec/data/directive_args.graphql create mode 100644 rust_graphql_parser/spec/data/directive_args_multiline.graphql create mode 100644 rust_graphql_parser/spec/data/field_arguments.graphql create mode 100644 rust_graphql_parser/spec/data/fragment.graphql create mode 100644 rust_graphql_parser/spec/data/fragment_spread.graphql create mode 100644 rust_graphql_parser/spec/data/inline_fragment.graphql create mode 100644 rust_graphql_parser/spec/data/inline_fragment_dir.graphql create mode 100644 rust_graphql_parser/spec/data/kitchen-sink.graphql create mode 100644 rust_graphql_parser/spec/data/kitchen-sink_canonical.graphql create mode 100644 rust_graphql_parser/spec/data/minimal.graphql create mode 100644 rust_graphql_parser/spec/data/minimal_mutation.graphql create mode 100644 rust_graphql_parser/spec/data/minimal_query.graphql create mode 100644 rust_graphql_parser/spec/data/mutation_directive.graphql create mode 100644 rust_graphql_parser/spec/data/mutation_nameless_vars.graphql create mode 100644 rust_graphql_parser/spec/data/named_query.graphql create mode 100644 rust_graphql_parser/spec/data/nested_field_arguments.graphql create mode 100644 rust_graphql_parser/spec/data/nested_selection.graphql create mode 100644 rust_graphql_parser/spec/data/query_aliases.graphql create mode 100644 rust_graphql_parser/spec/data/query_arguments.graphql create mode 100644 rust_graphql_parser/spec/data/query_arguments_multiline.graphql create mode 100644 rust_graphql_parser/spec/data/query_array_argument_multiline.graphql create mode 100644 rust_graphql_parser/spec/data/query_directive.graphql create mode 100644 rust_graphql_parser/spec/data/query_list_argument.graphql create mode 100644 rust_graphql_parser/spec/data/query_nameless_vars.graphql create mode 100644 rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields.graphql create mode 100644 rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields_canonical.graphql create mode 100644 rust_graphql_parser/spec/data/query_object_argument.graphql create mode 100644 rust_graphql_parser/spec/data/query_object_argument_multiline.graphql create mode 100644 rust_graphql_parser/spec/data/query_var_default_float.graphql create mode 100644 rust_graphql_parser/spec/data/query_var_default_list.graphql create mode 100644 rust_graphql_parser/spec/data/query_var_default_object.graphql create mode 100644 rust_graphql_parser/spec/data/query_var_default_string.graphql create mode 100644 rust_graphql_parser/spec/data/query_var_defaults.graphql create mode 100644 rust_graphql_parser/spec/data/query_vars.graphql create mode 100644 rust_graphql_parser/spec/data/string_literal.graphql create mode 100644 rust_graphql_parser/spec/data/subscription_directive.graphql create mode 100644 rust_graphql_parser/spec/data/triple_quoted_literal.graphql create mode 100644 rust_graphql_parser/spec/data/types.graphql create mode 100644 rust_graphql_parser/spec/integration_spec.rb create mode 100644 rust_graphql_parser/spec/spec_helper.rb diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..94143827ed --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..21ffb69a17 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,49 @@ +FROM debian:bookworm-slim + +SHELL ["/bin/bash","-l","-c"] + +ENV DEBIAN_FRONTEND=noninteractive + +# Libs + +RUN apt-get update && apt-get install -y \ + curl \ + gnupg \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +RUN apt-get update && apt-get install -y libclang-dev + +RUN apt-get install ghostscript shared-mime-info openssl curl gnupg2 dirmngr git-core libcurl4-openssl-dev software-properties-common zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libffi-dev libpq-dev libmagickcore-6.q16-dev -y + +# Rust + +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y \ + && chmod +x $HOME/.cargo/bin/rustc + +# Ruby (rbenv) + +RUN git clone https://github.com/rbenv/rbenv.git ~/.rbenv +RUN echo 'export PATH="~/.rbenv/bin:$PATH"' >> ~/.bashrc +RUN echo 'eval "$(rbenv init -)"' >> ~/.bashrc + +RUN git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build +RUN echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc + +ENV PATH="${HOME}/.rbenv/plugins/ruby-build/bin:${HOME}/.rbenv/bin:${PATH}" + +RUN rbenv install 3.3.6 +RUN rbenv global 3.3.6 + +# Benchmark + +WORKDIR /app + +COPY . . + +RUN bundle config set without 'jekyll-plugins' && bundle install +RUN bundle exec rake clobber compile + +ENV PATH="/root/.cargo/bin:${PATH}" +RUN cd rust_graphql_parser && bundle install && bundle exec rake clobber compile && cd .. +CMD ["/root/.rbenv/shims/bundle", "exec", "ruby", "--yjit", "/app/benchmark/parser_benchmark.rb"] diff --git a/Gemfile b/Gemfile index 69aca9d35a..0776eddfef 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,8 @@ gem 'pry' gem 'pry-stack_explorer', platform: :ruby gem 'pry-byebug' +gem 'rust_graphql_parser', path: 'rust_graphql_parser' + if RUBY_VERSION >= "3.0" gem "libev_scheduler" gem "evt" diff --git a/benchmark/parser_benchmark.rb b/benchmark/parser_benchmark.rb new file mode 100644 index 0000000000..e41b1a505d --- /dev/null +++ b/benchmark/parser_benchmark.rb @@ -0,0 +1,33 @@ +require "benchmark/ips" +require "graphql/c_parser" +require 'rust_graphql_parser' +require "memory_profiler" + +BENCHMARK_PATH = File.expand_path("../", __FILE__) +BIG_QUERY_STRING = File.read(File.join(BENCHMARK_PATH, "big_query.graphql")) +BIG_QUERY = GraphQL.parse(BIG_QUERY_STRING) + +def rust_parse(query) + GraphQL.default_parser = RustGraphqlParserWrapper + GraphQL.parse(BIG_QUERY_STRING) +end + +def ruby_parse(query) + GraphQL.default_parser = GraphQL::Language::Parser + GraphQL.parse(BIG_QUERY_STRING) +end + +def c_parse(query) + GraphQL.default_parser = GraphQL::CParser + GraphQL.parse(BIG_QUERY_STRING) +end + +# Sanity check. +raise "output mismatch" unless rust_parse(BIG_QUERY) == ruby_parse(BIG_QUERY) + +Benchmark.ips(time: 30) do |x| + x.report("parsing - Rust") { rust_parse(BIG_QUERY) } + x.report("parsing - C") { c_parse(BIG_QUERY) } + x.report("parsing - Ruby") { ruby_parse(BIG_QUERY) } + x.compare! +end diff --git a/benchmark/run.rb b/benchmark/run.rb index 8052e0486f..25d1bd4842 100644 --- a/benchmark/run.rb +++ b/benchmark/run.rb @@ -47,7 +47,11 @@ def self.run(task) x.report("scan - big query") { GraphQL.scan_with_ruby(BIG_QUERY_STRING) } when "parse" # Uncomment this to use the C parser: - # require "graphql/c_parser" + require "graphql/c_parser" + require 'rust_graphql_parser' + GraphQL.default_parser = GraphQL::Language::Parser + # GraphQL.default_parser = GraphQL::CParser + # GraphQL.default_parser = YetAnotherParser x.report("parse - introspection") { GraphQL.parse(QUERY_STRING) } x.report("parse - fragments") { GraphQL.parse(ABSTRACT_FRAGMENTS_2_QUERY_STRING) } x.report("parse - big query") { GraphQL.parse(BIG_QUERY_STRING) } diff --git a/rust_graphql_parser/.gitignore b/rust_graphql_parser/.gitignore new file mode 100644 index 0000000000..83b1b8d61d --- /dev/null +++ b/rust_graphql_parser/.gitignore @@ -0,0 +1,17 @@ +/.bundle/ +/.yardoc +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ +*.bundle +*.so +*.o +*.a +mkmf.log +target/ + +# rspec failure tracking +.rspec_status diff --git a/rust_graphql_parser/.rspec b/rust_graphql_parser/.rspec new file mode 100644 index 0000000000..34c5164d9b --- /dev/null +++ b/rust_graphql_parser/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--require spec_helper diff --git a/rust_graphql_parser/.rubocop.yml b/rust_graphql_parser/.rubocop.yml new file mode 100644 index 0000000000..e3462a7494 --- /dev/null +++ b/rust_graphql_parser/.rubocop.yml @@ -0,0 +1,13 @@ +AllCops: + TargetRubyVersion: 2.6 + +Style/StringLiterals: + Enabled: true + EnforcedStyle: double_quotes + +Style/StringLiteralsInInterpolation: + Enabled: true + EnforcedStyle: double_quotes + +Layout/LineLength: + Max: 120 diff --git a/rust_graphql_parser/Cargo.lock b/rust_graphql_parser/Cargo.lock new file mode 100644 index 0000000000..4158eaa043 --- /dev/null +++ b/rust_graphql_parser/Cargo.lock @@ -0,0 +1,419 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "graphql-parser" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ebc8013b4426d5b81a4364c419a95ed0b404af2b82e2457de52d9348f0e474" +dependencies = [ + "combine", + "thiserror", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "magnus" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4778544796676e8428e9c622460ebf284bea52d8b10db3aeb449d8b5e61b3a13" +dependencies = [ + "magnus-macros", + "rb-sys", + "rb-sys-env", + "seq-macro", +] + +[[package]] +name = "magnus-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rb-sys" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55d933382388cc7a6fdfd54e222eca7994791ac4b9ce5c9e8df280c739d86bbe" +dependencies = [ + "rb-sys-build", +] + +[[package]] +name = "rb-sys-build" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc5a7e3a875419baaa0d8cc606cdfb9361b444cb7e5abcf0de4693025887374" +dependencies = [ + "bindgen", + "lazy_static", + "proc-macro2", + "quote", + "regex", + "shell-words", + "syn", +] + +[[package]] +name = "rb-sys-env" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb" + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rust_graphql_parser" +version = "0.1.0" +dependencies = [ + "graphql-parser", + "magnus", + "once_cell", + "rb-sys", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "seq-macro" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" + +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" diff --git a/rust_graphql_parser/Cargo.toml b/rust_graphql_parser/Cargo.toml new file mode 100644 index 0000000000..f17f9b5c17 --- /dev/null +++ b/rust_graphql_parser/Cargo.toml @@ -0,0 +1,7 @@ +# This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is +# a Rust project. Your extensions dependencies should be added to the Cargo.toml +# in the ext/ directory. + +[workspace] +members = ["./ext/rust_graphql_parser"] +resolver = "2" diff --git a/rust_graphql_parser/Gemfile b/rust_graphql_parser/Gemfile new file mode 100644 index 0000000000..c362235d8d --- /dev/null +++ b/rust_graphql_parser/Gemfile @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# Specify your gem's dependencies in rust_graphql_parser.gemspec +gemspec + +gem "rake", "~> 13.0" + +gem "rake-compiler" +gem "rb_sys" + +gem "rspec", "~> 3.0" + +gem "rubocop", "~> 1.21" + +gem "benchmark-ips" +gem "memory_profiler" + +gem "graphql" +gem "graphql-c_parser" + +gem 'pry' diff --git a/rust_graphql_parser/LICENSE.txt b/rust_graphql_parser/LICENSE.txt new file mode 100644 index 0000000000..c8d21dd3d9 --- /dev/null +++ b/rust_graphql_parser/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Filip Pacanowski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/rust_graphql_parser/README.md b/rust_graphql_parser/README.md new file mode 100644 index 0000000000..4c2886d58d --- /dev/null +++ b/rust_graphql_parser/README.md @@ -0,0 +1,37 @@ +# RustGraphqlParser + +This is an experimental gem that provides a Rust-based implementation of GraphQL parser. + +TODO: Delete this and the text below, and describe your gem + +Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rust_graphql_parser`. To experiment with that code, run `bin/console` for an interactive prompt. + +## Installation + +TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org. + +Install the gem and add to the application's Gemfile by executing: + + $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG + +If bundler is not being used to manage dependencies, install the gem by executing: + + $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG + +## Usage + +TODO: Write usage instructions here + +## Development + +After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. + +To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org). + +## Contributing + +Bug reports and pull requests are welcome on GitHub at https://github.com/fpacanowski/rust_graphql_parser. + +## License + +The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). diff --git a/rust_graphql_parser/Rakefile b/rust_graphql_parser/Rakefile new file mode 100644 index 0000000000..363fd1d288 --- /dev/null +++ b/rust_graphql_parser/Rakefile @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require "bundler/gem_tasks" +require "rspec/core/rake_task" + +RSpec::Core::RakeTask.new(:spec) + +require "rubocop/rake_task" + +RuboCop::RakeTask.new + +require "rake/extensiontask" + +task build: :compile + +Rake::ExtensionTask.new("rust_graphql_parser") do |ext| + ext.lib_dir = "lib/rust_graphql_parser" +end + +task default: %i[compile spec rubocop] diff --git a/rust_graphql_parser/benchmark.rb b/rust_graphql_parser/benchmark.rb new file mode 100644 index 0000000000..6c4d01c5d0 --- /dev/null +++ b/rust_graphql_parser/benchmark.rb @@ -0,0 +1,28 @@ +require 'benchmark/ips' +require 'rust_graphql_parser' +require 'graphql/c_parser' +require 'graphql' +require 'memory_profiler' + +source = File.read('negotiate.gql') +raise "mismatch" unless GraphQL.parse(source) == AnotherParser.parse(source) + +# MemoryProfiler.report{ GraphQL.parse(source) }.pretty_print +# MemoryProfiler.report{ AnotherParser.parse(source) }.pretty_print + +# GC.disable +r = Benchmark.ips do |x| + # x.report('parse_raw') { RustGraphqlParser.parse_raw(source) } + x.report('parse_ruby') { GraphQL.parse(source) } + # x.report('parse_and_translate') { RustGraphqlParser.translate(RustGraphqlParser.parse(source)) } + # x.report('parse') { RustGraphqlParser.parse(source) } + x.report('parse2') { AnotherParser.parse(source) } + + x.compare! +end + +r.data.each do |entry| + iterations = entry.fetch(:iterations) + time = entry.fetch(:microseconds) + puts "#{entry.fetch(:name)} = #{format("%.2f", time/iterations/1000)} ms" +end diff --git a/rust_graphql_parser/bin/console b/rust_graphql_parser/bin/console new file mode 100755 index 0000000000..4d169d3a0f --- /dev/null +++ b/rust_graphql_parser/bin/console @@ -0,0 +1,15 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "bundler/setup" +require "rust_graphql_parser" + +# You can add fixtures and/or initialization code here to make experimenting +# with your gem easier. You can also use a different console, if you like. + +# (If you use this, don't forget to add pry to your Gemfile!) +# require "pry" +# Pry.start + +require "irb" +IRB.start(__FILE__) diff --git a/rust_graphql_parser/bin/setup b/rust_graphql_parser/bin/setup new file mode 100755 index 0000000000..dce67d860a --- /dev/null +++ b/rust_graphql_parser/bin/setup @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +set -vx + +bundle install + +# Do any other automated setup that you need to do here diff --git a/rust_graphql_parser/ext/rust_graphql_parser/Cargo.toml b/rust_graphql_parser/ext/rust_graphql_parser/Cargo.toml new file mode 100644 index 0000000000..c894c40e74 --- /dev/null +++ b/rust_graphql_parser/ext/rust_graphql_parser/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rust_graphql_parser" +version = "0.1.0" +edition = "2021" +authors = ["Filip Pacanowski "] +license = "MIT" +publish = false + +[lib] +crate-type = ["cdylib"] + +[dependencies] +rb-sys = { version = "0.9", features = ["ruby-static", "stable-api-compiled-fallback"] } +graphql-parser = "0.4.0" +magnus = { version = "0.6.2" } +once_cell = "1.19.0" diff --git a/rust_graphql_parser/ext/rust_graphql_parser/extconf.rb b/rust_graphql_parser/ext/rust_graphql_parser/extconf.rb new file mode 100644 index 0000000000..4102bbaf0e --- /dev/null +++ b/rust_graphql_parser/ext/rust_graphql_parser/extconf.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +require "mkmf" +require "rb_sys/mkmf" + +create_rust_makefile("rust_graphql_parser/rust_graphql_parser") diff --git a/rust_graphql_parser/ext/rust_graphql_parser/src/lib.rs b/rust_graphql_parser/ext/rust_graphql_parser/src/lib.rs new file mode 100644 index 0000000000..1927c52242 --- /dev/null +++ b/rust_graphql_parser/ext/rust_graphql_parser/src/lib.rs @@ -0,0 +1,49 @@ +use graphql_parser::query::parse_query; +mod translation; + +use rb_sys::{ + rb_define_module, rb_define_singleton_method, rb_str_buf_append, + rb_utf8_str_new_cstr, VALUE, rb_str_new, rb_string_value_ptr, rb_string_value_cstr +}; +use std::{intrinsics::transmute, os::raw::c_char}; + +use std::ffi::CStr; +use std::str; + +// Converts a static &str to a C string usable in foreign functions. +macro_rules! static_cstring { + ($string:expr) => {{ + concat!($string, "\0").as_ptr() as *const c_char + }}; +} + +unsafe fn parse(query: VALUE) -> VALUE { + let ptr = rb_sys::RSTRING_PTR(query) as *const u8; + let len = rb_sys::RSTRING_LEN(query) as usize; + // let query_str = std::ffi::CStr::from_ptr(query_ptr).to_str().unwrap(); + let query_str = std::str::from_utf8_unchecked(std::slice::from_raw_parts(ptr, len)); + let ast = parse_query::<&str>(&query_str).unwrap(); + // let result: String = format!("{:?}", ast); + // // let result: String = "foo".to_string(); + // return rb_str_new(result.as_ptr() as *const c_char, result.len().try_into().unwrap()); + return translation::translate_document(&ast); +} + +unsafe extern "C" fn wrapped_parse(_: VALUE, query: VALUE) -> VALUE { + let result = parse(query); + return result; +} + +#[no_mangle] +unsafe extern "C" fn Init_rust_graphql_parser() { + let module = rb_define_module(static_cstring!("RustGraphqlParser")); + + rb_define_singleton_method( + module, + static_cstring!("parse"), + Some(transmute:: VALUE, _>( + wrapped_parse, + )), + 1, + ); +} \ No newline at end of file diff --git a/rust_graphql_parser/ext/rust_graphql_parser/src/translation.rs b/rust_graphql_parser/ext/rust_graphql_parser/src/translation.rs new file mode 100644 index 0000000000..f01968b7ed --- /dev/null +++ b/rust_graphql_parser/ext/rust_graphql_parser/src/translation.rs @@ -0,0 +1,454 @@ +use std::any::type_name; + +use graphql_parser::query::{ + Definition, Document, Field, FragmentDefinition, FragmentSpread, InlineFragment, Mutation, + OperationDefinition, Query, Selection, SelectionSet, Subscription, TypeCondition, + VariableDefinition, +}; +use graphql_parser::schema::{Directive, Type, Value}; +use graphql_parser::Pos; +use rb_sys::{VALUE, rb_intern, rb_hash_new, rb_id2sym, rb_hash_aset, rb_hash_bulk_insert, rb_ary_new_capa, rb_ary_push}; + + +macro_rules! static_cstring { + ($string:expr) => {{ + concat!($string, "\0").as_ptr() as *const std::os::raw::c_char + }}; +} + +pub unsafe fn translate_document<'a>(doc: &'a Document<'a, &'a str>) -> VALUE { + let definitions = rb_sys::rb_ary_new(); + for x in doc.definitions.iter() { + rb_sys::rb_ary_push(definitions, translate_definition(x)); + } + let kwargs = rb_hash_new(); + rb_sys::rb_hash_aset( + kwargs, rb_sys::rb_id2sym(rb_intern(static_cstring!("definitions"))), definitions); + return build_instance(*classes::DOCUMENT, kwargs); +} + +unsafe fn translate_definition<'a>(definition: &'a Definition<'a, &'a str>) -> VALUE { + return match definition { + Definition::Operation(operation) => translate_operation_definition(operation), + Definition::Fragment(fragment) => translate_fragment_definition(fragment), + }; +} + +unsafe fn translate_operation_definition<'a>(operation_definition: &'a OperationDefinition<'a, &'a str>) -> VALUE { + if let OperationDefinition::SelectionSet(selection_set) = &operation_definition { + return translate_top_level_selection_set(selection_set); + } + return match operation_definition { + OperationDefinition::Query(query) => translate_query(query), + OperationDefinition::SelectionSet(selection_set) => translate_selection_set(selection_set), + OperationDefinition::Mutation(mutation) => translate_mutation(mutation), + OperationDefinition::Subscription(subscription) => translate_subscription(subscription), + }; +} + +unsafe fn translate_top_level_selection_set<'a>(selection_set: &SelectionSet<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::OPERATION_TYPE, ruby_str("query"), + *symbols::SELECTIONS, translate_selection_set(selection_set), + ]); + return build_instance(*classes::OPERATION_DEFINITION, kwargs); +} + +unsafe fn translate_query<'a>(query: &Query<'a, &'a str>) -> VALUE { + translate_operation( + "query", + query.name, + &query.selection_set, + &query.variable_definitions, + &query.directives, + ) +} + +unsafe fn translate_mutation<'a>(mutation: &Mutation<'a, &'a str>) -> VALUE { + translate_operation( + "mutation", + mutation.name, + &mutation.selection_set, + &mutation.variable_definitions, + &mutation.directives, + ) +} + +unsafe fn translate_subscription<'a>(subscription: &Subscription<'a, &'a str>) -> VALUE { + translate_operation( + "subscription", + subscription.name, + &subscription.selection_set, + &subscription.variable_definitions, + &subscription.directives, + ) +} + +unsafe fn translate_operation<'a>( + operation_type: &str, + operation_name: Option<&'a str>, + selection_set: &SelectionSet<'a, &'a str>, + definitions: &Vec>, + directives: &Vec> +) -> VALUE { + let kwargs = rb_hash_new(); + rb_hash_aset(kwargs, *symbols::OPERATION_TYPE, ruby_str(operation_type)); + if let Some(name) = &operation_name { + rb_hash_aset(kwargs, *symbols::NAME, ruby_str(name)); + } + rb_hash_aset(kwargs, *symbols::SELECTIONS, + translate_selection_set(selection_set)); + rb_hash_aset(kwargs, *symbols::VARIABLES, + translate_variable_definitions(definitions)); + rb_hash_aset(kwargs, *symbols::DIRECTIVES, + translate_directives(directives)); + return build_instance(*classes::OPERATION_DEFINITION, kwargs); +} + +unsafe fn translate_variable_definitions<'a>(definitions: &Vec>) -> VALUE { + let result:VALUE = rb_ary_new_capa(definitions.len() as _); + for x in definitions { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(&x.name), + *symbols::TYPE, translate_type(&x.var_type), + *symbols::DEFAULT_VALUE, x.default_value.as_ref().map_or(rb_sys::Qnil as _, + |x| {translate_value(&x)} + ) + ]); + rb_ary_push(result, build_instance(*classes::VARIABLE_DEFINITION, kwargs)); + } + return result; +} + +unsafe fn translate_fragment_definition<'a>(fragment_definition: &FragmentDefinition<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(&fragment_definition.name), + *symbols::TYPE, translate_type_condition(&fragment_definition.type_condition), + *symbols::SELECTIONS, translate_selection_set(&fragment_definition.selection_set), + ]); + return build_instance(*classes::FRAGMENT_DEFINITION, kwargs); +} + +unsafe fn translate_type_condition<'a>(type_condition: &TypeCondition<'a, &'a str>) -> VALUE { + let TypeCondition::On(type_name) = type_condition; + let kwargs = build_hash(&[*symbols::NAME, ruby_str(type_name)]); + return build_instance(*classes::TYPE_NAME, kwargs); +} + +unsafe fn translate_selection_set<'a>(selection_set: &SelectionSet<'a, &'a str>) -> VALUE { + let result: VALUE = rb_ary_new_capa(selection_set.items.len() as _); + for x in selection_set.items.iter() { + rb_ary_push(result, translate_selection(x)); + } + return result; + // let hash = RHash::new(); + // hash.aset(Symbol::new("node_type"), Symbol::new("selection_set")) + // .unwrap(); + + // let span = RArray::new(); + // span.push(translate_position(&selection_set.span.0)) + // .unwrap(); + // span.push(translate_position(&selection_set.span.1)) + // .unwrap(); + // hash.aset(Symbol::new("span"), span).unwrap(); + + // let items = RArray::new(); + // for x in selection_set.items.iter() { + // items.push(translate_selection(x)).unwrap(); + // } + // hash.aset(Symbol::new("items"), items).unwrap(); + + // return hash; +} + +unsafe fn translate_selection<'a>(selection: &Selection<'a, &'a str>) -> VALUE { + return match selection { + Selection::Field(field) => translate_field(field), + Selection::FragmentSpread(fragment_spread) => translate_fragment_spread(fragment_spread), + Selection::InlineFragment(inline_fragment) => translate_inline_fragment(inline_fragment), + }; +} + +unsafe fn translate_field<'a>(field: &Field<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(&field.name), + *symbols::ARGUMENTS, translate_arguments(&field.arguments), + *symbols::SELECTIONS, translate_selection_set(&field.selection_set), + ]); + if let Some(alias) = &field.alias { + rb_hash_aset(kwargs, *symbols::FIELD_ALIAS, ruby_str(&alias)); + } + rb_hash_aset(kwargs, *symbols::DIRECTIVES, translate_directives(&field.directives)); + + return build_instance(*classes::FIELD, kwargs); +} + +unsafe fn translate_arguments<'a>(arguments: &Vec<(&'a str, Value<'a, &'a str>)>) -> VALUE { + let result: VALUE = rb_ary_new_capa(arguments.len() as _); + for (arg_name, arg_value) in arguments { + rb_ary_push(result, translate_argument(arg_name, arg_value)); + } + return result; +} + +unsafe fn translate_argument<'a>(name: &str, value: &Value<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(name), + *symbols::VALUE, translate_value(value), + ]); + return build_instance(*classes::ARGUMENT, kwargs); +} + +unsafe fn translate_value<'a>(value: &Value<'a, &'a str>) -> VALUE { + return match value { + Value::Variable(variable) => { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(variable), + ]); + build_instance(*classes::VARIABLE_IDENTIFIER, kwargs) + } + Value::Int(number) => { + rb_sys::rb_int2inum(number.as_i64().unwrap() as _) + } + Value::Float(number) => { + rb_sys::rb_float_new(*number) + } + Value::String(str) => { + ruby_str(str) + } + Value::Boolean(true) => { rb_sys::Qtrue as _ }, + Value::Boolean(false) => { rb_sys::Qfalse as _ }, + Value::Null => { + build_instance( + *classes::NULL_VALUE, + build_hash(&[*symbols::NAME, ruby_str("null")]) + ) + }, + Value::Enum(enum_name) => { + build_instance( + *classes::ENUM, + build_hash(&[*symbols::NAME, ruby_str(&enum_name)]) + ) + } + Value::List(vals) => { + let result: VALUE = rb_ary_new_capa(vals.len() as _); + for v in vals.iter() { + rb_ary_push(result, translate_value(v)); + } + result + } + Value::Object(obj) => { + let arguments: VALUE = rb_ary_new_capa(obj.len() as _); + for (name, val) in obj.iter() { + rb_ary_push(arguments, translate_argument(name, val)); + } + let kwargs = build_hash(&[ + *symbols::ARGUMENTS, arguments + ]); + build_instance(*classes::INPUT_OBJECT, kwargs) + } + }; +} + +unsafe fn translate_directives<'a>(directives: &Vec>) -> VALUE { + let result = rb_ary_new_capa(directives.len() as _); + for directive in directives.iter() { + rb_ary_push(result, translate_directive(directive)); + } + return result; +} + +unsafe fn translate_directive<'a>(directive: &Directive<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(&directive.name), + *symbols::ARGUMENTS, translate_arguments(&directive.arguments), + ]); + return build_instance(*classes::DIRECTIVE, kwargs); +} + +unsafe fn translate_fragment_spread<'a>(fragment_spread: &FragmentSpread<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::NAME, ruby_str(fragment_spread.fragment_name), + ]); + return build_instance(*classes::FRAGMENT_SPREAD, kwargs); +} + +unsafe fn translate_inline_fragment<'a>(inline_fragment: &InlineFragment<'a, &'a str>) -> VALUE { + let kwargs = build_hash(&[ + *symbols::SELECTIONS, translate_selection_set(&inline_fragment.selection_set), + *symbols::DIRECTIVES, translate_directives(&inline_fragment.directives), + ]); + if let Some(TypeCondition::On(on_type)) = &inline_fragment.type_condition { + rb_hash_aset( + kwargs, + *symbols::TYPE, + build_instance( + *classes::TYPE_NAME, + build_hash(&[*symbols::NAME, ruby_str(on_type)]) + ) + ); + } + return build_instance(*classes::INLINE_FRAGMENT, kwargs); +} + +unsafe fn translate_type<'a>(type_def: &Type<'a, &'a str>) -> VALUE { + return match type_def { + Type::NamedType(type_name) => { + let kwargs = build_hash(&[*symbols::NAME, ruby_str(&type_name)]); + build_instance(*classes::TYPE_NAME, kwargs) + } + Type::ListType(inner_type) => { + let kwargs = build_hash(&[ + *symbols::OF_TYPE, translate_type(inner_type) + ]); + build_instance(*classes::LIST_TYPE, kwargs) + } + Type::NonNullType(inner_type) => { + let kwargs = build_hash(&[ + *symbols::OF_TYPE, translate_type(inner_type) + ]); + build_instance(*classes::NON_NULL_TYPE, kwargs) + } + }; +} + +mod symbols { + use rb_sys::{VALUE, rb_intern, rb_hash_new, rb_id2sym, rb_hash_aset, rb_hash_bulk_insert}; + use once_cell::sync::Lazy; + pub static NAME: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("name")) + }); + pub static TYPE: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("type")) + }); + pub static SELECTIONS: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("selections")) + }); + pub static OPERATION_TYPE: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("operation_type")) + }); + pub static VARIABLES: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("variables")) + }); + pub static OF_TYPE: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("of_type")) + }); + pub static FIELD_ALIAS: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("field_alias")) + }); + pub static ARGUMENTS: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("arguments")) + }); + pub static VALUE: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("value")) + }); + pub static DIRECTIVES: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("directives")) + }); + pub static DEFAULT_VALUE: Lazy = Lazy::new(|| unsafe { + rb_id2sym(rb_intern!("default_value")) + }); +} + +mod classes { + use rb_sys::{VALUE, rb_intern}; + use once_cell::sync::Lazy; + pub static DOCUMENT: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("Document")) + }); + pub static FIELD: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("Field")) + }); + pub static FRAGMENT_DEFINITION: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("FragmentDefinition")) + }); + pub static TYPE_NAME: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("TypeName")) + }); + pub static OPERATION_DEFINITION: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("OperationDefinition")) + }); + pub static VARIABLE_DEFINITION: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("VariableDefinition")) + }); + pub static LIST_TYPE: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("ListType")) + }); + pub static NON_NULL_TYPE: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("NonNullType")) + }); + pub static ARGUMENT: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("Argument")) + }); + pub static VARIABLE_IDENTIFIER: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("VariableIdentifier")) + }); + pub static NULL_VALUE: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("NullValue")) + }); + pub static ENUM: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("Enum")) + }); + pub static INLINE_FRAGMENT: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("InlineFragment")) + }); + pub static INPUT_OBJECT: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("InputObject")) + }); + pub static DIRECTIVE: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("Directive")) + }); + pub static FRAGMENT_SPREAD: Lazy = Lazy::new(|| unsafe { + resolve(static_cstring!("FragmentSpread")) + }); + + unsafe fn resolve(class_name: *const std::os::raw::c_char) -> VALUE { + let cGraphQL = rb_sys::rb_const_get( + rb_sys::rb_cObject, + rb_intern!("GraphQL")); + let cLanguage = rb_sys::rb_const_get( + cGraphQL, + rb_intern!("Language")); + let cNodes = rb_sys::rb_const_get( + cLanguage, + rb_intern!("Nodes")); + + return rb_sys::rb_const_get( + cNodes, + rb_intern(class_name)); + } +} + +unsafe fn unimplemented() -> VALUE { + return build_hash(&[rb_id2sym(rb_intern(static_cstring!("unimplemented"))), rb_sys::Qtrue as _]) +} + +unsafe fn build_hash(arr: &[VALUE]) -> VALUE { + let result = rb_hash_new(); + rb_hash_bulk_insert(arr.len() as _, arr.as_ptr(), result); + return result; +} + +unsafe fn build_instance(class: VALUE, kwargs: VALUE) -> VALUE { + rb_sys::rb_class_new_instance_kw(1, &kwargs, class, 1) +} + +unsafe fn ruby_str(rust_str: &str) -> VALUE { + rb_sys::rb_str_new(rust_str.as_ptr() as _,rust_str.len() as _) +} + +macro_rules! build_node { + ($class:expr, $($args:expr),*) => { + rb_sys::rb_funcall( + $class, + rb_intern!("from_a"), + count_args!( $($args),* ), + $($args),* + ); + }; +} + +macro_rules! count_args { + () => { 0 }; + ($_arg:expr $(, $args:expr)*) => { 1 + count_args!($($args),*) }; +} diff --git a/rust_graphql_parser/lib/rust_graphql_parser.rb b/rust_graphql_parser/lib/rust_graphql_parser.rb new file mode 100644 index 0000000000..b4c4789dae --- /dev/null +++ b/rust_graphql_parser/lib/rust_graphql_parser.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require_relative "rust_graphql_parser/version" +require_relative "rust_graphql_parser/rust_graphql_parser" + +module RustGraphqlParser +end + +class RustGraphqlParserWrapper + def self.parse(query_string, filename: nil, trace: GraphQL::Tracing::NullTrace, max_tokens: nil) + trace.parse(query_string: query_string) do + RustGraphqlParser.parse(query_string) + end + end +end diff --git a/rust_graphql_parser/lib/rust_graphql_parser/version.rb b/rust_graphql_parser/lib/rust_graphql_parser/version.rb new file mode 100644 index 0000000000..20c4c6714e --- /dev/null +++ b/rust_graphql_parser/lib/rust_graphql_parser/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module RustGraphqlParser + VERSION = "0.1.0" +end diff --git a/rust_graphql_parser/negotiate.gql b/rust_graphql_parser/negotiate.gql new file mode 100644 index 0000000000..147a1ecfc5 --- /dev/null +++ b/rust_graphql_parser/negotiate.gql @@ -0,0 +1,3643 @@ +query NegotiateFromSession( + $sessionToken: String! + $checkpointData: String + $queueToken: String +) { + session(sessionInput: { sessionToken: $sessionToken }) { + context { + session { + ... on UnvalidatedParametersFact { + email + phone + shippingAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + zoneCode + postalCode: zip + __typename + } + billingAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + zoneCode + postalCode: zip + __typename + } + __typename + } + ... on PreviousNegotiationFact { + orderNumber + requiresShipping + __typename + } + __typename + } + policies { + payment { + ... on WalletsFact { + walletsAlreadyOffered + __typename + } + ... on PreviousPaymentsFact { + previouslyPaidTotal { + amount + currencyCode + __typename + } + updatedTotal { + amount + currencyCode + __typename + } + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + __typename + } + __typename + } + __typename + } + buyerIdentity { + ... on PreviousBuyerIdentityFact { + contactMethod { + email + phoneNumber + __typename + } + __typename + } + __typename + } + tax { + ... on PreviousTaxFact { + total { + amount + currencyCode + __typename + } + __typename + } + __typename + } + discount { + ... on PreviousDiscountFact { + orderLevelDiscounts { + label + amount { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + merchandise { + ... on PreviousMerchandiseFact { + lines { + title + variantTitle + quantity + sku + image { + id + altText + url + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + properties { + ...MerchandiseProperties + __typename + } + price { + amount + currencyCode + __typename + } + priceAfterDiscounts { + amount + currencyCode + __typename + } + appliedDiscounts { + label + amountDiscounted { + amount + currencyCode + __typename + } + __typename + } + quantityChange { + delta + type + __typename + } + __typename + } + __typename + } + __typename + } + tip { + ... on PreviousTipFact { + total { + amount + currencyCode + __typename + } + __typename + } + __typename + } + delivery { + ... on PreviousDeliveryFact { + total { + amount + currencyCode + __typename + } + deliveryAddress { + ... on StreetAddress { + address1 + address2 + city + company + coordinates { + latitude + longitude + __typename + } + countryCode + firstName + label + lastName + name + phone + postalCode + zoneCode + __typename + } + ... on Geolocation { + coordinates { + latitude + longitude + __typename + } + country { + code + name + __typename + } + zone { + code + name + __typename + } + __typename + } + ... on PartialStreetAddress { + address1 + address2 + address3 + city + company + countryCode + firstName + lastName + name + phone + postalCode + zoneCode + coordinates { + latitude + longitude + __typename + } + __typename + } + __typename + } + pickupAddress { + address1 + countryCode + coordinates { + latitude + longitude + __typename + } + address2 + city + postalCode + zoneCode + phone + __typename + } + pickupAddressName + lines { + title + lineAmount { + amount + currencyCode + __typename + } + appliedDiscounts { + label + allocationValue { + ... on PercentageValue { + percentage + __typename + } + ... on FixedAmountValue { + fixedAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + appliesOnEachItem + __typename + } + __typename + } + amountDiscounted { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + sessionType + sourceId + sourceVersion + checkoutSessionIdentifier + storefrontAnalyticsStartedOrderEventId + negotiate( + input: { checkpointData: $checkpointData, queueToken: $queueToken } + ) { + result { + ... on NegotiationResultAvailable { + queueToken + buyerProposal { + ...BuyerProposalDetails + __typename + } + sellerProposal { + ...ProposalDetails + __typename + } + __typename + } + ... on CheckpointDenied { + redirectUrl + __typename + } + ... on Throttled { + pollAfter + queueToken + pollUrl + buyerProposal { + ...BuyerProposalDetails + __typename + } + __typename + } + ... on NegotiationResultFailed { + __typename + } + ... on SubmittedForCompletion { + __typename + receipt { + ...ReceiptDetails + __typename + } + } + __typename + } + errors { + code + localizedMessage + nonLocalizedMessage + localizedMessageHtml + ... on RemoveTermViolation { + target + __typename + } + ... on AcceptNewTermViolation { + target + __typename + } + ... on ConfirmChangeViolation { + from + to + __typename + } + ... on UnprocessableTermViolation { + target + __typename + } + ... on UnresolvableTermViolation { + target + __typename + } + ... on InputValidationError { + field + __typename + } + ... on GenericError { + __typename + } + __typename + } + __typename + } + __typename + } +} +fragment MerchandiseProperties on MerchandiseProperty { + name + value { + ... on MerchandisePropertyValueString { + string: value + __typename + } + ... on MerchandisePropertyValueInt { + int: value + __typename + } + ... on MerchandisePropertyValueFloat { + float: value + __typename + } + ... on MerchandisePropertyValueBoolean { + boolean: value + __typename + } + ... on MerchandisePropertyValueJson { + json: value + __typename + } + __typename + } + visible + __typename +} +fragment BuyerProposalDetails on Proposal { + merchandiseDiscount { + ...ProposalDiscountFragment + __typename + } + deliveryDiscount { + ...ProposalDiscountFragment + __typename + } + delivery { + ...ProposalDeliveryFragment + __typename + } + merchandise { + ... on FilledMerchandiseTerms { + taxesIncluded + merchandiseLines { + stableId + merchandise { + ...SourceProvidedMerchandise + ...ProductVariantMerchandiseDetails + ...ContextualizedProductVariantMerchandiseDetails + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + quantity { + ... on ProposalMerchandiseQuantityByItem { + items { + ... on IntValueConstraint { + value + __typename + } + __typename + } + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + recurringTotal { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + lineAllocations { + ...LineAllocationDetails + __typename + } + lineComponents { + ...MerchandiseBundleLineComponent + __typename + } + __typename + } + __typename + } + __typename + } + runningTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + total { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalTaxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + deferredTotal { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + subtotalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + taxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + dueAt + __typename + } + hasOnlyDeferredShipping + subtotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + attribution { + attributions { + ... on AttributionItem { + ... on RetailAttributions { + deviceId + locationId + userId + __typename + } + ... on DraftOrderAttributions { + userIdentifier: userId + sourceName + locationIdentifier: locationId + __typename + } + __typename + } + __typename + } + __typename + } + __typename +} +fragment ProposalDiscountFragment on DiscountTermsV2 { + __typename + ... on FilledDiscountTerms { + lines { + ...DiscountLineDetailsFragment + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + taskId + __typename + } + ... on UnavailableTerms { + __typename + } +} +fragment DiscountLineDetailsFragment on DiscountLine { + allocations { + ... on DiscountAllocatedAllocationSet { + __typename + allocations { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + target { + index + targetType + stableId + __typename + } + __typename + } + } + __typename + } + discount { + ...DiscountDetailsFragment + __typename + } + lineAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename +} +fragment DiscountDetailsFragment on Discount { + ... on CustomDiscount { + title + presentationLevel + signature + signatureUuid + type + value { + ... on PercentageValue { + percentage + __typename + } + ... on FixedAmountValue { + appliesOnEachItem + fixedAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + ... on CodeDiscount { + title + code + presentationLevel + __typename + } + ... on DiscountCodeTrigger { + code + __typename + } + ... on AutomaticDiscount { + presentationLevel + title + __typename + } + __typename +} +fragment ProposalDeliveryFragment on DeliveryTerms { + __typename + ... on FilledDeliveryTerms { + intermediateRates + progressiveRatesEstimatedTimeUntilCompletion + shippingRatesStatusToken + deliveryLines { + destinationAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on Geolocation { + country { + code + __typename + } + zone { + code + __typename + } + coordinates { + latitude + longitude + __typename + } + __typename + } + ... on PartialStreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + coordinates { + latitude + longitude + __typename + } + __typename + } + __typename + } + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + groupType + selectedDeliveryStrategy { + ... on CompleteDeliveryStrategy { + handle + __typename + } + ... on DeliveryStrategyReference { + handle + __typename + } + __typename + } + availableDeliveryStrategies { + ... on CompleteDeliveryStrategy { + title + handle + custom + description + acceptsInstructions + phoneRequired + methodType + carrierName + brandedPromise { + logoUrl + name + __typename + } + deliveryStrategyBreakdown { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + discountRecurringCycleLimit + excludeFromDeliveryOptionPrice + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + minDeliveryDateTime + maxDeliveryDateTime + deliveryPromisePresentmentTitle { + short + long + __typename + } + displayCheckoutRedesign + estimatedTimeInTransit { + ... on IntIntervalConstraint { + lowerBound + upperBound + __typename + } + ... on IntValueConstraint { + value + __typename + } + __typename + } + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + amountAfterDiscounts { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + pickupLocation { + ... on PickupInStoreLocation { + address { + address1 + address2 + city + countryCode + phone + postalCode + zoneCode + __typename + } + instructions + name + __typename + } + ... on PickupPointLocation { + address { + address1 + address2 + address3 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + __typename + } + businessHours { + day + openingTime + closingTime + __typename + } + carrierCode + carrierName + handle + kind + name + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + taskId + __typename + } + ... on UnavailableTerms { + __typename + } +} +fragment SourceProvidedMerchandise on Merchandise { + ... on SourceProvidedMerchandise { + __typename + product { + id + title + productType + vendor + __typename + } + digest + variantId + optionalIdentifier + title + subtitle + taxable + giftCard + requiresShipping + price { + amount + currencyCode + __typename + } + deferredAmount { + amount + currencyCode + __typename + } + image { + altText + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + options { + name + value + __typename + } + properties { + ...MerchandiseProperties + __typename + } + taxCode + taxesIncluded + weight { + value + unit + __typename + } + sku + } + __typename +} +fragment ProductVariantMerchandiseDetails on ProductVariantMerchandise { + id + digest + variantId + title + subtitle + product { + id + vendor + productType + __typename + } + image { + altText + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + properties { + ...MerchandiseProperties + __typename + } + requiresShipping + options { + name + value + __typename + } + sellingPlan { + id + subscriptionDetails { + billingInterval + __typename + } + __typename + } + giftCard + __typename +} +fragment ContextualizedProductVariantMerchandiseDetails on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + subtitle + sku + price { + amount + currencyCode + __typename + } + product { + id + vendor + productType + __typename + } + image { + altText + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + properties { + ...MerchandiseProperties + __typename + } + requiresShipping + options { + name + value + __typename + } + sellingPlan { + name + id + digest + deliveriesPerBillingCycle + prepaid + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + giftCard + deferredAmount { + amount + currencyCode + __typename + } + __typename +} +fragment LineAllocationDetails on LineAllocation { + stableId + quantity + totalAmountBeforeReductions { + amount + currencyCode + __typename + } + totalAmountAfterDiscounts { + amount + currencyCode + __typename + } + totalAmountAfterLineDiscounts { + amount + currencyCode + __typename + } + checkoutPriceAfterDiscounts { + amount + currencyCode + __typename + } + checkoutPriceBeforeReductions { + amount + currencyCode + __typename + } + unitPrice { + price { + amount + currencyCode + __typename + } + measurement { + referenceUnit + referenceValue + __typename + } + __typename + } + allocations { + ... on LineComponentDiscountAllocation { + discountLine { + discount { + ...DiscountDetailsFragment + __typename + } + lineAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + allocation { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + amount { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename +} +fragment MerchandiseBundleLineComponent on MerchandiseBundleLineComponent { + __typename + stableId + merchandise { + ...SourceProvidedMerchandise + ...ProductVariantMerchandiseDetails + ...ContextualizedProductVariantMerchandiseDetails + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + quantity { + ... on ProposalMerchandiseQuantityByItem { + items { + ... on IntValueConstraint { + value + __typename + } + __typename + } + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + recurringTotal { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + lineAllocations { + ...LineAllocationDetails + __typename + } +} +fragment ProposalDetails on Proposal { + merchandiseDiscount { + ...ProposalDiscountFragment + __typename + } + deliveryDiscount { + ...ProposalDiscountFragment + __typename + } + delivery { + ... on FilledDeliveryTerms { + intermediateRates + progressiveRatesEstimatedTimeUntilCompletion + shippingRatesStatusToken + deliveryLines { + destinationAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on Geolocation { + country { + code + __typename + } + zone { + code + __typename + } + coordinates { + latitude + longitude + __typename + } + __typename + } + ... on PartialStreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + coordinates { + latitude + longitude + __typename + } + __typename + } + __typename + } + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + groupType + selectedDeliveryStrategy { + ... on CompleteDeliveryStrategy { + handle + __typename + } + __typename + } + availableDeliveryStrategies { + ... on CompleteDeliveryStrategy { + originLocation { + id + __typename + } + title + handle + custom + description + acceptsInstructions + phoneRequired + methodType + carrierName + brandedPromise { + logoUrl + name + __typename + } + deliveryStrategyBreakdown { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + discountRecurringCycleLimit + excludeFromDeliveryOptionPrice + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + subtitle + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + minDeliveryDateTime + maxDeliveryDateTime + deliveryPromisePresentmentTitle { + short + long + __typename + } + displayCheckoutRedesign + estimatedTimeInTransit { + ... on IntIntervalConstraint { + lowerBound + upperBound + __typename + } + ... on IntValueConstraint { + value + __typename + } + __typename + } + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + amountAfterDiscounts { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + pickupLocation { + ... on PickupInStoreLocation { + address { + address1 + address2 + city + countryCode + phone + postalCode + zoneCode + __typename + } + instructions + name + distanceFromBuyer { + unit + value + __typename + } + __typename + } + ... on PickupPointLocation { + address { + address1 + address2 + address3 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + __typename + } + businessHours { + day + openingTime + closingTime + __typename + } + carrierCode + carrierName + handle + kind + name + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + taskId + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + payment { + ... on FilledPaymentTerms { + availablePayments { + paymentMethod { + ... on AnyDirectPaymentMethod { + __typename + availablePaymentProviders { + paymentMethodIdentifier + name + brands + orderingIndex + displayName + __typename + } + } + ... on AnyOffsitePaymentMethod { + __typename + availableOffsiteProviders { + __typename + paymentMethodIdentifier + name + paymentBrands + orderingIndex + } + } + ... on DirectPaymentMethod { + __typename + paymentMethodIdentifier + } + ... on GiftCardPaymentMethod { + __typename + } + ... on AnyRedeemablePaymentMethod { + __typename + availableRedemptionSources + orderingIndex + } + ... on WalletsPlatformConfiguration { + name + configurationParams + __typename + } + ... on AnyWalletPaymentMethod { + availableWalletPaymentConfigs { + ... on PaypalWalletConfig { + __typename + name + merchantId + venmoEnabled + payflow + paymentIntent + paymentMethodIdentifier + orderingIndex + } + ... on ShopPayWalletConfig { + __typename + name + storefrontUrl + paymentMethodIdentifier + orderingIndex + } + ... on ShopifyInstallmentsWalletConfig { + __typename + name + availableLoanTypes + maxPrice { + amount + currencyCode + __typename + } + minPrice { + amount + currencyCode + __typename + } + supportedCountries + supportedCurrencies + giftCardsNotAllowed + subscriptionItemsNotAllowed + ineligibleTestModeCheckout + ineligibleLineItem + paymentMethodIdentifier + orderingIndex + } + ... on FacebookPayWalletConfig { + __typename + name + partnerId + partnerMerchantId + supportedContainers + acquirerCountryCode + mode + paymentMethodIdentifier + orderingIndex + } + ... on ApplePayWalletConfig { + __typename + name + supportedNetworks + walletAuthenticationToken + walletOrderTypeIdentifier + walletServiceUrl + paymentMethodIdentifier + orderingIndex + } + ... on GooglePayWalletConfig { + __typename + name + allowedAuthMethods + allowedCardNetworks + gateway + gatewayMerchantId + merchantId + authJwt + environment + paymentMethodIdentifier + orderingIndex + } + ... on AmazonPayClassicWalletConfig { + __typename + name + orderingIndex + } + __typename + } + __typename + } + ... on LocalPaymentMethodConfig { + __typename + paymentMethodIdentifier + name + displayName + additionalParameters { + ... on IdealBankSelectionParameterConfig { + __typename + label + options { + label + value + __typename + } + } + __typename + } + orderingIndex + } + ... on AnyPaymentOnDeliveryMethod { + __typename + additionalDetails + paymentInstructions + paymentMethodIdentifier + orderingIndex + displayName + } + ... on PaymentOnDeliveryMethod { + __typename + additionalDetails + paymentInstructions + paymentMethodIdentifier + } + ... on CustomPaymentMethod { + id + name + additionalDetails + paymentInstructions + __typename + } + ... on ManualPaymentMethodConfig { + id + name + additionalDetails + paymentInstructions + paymentMethodIdentifier + orderingIndex + __typename + } + ... on CustomPaymentMethodConfig { + id + name + additionalDetails + paymentInstructions + paymentMethodIdentifier + orderingIndex + __typename + } + ... on DeferredPaymentMethod { + orderingIndex + displayName + __typename + } + ... on NoopPaymentMethod { + __typename + } + ... on GiftCardPaymentMethod { + __typename + } + ... on CustomerCreditCardPaymentMethod { + __typename + expired + expiryMonth + expiryYear + name + orderingIndex + ...CustomerCreditCardPaymentMethodFragment + } + ... on PaypalBillingAgreementPaymentMethod { + __typename + orderingIndex + paypalAccountEmail + ...PaypalBillingAgreementPaymentMethodFragment + } + __typename + } + __typename + } + paymentLines { + ...PaymentLines + __typename + } + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + paymentFlexibilityPaymentTermsTemplate { + id + translatedName + dueDate + dueInDays + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + merchandise { + ... on FilledMerchandiseTerms { + taxesIncluded + merchandiseLines { + stableId + merchandise { + ...SourceProvidedMerchandise + ...ProductVariantMerchandiseDetails + ...ContextualizedProductVariantMerchandiseDetails + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + quantity { + ... on ProposalMerchandiseQuantityByItem { + items { + ... on IntValueConstraint { + value + __typename + } + __typename + } + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + recurringTotal { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + lineAllocations { + ...LineAllocationDetails + __typename + } + lineComponents { + ...MerchandiseBundleLineComponent + __typename + } + __typename + } + __typename + } + __typename + } + note { + customAttributes { + key + value + __typename + } + message + __typename + } + scriptFingerprint { + signature + signatureUuid + lineItemScriptChanges + paymentScriptChanges + shippingScriptChanges + __typename + } + transformerFingerprintV2 + buyerIdentity { + ... on FilledBuyerIdentityTerms { + buyerIdentity { + ... on GuestProfile { + presentmentCurrency + countryCode + __typename + } + ... on CustomerProfile { + id + presentmentCurrency + fullName + firstName + lastName + countryCode + email + imageUrl + acceptsMarketing + phone + billingAddresses { + id + default + address { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + __typename + } + shippingAddresses { + id + default + address { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + __typename + } + __typename + } + ... on BusinessCustomerProfile { + checkoutExperienceConfiguration { + availablePaymentOptions + checkoutCompletionTarget + editableShippingAddress + __typename + } + id + presentmentCurrency + fullName + firstName + lastName + acceptsMarketing + companyName + countryCode + email + phone + selectedCompanyLocation { + id + name + __typename + } + locationCount + billingAddress { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + shippingAddress { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + __typename + } + __typename + } + contactInfoV2 { + ... on EmailFormContents { + email + __typename + } + ... on SMSFormContents { + phoneNumber + __typename + } + __typename + } + marketingConsent { + ... on SMSMarketingConsent { + value + __typename + } + ... on EmailMarketingConsent { + value + __typename + } + __typename + } + shopPayOptInPhone + __typename + } + __typename + } + recurringTotals { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + subtotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + runningTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + total { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalTaxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + deferredTotal { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + subtotalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + taxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + dueAt + __typename + } + hasOnlyDeferredShipping + subtotalBeforeReductions { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + duty { + ... on FilledDutyTerms { + totalDutyAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + totalTaxAndDutyAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + tax { + ... on FilledTaxTerms { + totalTaxAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + totalTaxAndDutyAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + totalAmountIncludedInTarget { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + exemptions { + taxExemptionReason + targets { + ... on TargetAllLines { + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + tip { + tipSuggestions { + ... on TipSuggestion { + __typename + percentage + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + } + __typename + } + terms { + ... on FilledTipTerms { + tipLines { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + localizationExtension { + ... on LocalizationExtension { + fields { + ... on LocalizationExtensionField { + key + title + value + __typename + } + __typename + } + __typename + } + __typename + } + landedCostDetails { + incotermInformation { + incoterm + reason + __typename + } + __typename + } + nonNegotiableTerms { + signature + contents { + signature + targetTerms + targetLine { + allLines + index + __typename + } + attributes + __typename + } + __typename + } + optionalDuties { + buyerRefusesDuties + refuseDutiesPermitted + __typename + } + attribution { + attributions { + ... on AttributionItem { + ... on RetailAttributions { + deviceId + locationId + userId + __typename + } + ... on DraftOrderAttributions { + userIdentifier: userId + sourceName + locationIdentifier: locationId + __typename + } + __typename + } + __typename + } + __typename + } + managedByMarketsPro + captcha { + ... on Captcha { + provider + challenge + sitekey + token + __typename + } + ... on PendingTerms { + taskId + pollDelay + __typename + } + __typename + } + __typename +} +fragment CustomerCreditCardPaymentMethodFragment on CustomerCreditCardPaymentMethod { + cvvSessionId + paymentMethodIdentifier + token + displayLastDigits + brand + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename +} +fragment PaypalBillingAgreementPaymentMethodFragment on PaypalBillingAgreementPaymentMethod { + paymentMethodIdentifier + token + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename +} +fragment PaymentLines on PaymentLine { + specialInstructions + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + dueAt + paymentMethod { + ... on DirectPaymentMethod { + sessionId + paymentMethodIdentifier + creditCard { + ... on CreditCard { + brand + lastDigits + __typename + } + __typename + } + __typename + } + ... on GiftCardPaymentMethod { + code + balance { + amount + currencyCode + __typename + } + __typename + } + ... on RedeemablePaymentMethod { + redemptionSource + redemptionContent { + ... on ShopCashRedemptionContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + __typename + } + redemptionId + destinationAmount { + amount + currencyCode + __typename + } + sourceAmount { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + ... on WalletsPlatformPaymentMethod { + name + walletParams + __typename + } + ... on WalletPaymentMethod { + name + walletContent { + ... on ShopPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + sessionToken + paymentMethodIdentifier + __typename + } + ... on PaypalWalletContent { + paypalBillingAddress: billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + email + payerId + token + paymentMethodIdentifier + acceptedSubscriptionTerms + expiresAt + __typename + } + ... on ApplePayWalletContent { + data + signature + version + lastDigits + paymentMethodIdentifier + __typename + } + ... on GooglePayWalletContent { + signature + signedMessage + protocolVersion + paymentMethodIdentifier + __typename + } + ... on FacebookPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + containerData + containerId + mode + paymentMethodIdentifier + __typename + } + ... on ShopifyInstallmentsWalletContent { + autoPayEnabled + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + disclosureDetails { + evidence + id + type + __typename + } + installmentsToken + sessionToken + paymentMethodIdentifier + __typename + } + __typename + } + __typename + } + ... on LocalPaymentMethod { + paymentMethodIdentifier + name + additionalParameters { + ... on IdealPaymentMethodParameters { + bank + __typename + } + __typename + } + __typename + } + ... on PaymentOnDeliveryMethod { + additionalDetails + paymentInstructions + paymentMethodIdentifier + __typename + } + ... on OffsitePaymentMethod { + paymentMethodIdentifier + name + __typename + } + ... on CustomPaymentMethod { + id + name + additionalDetails + paymentInstructions + paymentMethodIdentifier + __typename + } + ... on ManualPaymentMethod { + id + name + paymentMethodIdentifier + __typename + } + ... on DeferredPaymentMethod { + orderingIndex + displayName + __typename + } + ... on CustomerCreditCardPaymentMethod { + ...CustomerCreditCardPaymentMethodFragment + __typename + } + ... on PaypalBillingAgreementPaymentMethod { + ...PaypalBillingAgreementPaymentMethodFragment + __typename + } + ... on NoopPaymentMethod { + __typename + } + __typename + } + __typename +} +fragment ReceiptDetails on Receipt { + ... on ProcessedReceipt { + id + token + classicThankYouPageUrl + orderIdentity { + buyerIdentifier + id + __typename + } + shopPayArtifact { + optIn { + vaultPhone + __typename + } + __typename + } + eligibleForMarketingOptIn + purchaseOrder { + ...ReceiptPurchaseOrder + __typename + } + orderCreationStatus { + __typename + } + paymentDetails { + creditCardBrand + creditCardLastFourDigits + __typename + } + shopAppLinksAndResources { + mobileUrl + qrCodeUrl + canTrackOrderUpdates + shopInstallmentsViewSchedules + shopInstallmentsMobileUrl + installmentsHighlightEligible + mobileUrlAttributionPayload + shopAppEligible + shopAppQrCodeKillswitch + shopPayOrder + buyerHasShopApp + buyerHasShopPay + orderUpdateOptions + __typename + } + postPurchasePageRequested + postPurchaseVaultedPaymentMethodStatus + __typename + } + ... on ProcessingReceipt { + id + pollDelay + __typename + } + ... on ActionRequiredReceipt { + id + action { + ... on CompletePaymentChallenge { + offsiteRedirect + url + __typename + } + __typename + } + __typename + } + ... on FailedReceipt { + id + processingError { + ... on InventoryClaimFailure { + __typename + } + ... on InventoryReservationFailure { + __typename + } + ... on OrderCreationFailure { + paymentsHaveBeenReverted + __typename + } + ... on OrderCreationSchedulingFailure { + __typename + } + ... on PaymentFailed { + code + messageUntranslated + __typename + } + ... on DiscountUsageLimitExceededFailure { + __typename + } + ... on CustomerPersistenceFailure { + __typename + } + __typename + } + __typename + } + __typename +} +fragment ReceiptPurchaseOrder on PurchaseOrder { + __typename + sessionToken + totalAmountToPay { + amount + currencyCode + __typename + } + delivery { + ... on PurchaseOrderDeliveryTerms { + deliveryLines { + __typename + deliveryStrategy { + handle + title + description + methodType + pickupLocation { + ... on PickupInStoreLocation { + name + address { + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + coordinates { + latitude + longitude + __typename + } + __typename + } + instructions + __typename + } + __typename + } + __typename + } + lineAmount { + amount + currencyCode + __typename + } + destinationAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + __typename + } + groupType + } + __typename + } + __typename + } + payment { + ... on PurchaseOrderPaymentTerms { + billingAddress { + __typename + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + } + paymentLines { + amount { + amount + currencyCode + __typename + } + postPaymentMessage + dueAt + paymentMethod { + ... on DirectPaymentMethod { + sessionId + paymentMethodIdentifier + vaultingAgreement + creditCard { + brand + lastDigits + __typename + } + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on CustomerCreditCardPaymentMethod { + brand + displayLastDigits + token + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename + } + ... on PurchaseOrderGiftCardPaymentMethod { + code + __typename + } + ... on WalletPaymentMethod { + name + walletContent { + ... on ShopPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + sessionToken + paymentMethodIdentifier + __typename + } + ... on PaypalWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + email + payerId + token + expiresAt + __typename + } + ... on ApplePayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + data + signature + version + __typename + } + ... on GooglePayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + signature + signedMessage + protocolVersion + __typename + } + ... on FacebookPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + containerData + containerId + mode + __typename + } + ... on ShopifyInstallmentsWalletContent { + autoPayEnabled + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + disclosureDetails { + evidence + id + type + __typename + } + installmentsToken + sessionToken + __typename + } + __typename + } + __typename + } + ... on LocalPaymentMethod { + paymentMethodIdentifier + name + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on PaymentOnDeliveryMethod { + additionalDetails + paymentInstructions + paymentMethodIdentifier + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on OffsitePaymentMethod { + paymentMethodIdentifier + name + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on ManualPaymentMethod { + additionalDetails + name + paymentInstructions + id + paymentMethodIdentifier + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on CustomPaymentMethod { + additionalDetails + name + paymentInstructions + id + paymentMethodIdentifier + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on DeferredPaymentMethod { + orderingIndex + displayName + __typename + } + ... on PaypalBillingAgreementPaymentMethod { + token + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + buyerIdentity { + ... on PurchaseOrderBuyerIdentityTerms { + contactMethod { + ... on PurchaseOrderEmailContactMethod { + email + __typename + } + ... on PurchaseOrderSMSContactMethod { + phoneNumber + __typename + } + __typename + } + marketingConsent { + ... on PurchaseOrderEmailContactMethod { + email + __typename + } + ... on PurchaseOrderSMSContactMethod { + phoneNumber + __typename + } + __typename + } + __typename + } + __typename + } + merchandise { + merchandiseLines { + merchandise { + ...ProductVariantSnapshotMerchandiseDetails + __typename + } + __typename + } + __typename + } + tax { + totalTaxAmount { + amount + currencyCode + __typename + } + __typename + } + discounts { + lines { + deliveryAllocations { + amount { + amount + currencyCode + __typename + } + index + __typename + } + __typename + } + __typename + } +} +fragment ProductVariantSnapshotMerchandiseDetails on ProductVariantSnapshot { + variantId + options { + name + value + __typename + } + productTitle + title + sellingPlan { + name + id + digest + deliveriesPerBillingCycle + prepaid + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + __typename +} diff --git a/rust_graphql_parser/rust_graphql_parser.gemspec b/rust_graphql_parser/rust_graphql_parser.gemspec new file mode 100644 index 0000000000..555ee8014a --- /dev/null +++ b/rust_graphql_parser/rust_graphql_parser.gemspec @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require_relative "lib/rust_graphql_parser/version" + +Gem::Specification.new do |spec| + spec.name = "rust_graphql_parser" + spec.version = RustGraphqlParser::VERSION + spec.authors = ["Filip Pacanowski"] + spec.email = ["fpacanowski@gmail.com"] + + spec.summary = "TOD: Write a short summary, because RubyGems requires one." + spec.description = "TOD: Write a longer description or delete this line." + spec.homepage = "https://example.com" + spec.license = "MIT" + spec.required_ruby_version = ">= 2.6.0" + spec.required_rubygems_version = ">= 3.3.11" + + spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'" + + spec.metadata["homepage_uri"] = spec.homepage + #spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." + #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." + + # Specify which files should be added to the gem when it is released. + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. + spec.files = Dir.chdir(__dir__) do + `git ls-files -z`.split("\x0").reject do |f| + (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)}) + end + end + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] + spec.extensions = ["ext/rust_graphql_parser/Cargo.toml"] + + # Uncomment to register a new dependency of your gem + # spec.add_dependency "example-gem", "~> 1.0" + + # For more information and examples about making a new gem, check out our + # guide at: https://bundler.io/guides/creating_gem.html +end diff --git a/rust_graphql_parser/sig/rust_graphql_parser.rbs b/rust_graphql_parser/sig/rust_graphql_parser.rbs new file mode 100644 index 0000000000..e079e3b51f --- /dev/null +++ b/rust_graphql_parser/sig/rust_graphql_parser.rbs @@ -0,0 +1,4 @@ +module RustGraphqlParser + VERSION: String + # See the writing guide of rbs: https://github.com/ruby/rbs#guides +end diff --git a/rust_graphql_parser/spec/data/big_query.graphql b/rust_graphql_parser/spec/data/big_query.graphql new file mode 100644 index 0000000000..147a1ecfc5 --- /dev/null +++ b/rust_graphql_parser/spec/data/big_query.graphql @@ -0,0 +1,3643 @@ +query NegotiateFromSession( + $sessionToken: String! + $checkpointData: String + $queueToken: String +) { + session(sessionInput: { sessionToken: $sessionToken }) { + context { + session { + ... on UnvalidatedParametersFact { + email + phone + shippingAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + zoneCode + postalCode: zip + __typename + } + billingAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + zoneCode + postalCode: zip + __typename + } + __typename + } + ... on PreviousNegotiationFact { + orderNumber + requiresShipping + __typename + } + __typename + } + policies { + payment { + ... on WalletsFact { + walletsAlreadyOffered + __typename + } + ... on PreviousPaymentsFact { + previouslyPaidTotal { + amount + currencyCode + __typename + } + updatedTotal { + amount + currencyCode + __typename + } + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + __typename + } + __typename + } + __typename + } + buyerIdentity { + ... on PreviousBuyerIdentityFact { + contactMethod { + email + phoneNumber + __typename + } + __typename + } + __typename + } + tax { + ... on PreviousTaxFact { + total { + amount + currencyCode + __typename + } + __typename + } + __typename + } + discount { + ... on PreviousDiscountFact { + orderLevelDiscounts { + label + amount { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + merchandise { + ... on PreviousMerchandiseFact { + lines { + title + variantTitle + quantity + sku + image { + id + altText + url + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + properties { + ...MerchandiseProperties + __typename + } + price { + amount + currencyCode + __typename + } + priceAfterDiscounts { + amount + currencyCode + __typename + } + appliedDiscounts { + label + amountDiscounted { + amount + currencyCode + __typename + } + __typename + } + quantityChange { + delta + type + __typename + } + __typename + } + __typename + } + __typename + } + tip { + ... on PreviousTipFact { + total { + amount + currencyCode + __typename + } + __typename + } + __typename + } + delivery { + ... on PreviousDeliveryFact { + total { + amount + currencyCode + __typename + } + deliveryAddress { + ... on StreetAddress { + address1 + address2 + city + company + coordinates { + latitude + longitude + __typename + } + countryCode + firstName + label + lastName + name + phone + postalCode + zoneCode + __typename + } + ... on Geolocation { + coordinates { + latitude + longitude + __typename + } + country { + code + name + __typename + } + zone { + code + name + __typename + } + __typename + } + ... on PartialStreetAddress { + address1 + address2 + address3 + city + company + countryCode + firstName + lastName + name + phone + postalCode + zoneCode + coordinates { + latitude + longitude + __typename + } + __typename + } + __typename + } + pickupAddress { + address1 + countryCode + coordinates { + latitude + longitude + __typename + } + address2 + city + postalCode + zoneCode + phone + __typename + } + pickupAddressName + lines { + title + lineAmount { + amount + currencyCode + __typename + } + appliedDiscounts { + label + allocationValue { + ... on PercentageValue { + percentage + __typename + } + ... on FixedAmountValue { + fixedAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + appliesOnEachItem + __typename + } + __typename + } + amountDiscounted { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + sessionType + sourceId + sourceVersion + checkoutSessionIdentifier + storefrontAnalyticsStartedOrderEventId + negotiate( + input: { checkpointData: $checkpointData, queueToken: $queueToken } + ) { + result { + ... on NegotiationResultAvailable { + queueToken + buyerProposal { + ...BuyerProposalDetails + __typename + } + sellerProposal { + ...ProposalDetails + __typename + } + __typename + } + ... on CheckpointDenied { + redirectUrl + __typename + } + ... on Throttled { + pollAfter + queueToken + pollUrl + buyerProposal { + ...BuyerProposalDetails + __typename + } + __typename + } + ... on NegotiationResultFailed { + __typename + } + ... on SubmittedForCompletion { + __typename + receipt { + ...ReceiptDetails + __typename + } + } + __typename + } + errors { + code + localizedMessage + nonLocalizedMessage + localizedMessageHtml + ... on RemoveTermViolation { + target + __typename + } + ... on AcceptNewTermViolation { + target + __typename + } + ... on ConfirmChangeViolation { + from + to + __typename + } + ... on UnprocessableTermViolation { + target + __typename + } + ... on UnresolvableTermViolation { + target + __typename + } + ... on InputValidationError { + field + __typename + } + ... on GenericError { + __typename + } + __typename + } + __typename + } + __typename + } +} +fragment MerchandiseProperties on MerchandiseProperty { + name + value { + ... on MerchandisePropertyValueString { + string: value + __typename + } + ... on MerchandisePropertyValueInt { + int: value + __typename + } + ... on MerchandisePropertyValueFloat { + float: value + __typename + } + ... on MerchandisePropertyValueBoolean { + boolean: value + __typename + } + ... on MerchandisePropertyValueJson { + json: value + __typename + } + __typename + } + visible + __typename +} +fragment BuyerProposalDetails on Proposal { + merchandiseDiscount { + ...ProposalDiscountFragment + __typename + } + deliveryDiscount { + ...ProposalDiscountFragment + __typename + } + delivery { + ...ProposalDeliveryFragment + __typename + } + merchandise { + ... on FilledMerchandiseTerms { + taxesIncluded + merchandiseLines { + stableId + merchandise { + ...SourceProvidedMerchandise + ...ProductVariantMerchandiseDetails + ...ContextualizedProductVariantMerchandiseDetails + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + quantity { + ... on ProposalMerchandiseQuantityByItem { + items { + ... on IntValueConstraint { + value + __typename + } + __typename + } + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + recurringTotal { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + lineAllocations { + ...LineAllocationDetails + __typename + } + lineComponents { + ...MerchandiseBundleLineComponent + __typename + } + __typename + } + __typename + } + __typename + } + runningTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + total { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalTaxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + deferredTotal { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + subtotalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + taxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + dueAt + __typename + } + hasOnlyDeferredShipping + subtotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + attribution { + attributions { + ... on AttributionItem { + ... on RetailAttributions { + deviceId + locationId + userId + __typename + } + ... on DraftOrderAttributions { + userIdentifier: userId + sourceName + locationIdentifier: locationId + __typename + } + __typename + } + __typename + } + __typename + } + __typename +} +fragment ProposalDiscountFragment on DiscountTermsV2 { + __typename + ... on FilledDiscountTerms { + lines { + ...DiscountLineDetailsFragment + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + taskId + __typename + } + ... on UnavailableTerms { + __typename + } +} +fragment DiscountLineDetailsFragment on DiscountLine { + allocations { + ... on DiscountAllocatedAllocationSet { + __typename + allocations { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + target { + index + targetType + stableId + __typename + } + __typename + } + } + __typename + } + discount { + ...DiscountDetailsFragment + __typename + } + lineAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename +} +fragment DiscountDetailsFragment on Discount { + ... on CustomDiscount { + title + presentationLevel + signature + signatureUuid + type + value { + ... on PercentageValue { + percentage + __typename + } + ... on FixedAmountValue { + appliesOnEachItem + fixedAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + ... on CodeDiscount { + title + code + presentationLevel + __typename + } + ... on DiscountCodeTrigger { + code + __typename + } + ... on AutomaticDiscount { + presentationLevel + title + __typename + } + __typename +} +fragment ProposalDeliveryFragment on DeliveryTerms { + __typename + ... on FilledDeliveryTerms { + intermediateRates + progressiveRatesEstimatedTimeUntilCompletion + shippingRatesStatusToken + deliveryLines { + destinationAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on Geolocation { + country { + code + __typename + } + zone { + code + __typename + } + coordinates { + latitude + longitude + __typename + } + __typename + } + ... on PartialStreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + coordinates { + latitude + longitude + __typename + } + __typename + } + __typename + } + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + groupType + selectedDeliveryStrategy { + ... on CompleteDeliveryStrategy { + handle + __typename + } + ... on DeliveryStrategyReference { + handle + __typename + } + __typename + } + availableDeliveryStrategies { + ... on CompleteDeliveryStrategy { + title + handle + custom + description + acceptsInstructions + phoneRequired + methodType + carrierName + brandedPromise { + logoUrl + name + __typename + } + deliveryStrategyBreakdown { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + discountRecurringCycleLimit + excludeFromDeliveryOptionPrice + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + minDeliveryDateTime + maxDeliveryDateTime + deliveryPromisePresentmentTitle { + short + long + __typename + } + displayCheckoutRedesign + estimatedTimeInTransit { + ... on IntIntervalConstraint { + lowerBound + upperBound + __typename + } + ... on IntValueConstraint { + value + __typename + } + __typename + } + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + amountAfterDiscounts { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + pickupLocation { + ... on PickupInStoreLocation { + address { + address1 + address2 + city + countryCode + phone + postalCode + zoneCode + __typename + } + instructions + name + __typename + } + ... on PickupPointLocation { + address { + address1 + address2 + address3 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + __typename + } + businessHours { + day + openingTime + closingTime + __typename + } + carrierCode + carrierName + handle + kind + name + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + taskId + __typename + } + ... on UnavailableTerms { + __typename + } +} +fragment SourceProvidedMerchandise on Merchandise { + ... on SourceProvidedMerchandise { + __typename + product { + id + title + productType + vendor + __typename + } + digest + variantId + optionalIdentifier + title + subtitle + taxable + giftCard + requiresShipping + price { + amount + currencyCode + __typename + } + deferredAmount { + amount + currencyCode + __typename + } + image { + altText + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + options { + name + value + __typename + } + properties { + ...MerchandiseProperties + __typename + } + taxCode + taxesIncluded + weight { + value + unit + __typename + } + sku + } + __typename +} +fragment ProductVariantMerchandiseDetails on ProductVariantMerchandise { + id + digest + variantId + title + subtitle + product { + id + vendor + productType + __typename + } + image { + altText + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + properties { + ...MerchandiseProperties + __typename + } + requiresShipping + options { + name + value + __typename + } + sellingPlan { + id + subscriptionDetails { + billingInterval + __typename + } + __typename + } + giftCard + __typename +} +fragment ContextualizedProductVariantMerchandiseDetails on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + subtitle + sku + price { + amount + currencyCode + __typename + } + product { + id + vendor + productType + __typename + } + image { + altText + one: transformedSrc(maxWidth: 64, maxHeight: 64) + two: transformedSrc(maxWidth: 128, maxHeight: 128) + four: transformedSrc(maxWidth: 256, maxHeight: 256) + __typename + } + properties { + ...MerchandiseProperties + __typename + } + requiresShipping + options { + name + value + __typename + } + sellingPlan { + name + id + digest + deliveriesPerBillingCycle + prepaid + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + giftCard + deferredAmount { + amount + currencyCode + __typename + } + __typename +} +fragment LineAllocationDetails on LineAllocation { + stableId + quantity + totalAmountBeforeReductions { + amount + currencyCode + __typename + } + totalAmountAfterDiscounts { + amount + currencyCode + __typename + } + totalAmountAfterLineDiscounts { + amount + currencyCode + __typename + } + checkoutPriceAfterDiscounts { + amount + currencyCode + __typename + } + checkoutPriceBeforeReductions { + amount + currencyCode + __typename + } + unitPrice { + price { + amount + currencyCode + __typename + } + measurement { + referenceUnit + referenceValue + __typename + } + __typename + } + allocations { + ... on LineComponentDiscountAllocation { + discountLine { + discount { + ...DiscountDetailsFragment + __typename + } + lineAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + allocation { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + amount { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename +} +fragment MerchandiseBundleLineComponent on MerchandiseBundleLineComponent { + __typename + stableId + merchandise { + ...SourceProvidedMerchandise + ...ProductVariantMerchandiseDetails + ...ContextualizedProductVariantMerchandiseDetails + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + quantity { + ... on ProposalMerchandiseQuantityByItem { + items { + ... on IntValueConstraint { + value + __typename + } + __typename + } + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + recurringTotal { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + lineAllocations { + ...LineAllocationDetails + __typename + } +} +fragment ProposalDetails on Proposal { + merchandiseDiscount { + ...ProposalDiscountFragment + __typename + } + deliveryDiscount { + ...ProposalDiscountFragment + __typename + } + delivery { + ... on FilledDeliveryTerms { + intermediateRates + progressiveRatesEstimatedTimeUntilCompletion + shippingRatesStatusToken + deliveryLines { + destinationAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on Geolocation { + country { + code + __typename + } + zone { + code + __typename + } + coordinates { + latitude + longitude + __typename + } + __typename + } + ... on PartialStreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + coordinates { + latitude + longitude + __typename + } + __typename + } + __typename + } + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + groupType + selectedDeliveryStrategy { + ... on CompleteDeliveryStrategy { + handle + __typename + } + __typename + } + availableDeliveryStrategies { + ... on CompleteDeliveryStrategy { + originLocation { + id + __typename + } + title + handle + custom + description + acceptsInstructions + phoneRequired + methodType + carrierName + brandedPromise { + logoUrl + name + __typename + } + deliveryStrategyBreakdown { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + discountRecurringCycleLimit + excludeFromDeliveryOptionPrice + targetMerchandise { + ... on FilledMerchandiseLineTargetCollection { + lines { + stableId + merchandise { + ...SourceProvidedMerchandise + ... on ProductVariantMerchandise { + id + digest + variantId + title + requiresShipping + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on ContextualizedProductVariantMerchandise { + id + digest + variantId + title + subtitle + requiresShipping + sellingPlan { + id + digest + name + prepaid + deliveriesPerBillingCycle + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + properties { + ...MerchandiseProperties + __typename + } + __typename + } + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + minDeliveryDateTime + maxDeliveryDateTime + deliveryPromisePresentmentTitle { + short + long + __typename + } + displayCheckoutRedesign + estimatedTimeInTransit { + ... on IntIntervalConstraint { + lowerBound + upperBound + __typename + } + ... on IntValueConstraint { + value + __typename + } + __typename + } + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + amountAfterDiscounts { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + pickupLocation { + ... on PickupInStoreLocation { + address { + address1 + address2 + city + countryCode + phone + postalCode + zoneCode + __typename + } + instructions + name + distanceFromBuyer { + unit + value + __typename + } + __typename + } + ... on PickupPointLocation { + address { + address1 + address2 + address3 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + __typename + } + businessHours { + day + openingTime + closingTime + __typename + } + carrierCode + carrierName + handle + kind + name + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + taskId + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + payment { + ... on FilledPaymentTerms { + availablePayments { + paymentMethod { + ... on AnyDirectPaymentMethod { + __typename + availablePaymentProviders { + paymentMethodIdentifier + name + brands + orderingIndex + displayName + __typename + } + } + ... on AnyOffsitePaymentMethod { + __typename + availableOffsiteProviders { + __typename + paymentMethodIdentifier + name + paymentBrands + orderingIndex + } + } + ... on DirectPaymentMethod { + __typename + paymentMethodIdentifier + } + ... on GiftCardPaymentMethod { + __typename + } + ... on AnyRedeemablePaymentMethod { + __typename + availableRedemptionSources + orderingIndex + } + ... on WalletsPlatformConfiguration { + name + configurationParams + __typename + } + ... on AnyWalletPaymentMethod { + availableWalletPaymentConfigs { + ... on PaypalWalletConfig { + __typename + name + merchantId + venmoEnabled + payflow + paymentIntent + paymentMethodIdentifier + orderingIndex + } + ... on ShopPayWalletConfig { + __typename + name + storefrontUrl + paymentMethodIdentifier + orderingIndex + } + ... on ShopifyInstallmentsWalletConfig { + __typename + name + availableLoanTypes + maxPrice { + amount + currencyCode + __typename + } + minPrice { + amount + currencyCode + __typename + } + supportedCountries + supportedCurrencies + giftCardsNotAllowed + subscriptionItemsNotAllowed + ineligibleTestModeCheckout + ineligibleLineItem + paymentMethodIdentifier + orderingIndex + } + ... on FacebookPayWalletConfig { + __typename + name + partnerId + partnerMerchantId + supportedContainers + acquirerCountryCode + mode + paymentMethodIdentifier + orderingIndex + } + ... on ApplePayWalletConfig { + __typename + name + supportedNetworks + walletAuthenticationToken + walletOrderTypeIdentifier + walletServiceUrl + paymentMethodIdentifier + orderingIndex + } + ... on GooglePayWalletConfig { + __typename + name + allowedAuthMethods + allowedCardNetworks + gateway + gatewayMerchantId + merchantId + authJwt + environment + paymentMethodIdentifier + orderingIndex + } + ... on AmazonPayClassicWalletConfig { + __typename + name + orderingIndex + } + __typename + } + __typename + } + ... on LocalPaymentMethodConfig { + __typename + paymentMethodIdentifier + name + displayName + additionalParameters { + ... on IdealBankSelectionParameterConfig { + __typename + label + options { + label + value + __typename + } + } + __typename + } + orderingIndex + } + ... on AnyPaymentOnDeliveryMethod { + __typename + additionalDetails + paymentInstructions + paymentMethodIdentifier + orderingIndex + displayName + } + ... on PaymentOnDeliveryMethod { + __typename + additionalDetails + paymentInstructions + paymentMethodIdentifier + } + ... on CustomPaymentMethod { + id + name + additionalDetails + paymentInstructions + __typename + } + ... on ManualPaymentMethodConfig { + id + name + additionalDetails + paymentInstructions + paymentMethodIdentifier + orderingIndex + __typename + } + ... on CustomPaymentMethodConfig { + id + name + additionalDetails + paymentInstructions + paymentMethodIdentifier + orderingIndex + __typename + } + ... on DeferredPaymentMethod { + orderingIndex + displayName + __typename + } + ... on NoopPaymentMethod { + __typename + } + ... on GiftCardPaymentMethod { + __typename + } + ... on CustomerCreditCardPaymentMethod { + __typename + expired + expiryMonth + expiryYear + name + orderingIndex + ...CustomerCreditCardPaymentMethodFragment + } + ... on PaypalBillingAgreementPaymentMethod { + __typename + orderingIndex + paypalAccountEmail + ...PaypalBillingAgreementPaymentMethodFragment + } + __typename + } + __typename + } + paymentLines { + ...PaymentLines + __typename + } + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + paymentFlexibilityPaymentTermsTemplate { + id + translatedName + dueDate + dueInDays + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + merchandise { + ... on FilledMerchandiseTerms { + taxesIncluded + merchandiseLines { + stableId + merchandise { + ...SourceProvidedMerchandise + ...ProductVariantMerchandiseDetails + ...ContextualizedProductVariantMerchandiseDetails + ... on MissingProductVariantMerchandise { + id + digest + variantId + __typename + } + __typename + } + quantity { + ... on ProposalMerchandiseQuantityByItem { + items { + ... on IntValueConstraint { + value + __typename + } + __typename + } + __typename + } + __typename + } + totalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + recurringTotal { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + lineAllocations { + ...LineAllocationDetails + __typename + } + lineComponents { + ...MerchandiseBundleLineComponent + __typename + } + __typename + } + __typename + } + __typename + } + note { + customAttributes { + key + value + __typename + } + message + __typename + } + scriptFingerprint { + signature + signatureUuid + lineItemScriptChanges + paymentScriptChanges + shippingScriptChanges + __typename + } + transformerFingerprintV2 + buyerIdentity { + ... on FilledBuyerIdentityTerms { + buyerIdentity { + ... on GuestProfile { + presentmentCurrency + countryCode + __typename + } + ... on CustomerProfile { + id + presentmentCurrency + fullName + firstName + lastName + countryCode + email + imageUrl + acceptsMarketing + phone + billingAddresses { + id + default + address { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + __typename + } + shippingAddresses { + id + default + address { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + __typename + } + __typename + } + ... on BusinessCustomerProfile { + checkoutExperienceConfiguration { + availablePaymentOptions + checkoutCompletionTarget + editableShippingAddress + __typename + } + id + presentmentCurrency + fullName + firstName + lastName + acceptsMarketing + companyName + countryCode + email + phone + selectedCompanyLocation { + id + name + __typename + } + locationCount + billingAddress { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + shippingAddress { + firstName + lastName + address1 + address2 + phone + postalCode + city + company + zoneCode + countryCode + label + __typename + } + __typename + } + __typename + } + contactInfoV2 { + ... on EmailFormContents { + email + __typename + } + ... on SMSFormContents { + phoneNumber + __typename + } + __typename + } + marketingConsent { + ... on SMSMarketingConsent { + value + __typename + } + ... on EmailMarketingConsent { + value + __typename + } + __typename + } + shopPayOptInPhone + __typename + } + __typename + } + recurringTotals { + title + interval + intervalCount + recurringPrice { + amount + currencyCode + __typename + } + fixedPrice { + amount + currencyCode + __typename + } + fixedPriceCount + __typename + } + subtotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + runningTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + total { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalBeforeTaxesAndShipping { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotalTaxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + checkoutTotal { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + deferredTotal { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + subtotalAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + taxes { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + dueAt + __typename + } + hasOnlyDeferredShipping + subtotalBeforeReductions { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + duty { + ... on FilledDutyTerms { + totalDutyAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + totalTaxAndDutyAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + tax { + ... on FilledTaxTerms { + totalTaxAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + totalTaxAndDutyAmount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + totalAmountIncludedInTarget { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + exemptions { + taxExemptionReason + targets { + ... on TargetAllLines { + __typename + } + __typename + } + __typename + } + __typename + } + ... on PendingTerms { + pollDelay + __typename + } + ... on UnavailableTerms { + __typename + } + __typename + } + tip { + tipSuggestions { + ... on TipSuggestion { + __typename + percentage + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + } + __typename + } + terms { + ... on FilledTipTerms { + tipLines { + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + localizationExtension { + ... on LocalizationExtension { + fields { + ... on LocalizationExtensionField { + key + title + value + __typename + } + __typename + } + __typename + } + __typename + } + landedCostDetails { + incotermInformation { + incoterm + reason + __typename + } + __typename + } + nonNegotiableTerms { + signature + contents { + signature + targetTerms + targetLine { + allLines + index + __typename + } + attributes + __typename + } + __typename + } + optionalDuties { + buyerRefusesDuties + refuseDutiesPermitted + __typename + } + attribution { + attributions { + ... on AttributionItem { + ... on RetailAttributions { + deviceId + locationId + userId + __typename + } + ... on DraftOrderAttributions { + userIdentifier: userId + sourceName + locationIdentifier: locationId + __typename + } + __typename + } + __typename + } + __typename + } + managedByMarketsPro + captcha { + ... on Captcha { + provider + challenge + sitekey + token + __typename + } + ... on PendingTerms { + taskId + pollDelay + __typename + } + __typename + } + __typename +} +fragment CustomerCreditCardPaymentMethodFragment on CustomerCreditCardPaymentMethod { + cvvSessionId + paymentMethodIdentifier + token + displayLastDigits + brand + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename +} +fragment PaypalBillingAgreementPaymentMethodFragment on PaypalBillingAgreementPaymentMethod { + paymentMethodIdentifier + token + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename +} +fragment PaymentLines on PaymentLine { + specialInstructions + amount { + ... on MoneyValueConstraint { + value { + amount + currencyCode + __typename + } + __typename + } + __typename + } + dueAt + paymentMethod { + ... on DirectPaymentMethod { + sessionId + paymentMethodIdentifier + creditCard { + ... on CreditCard { + brand + lastDigits + __typename + } + __typename + } + __typename + } + ... on GiftCardPaymentMethod { + code + balance { + amount + currencyCode + __typename + } + __typename + } + ... on RedeemablePaymentMethod { + redemptionSource + redemptionContent { + ... on ShopCashRedemptionContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + __typename + } + redemptionId + destinationAmount { + amount + currencyCode + __typename + } + sourceAmount { + amount + currencyCode + __typename + } + __typename + } + __typename + } + __typename + } + ... on WalletsPlatformPaymentMethod { + name + walletParams + __typename + } + ... on WalletPaymentMethod { + name + walletContent { + ... on ShopPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + sessionToken + paymentMethodIdentifier + __typename + } + ... on PaypalWalletContent { + paypalBillingAddress: billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + email + payerId + token + paymentMethodIdentifier + acceptedSubscriptionTerms + expiresAt + __typename + } + ... on ApplePayWalletContent { + data + signature + version + lastDigits + paymentMethodIdentifier + __typename + } + ... on GooglePayWalletContent { + signature + signedMessage + protocolVersion + paymentMethodIdentifier + __typename + } + ... on FacebookPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + containerData + containerId + mode + paymentMethodIdentifier + __typename + } + ... on ShopifyInstallmentsWalletContent { + autoPayEnabled + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + disclosureDetails { + evidence + id + type + __typename + } + installmentsToken + sessionToken + paymentMethodIdentifier + __typename + } + __typename + } + __typename + } + ... on LocalPaymentMethod { + paymentMethodIdentifier + name + additionalParameters { + ... on IdealPaymentMethodParameters { + bank + __typename + } + __typename + } + __typename + } + ... on PaymentOnDeliveryMethod { + additionalDetails + paymentInstructions + paymentMethodIdentifier + __typename + } + ... on OffsitePaymentMethod { + paymentMethodIdentifier + name + __typename + } + ... on CustomPaymentMethod { + id + name + additionalDetails + paymentInstructions + paymentMethodIdentifier + __typename + } + ... on ManualPaymentMethod { + id + name + paymentMethodIdentifier + __typename + } + ... on DeferredPaymentMethod { + orderingIndex + displayName + __typename + } + ... on CustomerCreditCardPaymentMethod { + ...CustomerCreditCardPaymentMethodFragment + __typename + } + ... on PaypalBillingAgreementPaymentMethod { + ...PaypalBillingAgreementPaymentMethodFragment + __typename + } + ... on NoopPaymentMethod { + __typename + } + __typename + } + __typename +} +fragment ReceiptDetails on Receipt { + ... on ProcessedReceipt { + id + token + classicThankYouPageUrl + orderIdentity { + buyerIdentifier + id + __typename + } + shopPayArtifact { + optIn { + vaultPhone + __typename + } + __typename + } + eligibleForMarketingOptIn + purchaseOrder { + ...ReceiptPurchaseOrder + __typename + } + orderCreationStatus { + __typename + } + paymentDetails { + creditCardBrand + creditCardLastFourDigits + __typename + } + shopAppLinksAndResources { + mobileUrl + qrCodeUrl + canTrackOrderUpdates + shopInstallmentsViewSchedules + shopInstallmentsMobileUrl + installmentsHighlightEligible + mobileUrlAttributionPayload + shopAppEligible + shopAppQrCodeKillswitch + shopPayOrder + buyerHasShopApp + buyerHasShopPay + orderUpdateOptions + __typename + } + postPurchasePageRequested + postPurchaseVaultedPaymentMethodStatus + __typename + } + ... on ProcessingReceipt { + id + pollDelay + __typename + } + ... on ActionRequiredReceipt { + id + action { + ... on CompletePaymentChallenge { + offsiteRedirect + url + __typename + } + __typename + } + __typename + } + ... on FailedReceipt { + id + processingError { + ... on InventoryClaimFailure { + __typename + } + ... on InventoryReservationFailure { + __typename + } + ... on OrderCreationFailure { + paymentsHaveBeenReverted + __typename + } + ... on OrderCreationSchedulingFailure { + __typename + } + ... on PaymentFailed { + code + messageUntranslated + __typename + } + ... on DiscountUsageLimitExceededFailure { + __typename + } + ... on CustomerPersistenceFailure { + __typename + } + __typename + } + __typename + } + __typename +} +fragment ReceiptPurchaseOrder on PurchaseOrder { + __typename + sessionToken + totalAmountToPay { + amount + currencyCode + __typename + } + delivery { + ... on PurchaseOrderDeliveryTerms { + deliveryLines { + __typename + deliveryStrategy { + handle + title + description + methodType + pickupLocation { + ... on PickupInStoreLocation { + name + address { + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + coordinates { + latitude + longitude + __typename + } + __typename + } + instructions + __typename + } + __typename + } + __typename + } + lineAmount { + amount + currencyCode + __typename + } + destinationAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + __typename + } + groupType + } + __typename + } + __typename + } + payment { + ... on PurchaseOrderPaymentTerms { + billingAddress { + __typename + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + } + paymentLines { + amount { + amount + currencyCode + __typename + } + postPaymentMessage + dueAt + paymentMethod { + ... on DirectPaymentMethod { + sessionId + paymentMethodIdentifier + vaultingAgreement + creditCard { + brand + lastDigits + __typename + } + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on CustomerCreditCardPaymentMethod { + brand + displayLastDigits + token + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename + } + ... on PurchaseOrderGiftCardPaymentMethod { + code + __typename + } + ... on WalletPaymentMethod { + name + walletContent { + ... on ShopPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + sessionToken + paymentMethodIdentifier + __typename + } + ... on PaypalWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + email + payerId + token + expiresAt + __typename + } + ... on ApplePayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + data + signature + version + __typename + } + ... on GooglePayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + signature + signedMessage + protocolVersion + __typename + } + ... on FacebookPayWalletContent { + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + containerData + containerId + mode + __typename + } + ... on ShopifyInstallmentsWalletContent { + autoPayEnabled + billingAddress { + ... on StreetAddress { + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + disclosureDetails { + evidence + id + type + __typename + } + installmentsToken + sessionToken + __typename + } + __typename + } + __typename + } + ... on LocalPaymentMethod { + paymentMethodIdentifier + name + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on PaymentOnDeliveryMethod { + additionalDetails + paymentInstructions + paymentMethodIdentifier + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on OffsitePaymentMethod { + paymentMethodIdentifier + name + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on ManualPaymentMethod { + additionalDetails + name + paymentInstructions + id + paymentMethodIdentifier + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on CustomPaymentMethod { + additionalDetails + name + paymentInstructions + id + paymentMethodIdentifier + billingAddress { + ... on StreetAddress { + name + firstName + lastName + company + address1 + address2 + city + countryCode + zoneCode + postalCode + coordinates { + latitude + longitude + __typename + } + phone + __typename + } + ... on InvalidBillingAddress { + __typename + } + __typename + } + __typename + } + ... on DeferredPaymentMethod { + orderingIndex + displayName + __typename + } + ... on PaypalBillingAgreementPaymentMethod { + token + billingAddress { + ... on StreetAddress { + address1 + address2 + city + company + countryCode + firstName + lastName + phone + postalCode + zoneCode + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + __typename + } + buyerIdentity { + ... on PurchaseOrderBuyerIdentityTerms { + contactMethod { + ... on PurchaseOrderEmailContactMethod { + email + __typename + } + ... on PurchaseOrderSMSContactMethod { + phoneNumber + __typename + } + __typename + } + marketingConsent { + ... on PurchaseOrderEmailContactMethod { + email + __typename + } + ... on PurchaseOrderSMSContactMethod { + phoneNumber + __typename + } + __typename + } + __typename + } + __typename + } + merchandise { + merchandiseLines { + merchandise { + ...ProductVariantSnapshotMerchandiseDetails + __typename + } + __typename + } + __typename + } + tax { + totalTaxAmount { + amount + currencyCode + __typename + } + __typename + } + discounts { + lines { + deliveryAllocations { + amount { + amount + currencyCode + __typename + } + index + __typename + } + __typename + } + __typename + } +} +fragment ProductVariantSnapshotMerchandiseDetails on ProductVariantSnapshot { + variantId + options { + name + value + __typename + } + productTitle + title + sellingPlan { + name + id + digest + deliveriesPerBillingCycle + prepaid + subscriptionDetails { + billingInterval + billingIntervalCount + billingMaxCycles + deliveryInterval + deliveryIntervalCount + __typename + } + __typename + } + __typename +} diff --git a/rust_graphql_parser/spec/data/directive_args.graphql b/rust_graphql_parser/spec/data/directive_args.graphql new file mode 100644 index 0000000000..5937cce5e5 --- /dev/null +++ b/rust_graphql_parser/spec/data/directive_args.graphql @@ -0,0 +1,3 @@ +query { + node @dir(a: 1, b: "2", c: true, d: false, e: null) +} diff --git a/rust_graphql_parser/spec/data/directive_args_multiline.graphql b/rust_graphql_parser/spec/data/directive_args_multiline.graphql new file mode 100644 index 0000000000..664028acfa --- /dev/null +++ b/rust_graphql_parser/spec/data/directive_args_multiline.graphql @@ -0,0 +1,9 @@ +query { + node @dir( + a: 1, + b: "2", + c: true, + d: false, + e: null + ) +} diff --git a/rust_graphql_parser/spec/data/field_arguments.graphql b/rust_graphql_parser/spec/data/field_arguments.graphql new file mode 100644 index 0000000000..ea6bb2991b --- /dev/null +++ b/rust_graphql_parser/spec/data/field_arguments.graphql @@ -0,0 +1,13 @@ +query { + foo( + first: $var, + second: 1, + third: 3.14, + fourth: "abc", + fifth: true, + sixth: null, + seventh: NONE, + eight: ["foo", "bar", null, NULL], + ninth: [[1,2], [3,4]], + ) +} \ No newline at end of file diff --git a/rust_graphql_parser/spec/data/fragment.graphql b/rust_graphql_parser/spec/data/fragment.graphql new file mode 100644 index 0000000000..4627f06d26 --- /dev/null +++ b/rust_graphql_parser/spec/data/fragment.graphql @@ -0,0 +1,3 @@ +fragment frag on Friend { + node +} diff --git a/rust_graphql_parser/spec/data/fragment_spread.graphql b/rust_graphql_parser/spec/data/fragment_spread.graphql new file mode 100644 index 0000000000..940fb624e9 --- /dev/null +++ b/rust_graphql_parser/spec/data/fragment_spread.graphql @@ -0,0 +1,6 @@ +query { + node { + id + ...something + } +} diff --git a/rust_graphql_parser/spec/data/inline_fragment.graphql b/rust_graphql_parser/spec/data/inline_fragment.graphql new file mode 100644 index 0000000000..f09fb52917 --- /dev/null +++ b/rust_graphql_parser/spec/data/inline_fragment.graphql @@ -0,0 +1,8 @@ +query { + node { + id + ... on User { + name + } + } +} diff --git a/rust_graphql_parser/spec/data/inline_fragment_dir.graphql b/rust_graphql_parser/spec/data/inline_fragment_dir.graphql new file mode 100644 index 0000000000..4f9db15b2c --- /dev/null +++ b/rust_graphql_parser/spec/data/inline_fragment_dir.graphql @@ -0,0 +1,8 @@ +query { + node { + id + ... on User @defer { + name + } + } +} diff --git a/rust_graphql_parser/spec/data/kitchen-sink.graphql b/rust_graphql_parser/spec/data/kitchen-sink.graphql new file mode 100644 index 0000000000..6fcf394bf3 --- /dev/null +++ b/rust_graphql_parser/spec/data/kitchen-sink.graphql @@ -0,0 +1,59 @@ +# Copyright (c) 2015-present, Facebook, Inc. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +query queryName($foo: ComplexType, $site: Site = MOBILE) { + whoever123is: node(id: [123, 456]) { + id , + ... on User @defer { + field2 { + id , + alias: field1(first:10, after:$foo,) @include(if: $foo) { + id, + ...frag + } + } + } + ... @skip(unless: $foo) { + id + } + ... { + id + } + } +} + +mutation likeStory { + like(story: 123) @defer { + story { + id + } + } +} + +subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) { + storyLikeSubscribe(input: $input) { + story { + likers { + count + } + likeSentence { + text + } + } + } +} + +fragment frag on Friend { + foo(size: $size, bar: $b, obj: {key: "value", block: """ + + block string uses \""" + + """}) +} + +{ + unnamed(truthy: true, falsey: false, nullish: null), + query +} diff --git a/rust_graphql_parser/spec/data/kitchen-sink_canonical.graphql b/rust_graphql_parser/spec/data/kitchen-sink_canonical.graphql new file mode 100644 index 0000000000..726ed42ff2 --- /dev/null +++ b/rust_graphql_parser/spec/data/kitchen-sink_canonical.graphql @@ -0,0 +1,54 @@ +query queryName($foo: ComplexType, $site: Site = MOBILE) { + whoever123is: node(id: [123, 456]) { + id + ... on User @defer { + field2 { + id + alias: field1(first: 10, after: $foo) @include(if: $foo) { + id + ...frag + } + } + } + ... @skip(unless: $foo) { + id + } + ... { + id + } + } +} + +mutation likeStory { + like(story: 123) @defer { + story { + id + } + } +} + +subscription StoryLikeSubscription($input: StoryLikeSubscribeInput) { + storyLikeSubscribe(input: $input) { + story { + likers { + count + } + likeSentence { + text + } + } + } +} + +fragment frag on Friend { + foo(size: $size, bar: $b, obj: {block: """ + + block string uses \""" + + """, key: "value"}) +} + +{ + unnamed(truthy: true, falsey: false, nullish: null) + query +} diff --git a/rust_graphql_parser/spec/data/minimal.graphql b/rust_graphql_parser/spec/data/minimal.graphql new file mode 100644 index 0000000000..e0d57a0388 --- /dev/null +++ b/rust_graphql_parser/spec/data/minimal.graphql @@ -0,0 +1,3 @@ +{ + a +} diff --git a/rust_graphql_parser/spec/data/minimal_mutation.graphql b/rust_graphql_parser/spec/data/minimal_mutation.graphql new file mode 100644 index 0000000000..bf0c4eb545 --- /dev/null +++ b/rust_graphql_parser/spec/data/minimal_mutation.graphql @@ -0,0 +1,3 @@ +mutation { + notify +} diff --git a/rust_graphql_parser/spec/data/minimal_query.graphql b/rust_graphql_parser/spec/data/minimal_query.graphql new file mode 100644 index 0000000000..5017efe9f9 --- /dev/null +++ b/rust_graphql_parser/spec/data/minimal_query.graphql @@ -0,0 +1,3 @@ +query { + node +} diff --git a/rust_graphql_parser/spec/data/mutation_directive.graphql b/rust_graphql_parser/spec/data/mutation_directive.graphql new file mode 100644 index 0000000000..21b6321627 --- /dev/null +++ b/rust_graphql_parser/spec/data/mutation_directive.graphql @@ -0,0 +1,3 @@ +mutation @directive { + node +} diff --git a/rust_graphql_parser/spec/data/mutation_nameless_vars.graphql b/rust_graphql_parser/spec/data/mutation_nameless_vars.graphql new file mode 100644 index 0000000000..bb77ebcddb --- /dev/null +++ b/rust_graphql_parser/spec/data/mutation_nameless_vars.graphql @@ -0,0 +1,4 @@ +mutation($first: Int, $second: Int) { + field1(first: $first) + field2(second: $second) +} diff --git a/rust_graphql_parser/spec/data/named_query.graphql b/rust_graphql_parser/spec/data/named_query.graphql new file mode 100644 index 0000000000..f3f48a2c8d --- /dev/null +++ b/rust_graphql_parser/spec/data/named_query.graphql @@ -0,0 +1,3 @@ +query Foo { + field +} diff --git a/rust_graphql_parser/spec/data/nested_field_arguments.graphql b/rust_graphql_parser/spec/data/nested_field_arguments.graphql new file mode 100644 index 0000000000..4cd7d4fa57 --- /dev/null +++ b/rust_graphql_parser/spec/data/nested_field_arguments.graphql @@ -0,0 +1,10 @@ +query { + field( + nested: { + first: 7, + secondNested: { + third: "abc", + } + } + ) +} \ No newline at end of file diff --git a/rust_graphql_parser/spec/data/nested_selection.graphql b/rust_graphql_parser/spec/data/nested_selection.graphql new file mode 100644 index 0000000000..defe356cd6 --- /dev/null +++ b/rust_graphql_parser/spec/data/nested_selection.graphql @@ -0,0 +1,5 @@ +query { + node { + id + } +} diff --git a/rust_graphql_parser/spec/data/query_aliases.graphql b/rust_graphql_parser/spec/data/query_aliases.graphql new file mode 100644 index 0000000000..5069783ce7 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_aliases.graphql @@ -0,0 +1,3 @@ +query { + an_alias: node +} diff --git a/rust_graphql_parser/spec/data/query_arguments.graphql b/rust_graphql_parser/spec/data/query_arguments.graphql new file mode 100644 index 0000000000..681c39962b --- /dev/null +++ b/rust_graphql_parser/spec/data/query_arguments.graphql @@ -0,0 +1,3 @@ +query { + node(id: 1) +} diff --git a/rust_graphql_parser/spec/data/query_arguments_multiline.graphql b/rust_graphql_parser/spec/data/query_arguments_multiline.graphql new file mode 100644 index 0000000000..1447e76af8 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_arguments_multiline.graphql @@ -0,0 +1,9 @@ +query { + node( + id: 1 + ) + node( + id: 1, + one: 3 + ) +} diff --git a/rust_graphql_parser/spec/data/query_array_argument_multiline.graphql b/rust_graphql_parser/spec/data/query_array_argument_multiline.graphql new file mode 100644 index 0000000000..caa614414b --- /dev/null +++ b/rust_graphql_parser/spec/data/query_array_argument_multiline.graphql @@ -0,0 +1,9 @@ +query { + node( + id: [ + 5, + 6, + 7 + ] + ) +} diff --git a/rust_graphql_parser/spec/data/query_directive.graphql b/rust_graphql_parser/spec/data/query_directive.graphql new file mode 100644 index 0000000000..e649dc17e2 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_directive.graphql @@ -0,0 +1,3 @@ +query @directive { + node +} diff --git a/rust_graphql_parser/spec/data/query_list_argument.graphql b/rust_graphql_parser/spec/data/query_list_argument.graphql new file mode 100644 index 0000000000..096e0c1545 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_list_argument.graphql @@ -0,0 +1,3 @@ +query { + node(id: 1, list: [123, 456]) +} diff --git a/rust_graphql_parser/spec/data/query_nameless_vars.graphql b/rust_graphql_parser/spec/data/query_nameless_vars.graphql new file mode 100644 index 0000000000..813603d666 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_nameless_vars.graphql @@ -0,0 +1,4 @@ +query($first: Int, $second: Int) { + field1(first: $first) + field2(second: $second) +} diff --git a/rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields.graphql b/rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields.graphql new file mode 100644 index 0000000000..0891748d07 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields.graphql @@ -0,0 +1,16 @@ +,,,,,,,,,,,,,,,,, +query ,,,,,,, ($houseId: String!, $streetNumber: Int!) ,,,,,,,,,,,, { # comment +,,,,,,,,,,,,,,,,,, # commas should be fine + house(id: $houseId) { + id + name + lat + lng + } + street(number: $streetNumber) { # this is a comment + id + } + houseStreet(id: $houseId, number: $streetNumber) { + id + } +} diff --git a/rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields_canonical.graphql b/rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields_canonical.graphql new file mode 100644 index 0000000000..edf96c9705 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_nameless_vars_multiple_fields_canonical.graphql @@ -0,0 +1,14 @@ +query($houseId: String!, $streetNumber: Int!) { + house(id: $houseId) { + id + name + lat + lng + } + street(number: $streetNumber) { + id + } + houseStreet(id: $houseId, number: $streetNumber) { + id + } +} diff --git a/rust_graphql_parser/spec/data/query_object_argument.graphql b/rust_graphql_parser/spec/data/query_object_argument.graphql new file mode 100644 index 0000000000..05379b053b --- /dev/null +++ b/rust_graphql_parser/spec/data/query_object_argument.graphql @@ -0,0 +1,3 @@ +query { + node(id: 1, obj: {key1: 123, key2: 456}) +} diff --git a/rust_graphql_parser/spec/data/query_object_argument_multiline.graphql b/rust_graphql_parser/spec/data/query_object_argument_multiline.graphql new file mode 100644 index 0000000000..b6a55c8834 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_object_argument_multiline.graphql @@ -0,0 +1,9 @@ +query { + node( + id: 1, + obj: { + key1: 123, + key2: 456 + } + ) +} diff --git a/rust_graphql_parser/spec/data/query_var_default_float.graphql b/rust_graphql_parser/spec/data/query_var_default_float.graphql new file mode 100644 index 0000000000..d3e03ff502 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_var_default_float.graphql @@ -0,0 +1,3 @@ +query Foo($site: Float = 0.5) { + field +} diff --git a/rust_graphql_parser/spec/data/query_var_default_list.graphql b/rust_graphql_parser/spec/data/query_var_default_list.graphql new file mode 100644 index 0000000000..7b6a0af8a1 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_var_default_list.graphql @@ -0,0 +1,3 @@ +query Foo($site: [Int] = [123, 456]) { + field +} diff --git a/rust_graphql_parser/spec/data/query_var_default_object.graphql b/rust_graphql_parser/spec/data/query_var_default_object.graphql new file mode 100644 index 0000000000..69c6d4da89 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_var_default_object.graphql @@ -0,0 +1,3 @@ +query Foo($site: Site = {url: null}) { + field +} diff --git a/rust_graphql_parser/spec/data/query_var_default_string.graphql b/rust_graphql_parser/spec/data/query_var_default_string.graphql new file mode 100644 index 0000000000..64bc387049 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_var_default_string.graphql @@ -0,0 +1,3 @@ +query Foo($site: String = "string") { + field +} diff --git a/rust_graphql_parser/spec/data/query_var_defaults.graphql b/rust_graphql_parser/spec/data/query_var_defaults.graphql new file mode 100644 index 0000000000..91b11f8ff7 --- /dev/null +++ b/rust_graphql_parser/spec/data/query_var_defaults.graphql @@ -0,0 +1,3 @@ +query Foo($site: Site = MOBILE) { + field +} diff --git a/rust_graphql_parser/spec/data/query_vars.graphql b/rust_graphql_parser/spec/data/query_vars.graphql new file mode 100644 index 0000000000..cb43b2b1ef --- /dev/null +++ b/rust_graphql_parser/spec/data/query_vars.graphql @@ -0,0 +1,3 @@ +query Foo($arg: SomeType) { + field +} diff --git a/rust_graphql_parser/spec/data/string_literal.graphql b/rust_graphql_parser/spec/data/string_literal.graphql new file mode 100644 index 0000000000..160efb44dd --- /dev/null +++ b/rust_graphql_parser/spec/data/string_literal.graphql @@ -0,0 +1,3 @@ +query { + node(id: "hello") +} diff --git a/rust_graphql_parser/spec/data/subscription_directive.graphql b/rust_graphql_parser/spec/data/subscription_directive.graphql new file mode 100644 index 0000000000..c643e53bfc --- /dev/null +++ b/rust_graphql_parser/spec/data/subscription_directive.graphql @@ -0,0 +1,3 @@ +subscription @directive { + node +} diff --git a/rust_graphql_parser/spec/data/triple_quoted_literal.graphql b/rust_graphql_parser/spec/data/triple_quoted_literal.graphql new file mode 100644 index 0000000000..1690ef97dc --- /dev/null +++ b/rust_graphql_parser/spec/data/triple_quoted_literal.graphql @@ -0,0 +1,6 @@ +query { + node(id: """ + Hello, + world! + """) +} diff --git a/rust_graphql_parser/spec/data/types.graphql b/rust_graphql_parser/spec/data/types.graphql new file mode 100644 index 0000000000..2b24cb3a66 --- /dev/null +++ b/rust_graphql_parser/spec/data/types.graphql @@ -0,0 +1,10 @@ +query MyQuery( + $first: Type, + $second: [Type], + $third: Type!, + $fourth: [Type!], + $fifth: [Type]!, + $sixth: [Type!]!, +) { + field +} \ No newline at end of file diff --git a/rust_graphql_parser/spec/integration_spec.rb b/rust_graphql_parser/spec/integration_spec.rb new file mode 100644 index 0000000000..22cffc423d --- /dev/null +++ b/rust_graphql_parser/spec/integration_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' +require 'rust_graphql_parser' +require 'benchmark/ips' +require 'graphql/c_parser' + +describe 'Parsing' do + %w[ + big_query + directive_args + directive_args_multiline + field_arguments + fragment + fragment_spread + inline_fragment + inline_fragment_dir + minimal + minimal_mutation + minimal_query + mutation_directive + mutation_nameless_vars + named_query + nested_field_arguments + nested_selection + query_aliases + query_arguments + query_arguments_multiline + query_array_argument_multiline + query_directive + query_list_argument + query_nameless_vars + query_nameless_vars_multiple_fields + query_nameless_vars_multiple_fields_canonical + query_object_argument + query_object_argument_multiline + query_var_default_float + query_var_default_list + query_var_default_object + query_var_default_string + query_var_defaults + query_vars + string_literal + subscription_directive + types + ].each do |filename| + specify filename do + source = File.read("spec/data/#{filename}.graphql") + ruby_ast = GraphQL.parse(source) + # pp ruby_ast + rust_ast = RustGraphqlParser.parse(source) + # pp rust_ast + expect(rust_ast).to eq(ruby_ast) + end + end +end diff --git a/rust_graphql_parser/spec/spec_helper.rb b/rust_graphql_parser/spec/spec_helper.rb new file mode 100644 index 0000000000..8a931a01df --- /dev/null +++ b/rust_graphql_parser/spec/spec_helper.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require "rust_graphql_parser" + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + # config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end +end