solidus_graphql_api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +93 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.gitignore +20 -0
  6. data/.rspec +2 -0
  7. data/.rubocop.yml +62 -0
  8. data/CHANGELOG.md +0 -0
  9. data/CONTRIBUTING.md +57 -0
  10. data/Gemfile +33 -0
  11. data/LICENSE +26 -0
  12. data/LICENSE.md +26 -0
  13. data/README.md +245 -0
  14. data/Rakefile +43 -0
  15. data/app/controllers/spree/graphql_controller.rb +49 -0
  16. data/bin/console +17 -0
  17. data/bin/rails +9 -0
  18. data/bin/rails-engine +16 -0
  19. data/bin/rails-sandbox +18 -0
  20. data/bin/rake +8 -0
  21. data/bin/sandbox +84 -0
  22. data/bin/setup +8 -0
  23. data/config/locales/en.yml +6 -0
  24. data/config/routes.rb +5 -0
  25. data/lib/generators/solidus_graphql_api/install/install_generator.rb +8 -0
  26. data/lib/solidus_graphql_api.rb +11 -0
  27. data/lib/solidus_graphql_api/batch_loader.rb +114 -0
  28. data/lib/solidus_graphql_api/batch_loader/belongs_to.rb +30 -0
  29. data/lib/solidus_graphql_api/batch_loader/has_many.rb +24 -0
  30. data/lib/solidus_graphql_api/batch_loader/has_many_through.rb +42 -0
  31. data/lib/solidus_graphql_api/batch_loader/has_one.rb +22 -0
  32. data/lib/solidus_graphql_api/configuration.rb +19 -0
  33. data/lib/solidus_graphql_api/context.rb +76 -0
  34. data/lib/solidus_graphql_api/engine.rb +25 -0
  35. data/lib/solidus_graphql_api/factories.rb +11 -0
  36. data/lib/solidus_graphql_api/factories/address_factory.rb +8 -0
  37. data/lib/solidus_graphql_api/factories/country_factory.rb +12 -0
  38. data/lib/solidus_graphql_api/factories/store_factory.rb +16 -0
  39. data/lib/solidus_graphql_api/factories/taxonomy_factory.rb +26 -0
  40. data/lib/solidus_graphql_api/mutations/.keep +0 -0
  41. data/lib/solidus_graphql_api/mutations/base_mutation.rb +45 -0
  42. data/lib/solidus_graphql_api/mutations/checkout/add_addresses_to_checkout.rb +41 -0
  43. data/lib/solidus_graphql_api/mutations/checkout/add_payment_to_checkout.rb +45 -0
  44. data/lib/solidus_graphql_api/mutations/checkout/add_to_cart.rb +30 -0
  45. data/lib/solidus_graphql_api/mutations/checkout/advance_checkout.rb +27 -0
  46. data/lib/solidus_graphql_api/mutations/checkout/apply_coupon_code.rb +32 -0
  47. data/lib/solidus_graphql_api/mutations/checkout/complete_checkout.rb +31 -0
  48. data/lib/solidus_graphql_api/mutations/checkout/create_order.rb +27 -0
  49. data/lib/solidus_graphql_api/mutations/checkout/empty_cart.rb +29 -0
  50. data/lib/solidus_graphql_api/mutations/checkout/next_checkout_state.rb +27 -0
  51. data/lib/solidus_graphql_api/mutations/checkout/remove_from_cart.rb +33 -0
  52. data/lib/solidus_graphql_api/mutations/checkout/select_shipping_rate.rb +40 -0
  53. data/lib/solidus_graphql_api/mutations/checkout/set_order_email.rb +29 -0
  54. data/lib/solidus_graphql_api/mutations/checkout/update_cart_quantity.rb +41 -0
  55. data/lib/solidus_graphql_api/mutations/user/mark_default_address.rb +31 -0
  56. data/lib/solidus_graphql_api/mutations/user/remove_from_address_book.rb +25 -0
  57. data/lib/solidus_graphql_api/mutations/user/save_in_address_book.rb +30 -0
  58. data/lib/solidus_graphql_api/queries/address/country_query.rb +19 -0
  59. data/lib/solidus_graphql_api/queries/address/state_query.rb +19 -0
  60. data/lib/solidus_graphql_api/queries/completed_orders_query.rb +19 -0
  61. data/lib/solidus_graphql_api/queries/countries_query.rb +11 -0
  62. data/lib/solidus_graphql_api/queries/country/states_query.rb +19 -0
  63. data/lib/solidus_graphql_api/queries/line_item/variant_query.rb +19 -0
  64. data/lib/solidus_graphql_api/queries/option_type/option_values_query.rb +19 -0
  65. data/lib/solidus_graphql_api/queries/order/adjustments_query.rb +19 -0
  66. data/lib/solidus_graphql_api/queries/order/billing_address_query.rb +19 -0
  67. data/lib/solidus_graphql_api/queries/order/line_items_query.rb +19 -0
  68. data/lib/solidus_graphql_api/queries/order/payments_query.rb +19 -0
  69. data/lib/solidus_graphql_api/queries/order/shipments_query.rb +19 -0
  70. data/lib/solidus_graphql_api/queries/order/shipping_address_query.rb +19 -0
  71. data/lib/solidus_graphql_api/queries/product/master_variant_query.rb +19 -0
  72. data/lib/solidus_graphql_api/queries/product/option_types_query.rb +19 -0
  73. data/lib/solidus_graphql_api/queries/product/product_properties_query.rb +19 -0
  74. data/lib/solidus_graphql_api/queries/product/variants_query.rb +19 -0
  75. data/lib/solidus_graphql_api/queries/product_by_slug_query.rb +11 -0
  76. data/lib/solidus_graphql_api/queries/product_property/property_query.rb +19 -0
  77. data/lib/solidus_graphql_api/queries/products_query.rb +29 -0
  78. data/lib/solidus_graphql_api/queries/shipment/shipping_rates_query.rb +19 -0
  79. data/lib/solidus_graphql_api/queries/taxon/children_query.rb +19 -0
  80. data/lib/solidus_graphql_api/queries/taxon/parent_taxon_query.rb +19 -0
  81. data/lib/solidus_graphql_api/queries/taxonomies_query.rb +11 -0
  82. data/lib/solidus_graphql_api/queries/taxonomy/root_taxon_query.rb +19 -0
  83. data/lib/solidus_graphql_api/queries/taxonomy/taxons_query.rb +19 -0
  84. data/lib/solidus_graphql_api/queries/variant/default_price_query.rb +19 -0
  85. data/lib/solidus_graphql_api/queries/variant/images_query.rb +19 -0
  86. data/lib/solidus_graphql_api/queries/variant/option_values_query.rb +19 -0
  87. data/lib/solidus_graphql_api/queries/variant/prices_query.rb +19 -0
  88. data/lib/solidus_graphql_api/schema.rb +40 -0
  89. data/lib/solidus_graphql_api/types/.keep +0 -0
  90. data/lib/solidus_graphql_api/types/address.rb +32 -0
  91. data/lib/solidus_graphql_api/types/base/argument.rb +10 -0
  92. data/lib/solidus_graphql_api/types/base/enum.rb +10 -0
  93. data/lib/solidus_graphql_api/types/base/field.rb +13 -0
  94. data/lib/solidus_graphql_api/types/base/input_object.rb +10 -0
  95. data/lib/solidus_graphql_api/types/base/interface.rb +11 -0
  96. data/lib/solidus_graphql_api/types/base/object.rb +25 -0
  97. data/lib/solidus_graphql_api/types/base/relay_node.rb +13 -0
  98. data/lib/solidus_graphql_api/types/base/scalar.rb +10 -0
  99. data/lib/solidus_graphql_api/types/base/union.rb +10 -0
  100. data/lib/solidus_graphql_api/types/country.rb +23 -0
  101. data/lib/solidus_graphql_api/types/credit_card.rb +18 -0
  102. data/lib/solidus_graphql_api/types/currency.rb +14 -0
  103. data/lib/solidus_graphql_api/types/image.rb +27 -0
  104. data/lib/solidus_graphql_api/types/input_objects/address_input.rb +24 -0
  105. data/lib/solidus_graphql_api/types/input_objects/products_query_input.rb +15 -0
  106. data/lib/solidus_graphql_api/types/interfaces/adjustment.rb +32 -0
  107. data/lib/solidus_graphql_api/types/interfaces/payment_source.rb +19 -0
  108. data/lib/solidus_graphql_api/types/json.rb +63 -0
  109. data/lib/solidus_graphql_api/types/line_item.rb +26 -0
  110. data/lib/solidus_graphql_api/types/manifest_item.rb +12 -0
  111. data/lib/solidus_graphql_api/types/mutation.rb +24 -0
  112. data/lib/solidus_graphql_api/types/option_type.rb +22 -0
  113. data/lib/solidus_graphql_api/types/option_value.rb +15 -0
  114. data/lib/solidus_graphql_api/types/order.rb +63 -0
  115. data/lib/solidus_graphql_api/types/payment.rb +15 -0
  116. data/lib/solidus_graphql_api/types/payment_method.rb +15 -0
  117. data/lib/solidus_graphql_api/types/price.rb +21 -0
  118. data/lib/solidus_graphql_api/types/product.rb +38 -0
  119. data/lib/solidus_graphql_api/types/product_property.rb +19 -0
  120. data/lib/solidus_graphql_api/types/promotion_adjustment.rb +17 -0
  121. data/lib/solidus_graphql_api/types/property.rb +14 -0
  122. data/lib/solidus_graphql_api/types/query.rb +84 -0
  123. data/lib/solidus_graphql_api/types/shipment.rb +23 -0
  124. data/lib/solidus_graphql_api/types/shipping_rate.rb +15 -0
  125. data/lib/solidus_graphql_api/types/state.rb +14 -0
  126. data/lib/solidus_graphql_api/types/store.rb +27 -0
  127. data/lib/solidus_graphql_api/types/tax_adjustment.rb +11 -0
  128. data/lib/solidus_graphql_api/types/taxon.rb +33 -0
  129. data/lib/solidus_graphql_api/types/taxonomy.rb +23 -0
  130. data/lib/solidus_graphql_api/types/user.rb +23 -0
  131. data/lib/solidus_graphql_api/types/user_error.rb +12 -0
  132. data/lib/solidus_graphql_api/types/variant.rb +39 -0
  133. data/lib/solidus_graphql_api/types/wallet_payment_source.rb +14 -0
  134. data/lib/solidus_graphql_api/version.rb +5 -0
  135. data/schema.graphql +2070 -0
  136. data/solidus_graphql_api.gemspec +43 -0
  137. data/spec/integration/mutations/add_to_cart_spec.rb +67 -0
  138. data/spec/integration/mutations/checkout/add_addresses_to_checkout_spec.rb +115 -0
  139. data/spec/integration/mutations/checkout/add_payment_to_checkout_spec.rb +87 -0
  140. data/spec/integration/mutations/checkout/advance_checkout_spec.rb +71 -0
  141. data/spec/integration/mutations/checkout/apply_coupon_code_spec.rb +76 -0
  142. data/spec/integration/mutations/checkout/complete_checkout_spec.rb +56 -0
  143. data/spec/integration/mutations/checkout/next_checkout_state_spec.rb +69 -0
  144. data/spec/integration/mutations/checkout/select_shipping_rate_spec.rb +89 -0
  145. data/spec/integration/mutations/create_order_spec.rb +55 -0
  146. data/spec/integration/mutations/empty_cart_spec.rb +58 -0
  147. data/spec/integration/mutations/mark_default_address_spec.rb +33 -0
  148. data/spec/integration/mutations/remove_from_address_book_spec.rb +48 -0
  149. data/spec/integration/mutations/remove_from_cart_spec.rb +65 -0
  150. data/spec/integration/mutations/save_in_address_book_spec.rb +90 -0
  151. data/spec/integration/mutations/set_order_email_spec.rb +61 -0
  152. data/spec/integration/mutations/update_cart_quantity_spec.rb +68 -0
  153. data/spec/integration/queries/completed_orders_spec.rb +158 -0
  154. data/spec/integration/queries/countries_spec.rb +18 -0
  155. data/spec/integration/queries/current_order_spec.rb +15 -0
  156. data/spec/integration/queries/current_store_spec.rb +15 -0
  157. data/spec/integration/queries/current_user_spec.rb +43 -0
  158. data/spec/integration/queries/product_by_slug_spec.rb +42 -0
  159. data/spec/integration/queries/products_spec.rb +40 -0
  160. data/spec/integration/queries/taxonomies_spec.rb +22 -0
  161. data/spec/lib/solidus_graphql_api/batch_loader/belongs_to_spec.rb +67 -0
  162. data/spec/lib/solidus_graphql_api/batch_loader/has_many_spec.rb +38 -0
  163. data/spec/lib/solidus_graphql_api/batch_loader/has_many_through_spec.rb +47 -0
  164. data/spec/lib/solidus_graphql_api/batch_loader/has_one_spec.rb +38 -0
  165. data/spec/lib/solidus_graphql_api/context_spec.rb +236 -0
  166. data/spec/lib/solidus_graphql_api/queries/address/country_query_spec.rb +13 -0
  167. data/spec/lib/solidus_graphql_api/queries/address/state_query_spec.rb +13 -0
  168. data/spec/lib/solidus_graphql_api/queries/completed_orders_query_spec.rb +12 -0
  169. data/spec/lib/solidus_graphql_api/queries/countries_query_spec.rb +11 -0
  170. data/spec/lib/solidus_graphql_api/queries/country/states_query_spec.rb +11 -0
  171. data/spec/lib/solidus_graphql_api/queries/line_item/variant_query_spec.rb +9 -0
  172. data/spec/lib/solidus_graphql_api/queries/option_type/option_values_query_spec.rb +11 -0
  173. data/spec/lib/solidus_graphql_api/queries/order/adjustments_query_spec.rb +10 -0
  174. data/spec/lib/solidus_graphql_api/queries/order/billing_address_query_spec.rb +11 -0
  175. data/spec/lib/solidus_graphql_api/queries/order/line_items_query_spec.rb +9 -0
  176. data/spec/lib/solidus_graphql_api/queries/order/payments_query_spec.rb +9 -0
  177. data/spec/lib/solidus_graphql_api/queries/order/shipments_query_spec.rb +18 -0
  178. data/spec/lib/solidus_graphql_api/queries/order/shipping_address_query_spec.rb +11 -0
  179. data/spec/lib/solidus_graphql_api/queries/product/master_variant_query_spec.rb +11 -0
  180. data/spec/lib/solidus_graphql_api/queries/product/option_types_query_spec.rb +11 -0
  181. data/spec/lib/solidus_graphql_api/queries/product/product_properties_query_spec.rb +11 -0
  182. data/spec/lib/solidus_graphql_api/queries/product/variants_query_spec.rb +11 -0
  183. data/spec/lib/solidus_graphql_api/queries/product_by_slug_query_spec.rb +13 -0
  184. data/spec/lib/solidus_graphql_api/queries/product_property/property_query_spec.rb +11 -0
  185. data/spec/lib/solidus_graphql_api/queries/products_query_spec.rb +49 -0
  186. data/spec/lib/solidus_graphql_api/queries/shipment/shipping_rates_query_spec.rb +18 -0
  187. data/spec/lib/solidus_graphql_api/queries/taxon/children_query_spec.rb +11 -0
  188. data/spec/lib/solidus_graphql_api/queries/taxon/parent_taxon_query_spec.rb +10 -0
  189. data/spec/lib/solidus_graphql_api/queries/taxonomies_query_spec.rb +11 -0
  190. data/spec/lib/solidus_graphql_api/queries/taxonomy/root_taxon_query_spec.rb +10 -0
  191. data/spec/lib/solidus_graphql_api/queries/taxonomy/taxons_query_spec.rb +11 -0
  192. data/spec/lib/solidus_graphql_api/queries/variant/default_price_query_spec.rb +9 -0
  193. data/spec/lib/solidus_graphql_api/queries/variant/images_query_spec.rb +11 -0
  194. data/spec/lib/solidus_graphql_api/queries/variant/option_values_query_spec.rb +11 -0
  195. data/spec/lib/solidus_graphql_api/queries/variant/prices_query_spec.rb +13 -0
  196. data/spec/lib/solidus_graphql_api/schema_spec.rb +80 -0
  197. data/spec/lib/solidus_graphql_api/types/base/object_spec.rb +29 -0
  198. data/spec/lib/solidus_graphql_api/types/json_spec.rb +115 -0
  199. data/spec/lib/solidus_graphql_api/types/option_type_spec.rb +7 -0
  200. data/spec/lib/solidus_graphql_api/types/product_property_spec.rb +22 -0
  201. data/spec/lib/solidus_graphql_api/types/product_spec.rb +56 -0
  202. data/spec/lib/solidus_graphql_api/types/query_spec.rb +33 -0
  203. data/spec/lib/solidus_graphql_api/types/variant_spec.rb +58 -0
  204. data/spec/requests/spree/graphql_controller_spec.rb +17 -0
  205. data/spec/spec_helper.rb +62 -0
  206. data/spec/support/expected_schema.graphql +2070 -0
  207. data/spec/support/graphql/mutations/add_addresses_to_checkout.gql +19 -0
  208. data/spec/support/graphql/mutations/add_payment_to_checkout.gql +13 -0
  209. data/spec/support/graphql/mutations/add_to_cart.gql +21 -0
  210. data/spec/support/graphql/mutations/advance_checkout.gql +13 -0
  211. data/spec/support/graphql/mutations/apply_coupon_code.gql +13 -0
  212. data/spec/support/graphql/mutations/complete_checkout.gql +13 -0
  213. data/spec/support/graphql/mutations/create_order.gql +11 -0
  214. data/spec/support/graphql/mutations/empty_cart.gql +17 -0
  215. data/spec/support/graphql/mutations/mark_default_address.gql +9 -0
  216. data/spec/support/graphql/mutations/next_checkout_state.gql +13 -0
  217. data/spec/support/graphql/mutations/remove_from_address_book.gql +14 -0
  218. data/spec/support/graphql/mutations/remove_from_cart.gql +17 -0
  219. data/spec/support/graphql/mutations/save_in_address_book.gql +57 -0
  220. data/spec/support/graphql/mutations/select_shipping_rate.gql +23 -0
  221. data/spec/support/graphql/mutations/set_order_email.gql +13 -0
  222. data/spec/support/graphql/mutations/update_cart_quantity.gql +18 -0
  223. data/spec/support/graphql/queries/completed_orders.gql +29 -0
  224. data/spec/support/graphql/queries/completed_orders/adjustments.gql +24 -0
  225. data/spec/support/graphql/queries/completed_orders/available_payment_methods.gql +15 -0
  226. data/spec/support/graphql/queries/completed_orders/billing_address.gql +40 -0
  227. data/spec/support/graphql/queries/completed_orders/line_items.gql +23 -0
  228. data/spec/support/graphql/queries/completed_orders/payments.gql +23 -0
  229. data/spec/support/graphql/queries/completed_orders/shipping_address.gql +40 -0
  230. data/spec/support/graphql/queries/countries.gql +24 -0
  231. data/spec/support/graphql/queries/current_order.gql +32 -0
  232. data/spec/support/graphql/queries/current_store.gql +24 -0
  233. data/spec/support/graphql/queries/current_user.gql +197 -0
  234. data/spec/support/graphql/queries/product_by_slug.gql +106 -0
  235. data/spec/support/graphql/queries/products.gql +7 -0
  236. data/spec/support/graphql/queries/taxonomies.gql +81 -0
  237. data/spec/support/graphql/responses/completed_orders.json.erb +58 -0
  238. data/spec/support/graphql/responses/completed_orders/adjustments.json.erb +34 -0
  239. data/spec/support/graphql/responses/completed_orders/available_payment_methods.json.erb +29 -0
  240. data/spec/support/graphql/responses/completed_orders/billing_address.json.erb +78 -0
  241. data/spec/support/graphql/responses/completed_orders/line_items.json.erb +43 -0
  242. data/spec/support/graphql/responses/completed_orders/payments.json.erb +27 -0
  243. data/spec/support/graphql/responses/completed_orders/shipping_address.json.erb +78 -0
  244. data/spec/support/graphql/responses/countries.json.erb +51 -0
  245. data/spec/support/graphql/responses/current_order.json.erb +36 -0
  246. data/spec/support/graphql/responses/current_store.json.erb +34 -0
  247. data/spec/support/graphql/responses/current_user.json.erb +232 -0
  248. data/spec/support/graphql/responses/product_by_slug.json.erb +123 -0
  249. data/spec/support/graphql/responses/taxonomies.json.erb +145 -0
  250. data/spec/support/helpers/graphql.rb +43 -0
  251. data/spec/support/matchers/graphql.rb +35 -0
  252. data/spec/support/shared_contexts/graphql_query_subject.rb +21 -0
  253. metadata +572 -0
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ class BatchLoader
5
+ # A batch loader for +has_many+ associations.
6
+ class HasMany < BatchLoader
7
+ def load
8
+ graphql_loader_for(object.id, default_value: []) do |object_ids, loader|
9
+ retrieve_records_for(object_ids).each do |associated_record|
10
+ loader.call(associated_record.send(reflection.foreign_key)) do |memo|
11
+ memo << associated_record
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def retrieve_records_for(object_ids)
20
+ base_relation.where(reflection.foreign_key => object_ids)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ class BatchLoader
5
+ # A batch loader for +has_many :through+ associations.
6
+ class HasManyThrough < BatchLoader
7
+ def load
8
+ graphql_loader_for(object.id, default_value: []) do |object_ids, loader|
9
+ records_by_parent = group_records_by_parent(retrieve_records_for(object_ids))
10
+
11
+ records_by_parent.each_pair do |parent_id, children|
12
+ loader.call(parent_id) do |memo|
13
+ memo.concat(children)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def retrieve_records_for(object_ids)
22
+ through_reflection = reflection.through_reflection
23
+
24
+ base_relation
25
+ .joins(through_reflection.name)
26
+ .where("#{through_reflection.table_name}.#{through_reflection.foreign_key}" => object_ids)
27
+ end
28
+
29
+ def group_records_by_parent(records)
30
+ result = Hash.new { |h, k| h[k] = [] }
31
+
32
+ records.each do |record|
33
+ record.send(reflection.through_reflection.name).each do |parent|
34
+ result[parent.send(reflection.through_reflection.foreign_key)] << record
35
+ end
36
+ end
37
+
38
+ result
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ class BatchLoader
5
+ # A batch loader for +has_one+ associations.
6
+ class HasOne < BatchLoader
7
+ def load
8
+ graphql_loader_for(object.id) do |object_ids, loader|
9
+ retrieve_records_for(object_ids).each do |record|
10
+ loader.call(record.send(reflection.foreign_key), record)
11
+ end
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def retrieve_records_for(object_ids)
18
+ base_relation.where(reflection.foreign_key => object_ids)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ def self.configure
5
+ yield configuration
6
+ end
7
+
8
+ def self.configuration
9
+ @configuration ||= Configuration.new
10
+ end
11
+
12
+ class Configuration
13
+ attr_accessor :payment_sources
14
+
15
+ def initialize
16
+ @payment_sources = ['SolidusGraphqlApi::Types::CreditCard']
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ class Context
5
+ AUTHORIZATION_HEADER = "Authorization"
6
+ TOKEN_PATTERN = /^Bearer (?<token>.*)/.freeze
7
+
8
+ attr_reader :request, :headers
9
+
10
+ def initialize(request:)
11
+ @request = request
12
+ @headers = request.headers
13
+ end
14
+
15
+ def to_h
16
+ { current_user: current_user,
17
+ current_ability: current_ability,
18
+ current_store: current_store,
19
+ current_order: current_order,
20
+ current_pricing_options: current_pricing_options,
21
+ order_token: order_token }
22
+ end
23
+
24
+ def current_user
25
+ @current_user ||= Spree.user_class.find_by(spree_api_key: bearer_token)
26
+ end
27
+
28
+ def current_ability
29
+ @current_ability ||= Spree::Ability.new(current_user)
30
+ end
31
+
32
+ def order_token
33
+ @order_token ||= headers["X-Spree-Order-Token"]
34
+ end
35
+
36
+ def current_store
37
+ @current_store ||= Spree::Config.current_store_selector_class.new(request).store
38
+ end
39
+
40
+ def current_order
41
+ return @current_order if instance_variable_defined?(:@current_order)
42
+
43
+ @current_order = current_order_by_current_user || current_order_by_guest_token
44
+ end
45
+
46
+ def current_pricing_options
47
+ @current_pricing_options ||= pricing_options_from_context
48
+ end
49
+
50
+ private
51
+
52
+ def bearer_token
53
+ @bearer_token ||= headers[AUTHORIZATION_HEADER].to_s.match(TOKEN_PATTERN) do |match_data|
54
+ match_data[:token]
55
+ end
56
+ end
57
+
58
+ def current_order_by_current_user
59
+ current_user&.last_incomplete_spree_order(store: current_store)
60
+ end
61
+
62
+ def current_order_by_guest_token
63
+ incomplete_orders = Spree::Order.incomplete
64
+ incomplete_orders = incomplete_orders.where(store: current_store) if current_store
65
+
66
+ incomplete_orders.find_by(guest_token: order_token)
67
+ end
68
+
69
+ def pricing_options_from_context
70
+ Spree::Config.pricing_options_class.new(
71
+ currency: current_store&.default_currency.presence || Spree::Config[:currency],
72
+ country_iso: current_store&.cart_tax_country_iso.presence
73
+ )
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spree/core'
4
+ require 'solidus_graphql_api'
5
+
6
+ module SolidusGraphqlApi
7
+ class Engine < Rails::Engine
8
+ include SolidusSupport::EngineExtensions
9
+
10
+ isolate_namespace ::Spree
11
+
12
+ engine_name 'solidus_graphql_api'
13
+
14
+ # use rspec for tests
15
+ config.generators do |g|
16
+ g.test_framework :rspec
17
+ end
18
+
19
+ config.autoload_paths << File.expand_path('..', __dir__)
20
+
21
+ initializer "solidus_graphql_api.setup_batch_loader_middleware" do |app|
22
+ app.middleware.use BatchLoader::Middleware
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_graphql_api/factories/address_factory'
4
+ require 'solidus_graphql_api/factories/country_factory'
5
+ require 'solidus_graphql_api/factories/store_factory'
6
+ require 'solidus_graphql_api/factories/taxonomy_factory'
7
+
8
+ module SolidusGraphqlApi
9
+ module Factories
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.modify do
4
+ factory :address do
5
+ firstname { 'John' }
6
+ lastname { nil }
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.modify do
4
+ factory :country do
5
+ trait :with_states do
6
+ after :create do |country|
7
+ create(:state, id: 1, country: country)
8
+ create(:state, id: 2, country: country, state_code: 'CA')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.modify do
4
+ factory :store do
5
+ trait :with_defaults do
6
+ cart_tax_country_iso { 'US' }
7
+ code { 'solidus' }
8
+ default_currency { 'USD' }
9
+ meta_description { 'store description' }
10
+ meta_keywords { 'store, metaKeywords' }
11
+ name { 'Solidus Test Store' }
12
+ seo_title { 'Store Title' }
13
+ url { 'www.example.com' }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.modify do
4
+ factory :taxonomy do
5
+ transient do
6
+ root_taxon_id {}
7
+ end
8
+
9
+ after :create do |taxonomy, options|
10
+ if options.root_taxon_id.present? && taxonomy.root.id != options.root_taxon_id
11
+ taxonomy.root.update(id: options.root_taxon_id)
12
+ end
13
+ end
14
+
15
+ trait :with_taxon_meta do
16
+ after :create do |taxonomy|
17
+ taxonomy.root.update(
18
+ description: 'Brand description',
19
+ meta_description: 'Brand meta description',
20
+ meta_keywords: 'Brand meta keywords',
21
+ meta_title: 'Brand meta title',
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ module Mutations
5
+ class BaseMutation < GraphQL::Schema::RelayClassicMutation
6
+ argument_class Types::Base::Argument
7
+ field_class Types::Base::Field
8
+ input_object_class Types::Base::InputObject
9
+ object_class Types::Base::Object
10
+
11
+ private
12
+
13
+ def guest_token
14
+ context[:order_token]
15
+ end
16
+
17
+ def current_order
18
+ context[:current_order]
19
+ end
20
+
21
+ def current_user
22
+ context[:current_user]
23
+ end
24
+
25
+ def current_ability
26
+ context[:current_ability]
27
+ end
28
+
29
+ def current_store
30
+ context[:current_store]
31
+ end
32
+
33
+ def user_errors(*path, errors)
34
+ return [] if errors.empty?
35
+
36
+ errors.map do |attribute, message|
37
+ {
38
+ path: ["input", *path].concat(attribute.to_s.camelize(:lower).split('.')),
39
+ message: message,
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ module Mutations
5
+ module Checkout
6
+ class AddAddressesToCheckout < BaseMutation
7
+ null true
8
+
9
+ argument :billing_address, Types::InputObjects::AddressInput, required: true
10
+ argument :shipping_address, Types::InputObjects::AddressInput, required: false
11
+ argument :ship_to_billing_address, Boolean, required: false
12
+
13
+ field :order, Types::Order, null: true
14
+ field :errors, [Types::UserError], null: false
15
+
16
+ def resolve(billing_address:, shipping_address: nil, ship_to_billing_address: false)
17
+ current_order.update(state: :address)
18
+
19
+ update_params = {
20
+ bill_address: Spree::Address.new(billing_address.to_h),
21
+ ship_address: Spree::Address.new(shipping_address.to_h),
22
+ use_billing: ship_to_billing_address
23
+ }
24
+
25
+ if Spree::OrderUpdateAttributes.new(current_order, update_params).apply
26
+ current_order.recalculate
27
+ errors = []
28
+ else
29
+ errors = current_order.errors
30
+ end
31
+
32
+ { errors: user_errors('order', errors), order: current_order }
33
+ end
34
+
35
+ def ready?(*)
36
+ current_ability.authorize!(:update, current_order, guest_token)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ module Mutations
5
+ module Checkout
6
+ class AddPaymentToCheckout < BaseMutation
7
+ null true
8
+
9
+ argument :payment_method_id, ID, required: true, loads: Types::PaymentMethod
10
+ argument :amount, Float, required: false
11
+ argument :source, Types::Json, required: false
12
+
13
+ field :order, Types::Order, null: true
14
+ field :errors, [Types::UserError], null: false
15
+
16
+ def resolve(payment_method:, amount: nil, source:)
17
+ current_order.update(state: :payment)
18
+
19
+ update_params = {
20
+ payments_attributes: [{
21
+ payment_method_id: payment_method.id,
22
+ amount: amount || current_order.total,
23
+ source_attributes: source
24
+ }]
25
+ }
26
+
27
+ if Spree::OrderUpdateAttributes.new(current_order, update_params).apply
28
+ current_order.recalculate
29
+ errors = []
30
+ else
31
+ errors = current_order.errors
32
+ end
33
+
34
+ { errors: user_errors('order', errors), order: current_order }
35
+ end
36
+
37
+ private
38
+
39
+ def ready?(*)
40
+ current_ability.authorize!(:update, current_order, guest_token)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusGraphqlApi
4
+ module Mutations
5
+ module Checkout
6
+ class AddToCart < BaseMutation
7
+ null true
8
+
9
+ argument :variant_id, ID, required: true, loads: Types::Variant
10
+ argument :quantity, Integer, required: true
11
+
12
+ field :order, Types::Order, null: true
13
+ field :errors, [Types::UserError], null: false
14
+
15
+ def resolve(variant:, quantity:)
16
+ line_item = current_order.contents.add(variant, quantity)
17
+
18
+ {
19
+ order: current_order,
20
+ errors: user_errors("line_item", line_item.errors)
21
+ }
22
+ end
23
+
24
+ def ready?(*)
25
+ current_ability.authorize!(:update, current_order, guest_token)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end