e_plat 0.5.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +109 -60
  3. data/lib/e_plat/client/default_request_args.rb +1 -1
  4. data/lib/e_plat/client.rb +55 -9
  5. data/lib/e_plat/initializer.rb +26 -0
  6. data/lib/e_plat/mapping/bigcommerce/v_3/product/option.rb +58 -0
  7. data/lib/e_plat/mapping/bigcommerce/v_3/product/variant/option_value.rb +42 -0
  8. data/lib/e_plat/mapping/shopify/v_2024_07/metafield.rb +26 -0
  9. data/lib/e_plat/mapping/shopify/v_2024_07/order/billing_address.rb +14 -0
  10. data/lib/e_plat/mapping/shopify/v_2024_07/order/shipping_address.rb +30 -0
  11. data/lib/e_plat/mapping/shopify/v_2024_07/order.rb +26 -0
  12. data/lib/e_plat/mapping/shopify/v_2024_07/product/image.rb +52 -0
  13. data/lib/e_plat/mapping/shopify/v_2024_07/product/option.rb +45 -0
  14. data/lib/e_plat/mapping/shopify/v_2024_07/product/variant/option_value.rb +58 -0
  15. data/lib/e_plat/mapping/shopify/v_2024_07/product/variant.rb +180 -0
  16. data/lib/e_plat/mapping/shopify/v_2024_07/product.rb +100 -0
  17. data/lib/e_plat/mapping/shopify/v_2024_07/script_tag.rb +26 -0
  18. data/lib/e_plat/mapping/shopify/v_2024_07/shop.rb +26 -0
  19. data/lib/e_plat/mapping/shopify/v_2024_07/webhook.rb +29 -0
  20. data/lib/e_plat/mapping/virtual_collection/shopify/product/variant/option_value.rb +272 -0
  21. data/lib/e_plat/mapping.rb +39 -15
  22. data/lib/e_plat/resource/base.rb +39 -5
  23. data/lib/e_plat/resource/collection.rb +45 -16
  24. data/lib/e_plat/resource/concerns/aliases.rb +39 -19
  25. data/lib/e_plat/resource/concerns/dirty.rb +12 -8
  26. data/lib/e_plat/resource/concerns/graph_q_lable.rb +253 -0
  27. data/lib/e_plat/resource/concerns/overwrite_instance_methods.rb +4 -4
  28. data/lib/e_plat/resource/concerns/overwrite_request_methods.rb +64 -21
  29. data/lib/e_plat/resource/countable.rb +37 -10
  30. data/lib/e_plat/resource/metafield.rb +2 -2
  31. data/lib/e_plat/resource/platform_specific/bigcommerce/metafield.rb +4 -0
  32. data/lib/e_plat/resource/platform_specific/bigcommerce/order/Consignment.rb +2 -0
  33. data/lib/e_plat/resource/platform_specific/bigcommerce/order/billing_address.rb +2 -0
  34. data/lib/e_plat/resource/platform_specific/bigcommerce/order/fulfillment.rb +2 -0
  35. data/lib/e_plat/resource/platform_specific/bigcommerce/order/line_item.rb +2 -0
  36. data/lib/e_plat/resource/platform_specific/bigcommerce/order/shipping_address.rb +2 -0
  37. data/lib/e_plat/resource/platform_specific/bigcommerce/order/shipping_line.rb +2 -0
  38. data/lib/e_plat/resource/platform_specific/bigcommerce/order.rb +4 -0
  39. data/lib/e_plat/resource/platform_specific/bigcommerce/product/image.rb +2 -0
  40. data/lib/e_plat/resource/platform_specific/bigcommerce/product/option.rb +2 -0
  41. data/lib/e_plat/resource/platform_specific/bigcommerce/product/variant/option_value.rb +2 -0
  42. data/lib/e_plat/resource/platform_specific/bigcommerce/product/variant.rb +2 -0
  43. data/lib/e_plat/resource/platform_specific/bigcommerce/product.rb +4 -0
  44. data/lib/e_plat/resource/platform_specific/bigcommerce/script_tag.rb +4 -0
  45. data/lib/e_plat/resource/platform_specific/bigcommerce/shop.rb +4 -0
  46. data/lib/e_plat/resource/platform_specific/bigcommerce/webhook.rb +4 -0
  47. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/input/product/variant.rb +47 -0
  48. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/input/product/variants_bulk.rb +47 -0
  49. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/input/product.rb +23 -0
  50. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/input.rb +98 -0
  51. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/mutation/product/variant.rb +78 -0
  52. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/mutation/product.rb +55 -0
  53. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/mutation.rb +5 -0
  54. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/query/product/variant.rb +44 -0
  55. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/query/product.rb +58 -0
  56. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2024_07/query.rb +5 -0
  57. data/lib/e_plat/resource/platform_specific/shopify/metafield.rb +4 -0
  58. data/lib/e_plat/resource/platform_specific/shopify/order/Consignment.rb +2 -0
  59. data/lib/e_plat/resource/platform_specific/shopify/order/billing_address.rb +2 -0
  60. data/lib/e_plat/resource/platform_specific/shopify/order/fulfillment.rb +2 -0
  61. data/lib/e_plat/resource/platform_specific/shopify/order/line_item.rb +2 -0
  62. data/lib/e_plat/resource/platform_specific/shopify/order/shipping_address.rb +2 -0
  63. data/lib/e_plat/resource/platform_specific/shopify/order/shipping_line.rb +2 -0
  64. data/lib/e_plat/resource/platform_specific/shopify/order.rb +4 -0
  65. data/lib/e_plat/resource/platform_specific/shopify/product/image.rb +14 -0
  66. data/lib/e_plat/resource/platform_specific/shopify/product/option.rb +14 -0
  67. data/lib/e_plat/resource/platform_specific/shopify/product/variant/option_value.rb +14 -0
  68. data/lib/e_plat/resource/platform_specific/shopify/product/variant.rb +66 -0
  69. data/lib/e_plat/resource/platform_specific/shopify/product.rb +79 -0
  70. data/lib/e_plat/resource/platform_specific/shopify/recurring_application_charge/usage_charge.rb +2 -0
  71. data/lib/e_plat/resource/platform_specific/shopify/recurring_application_charge.rb +4 -0
  72. data/lib/e_plat/resource/platform_specific/shopify/script_tag.rb +4 -0
  73. data/lib/e_plat/resource/platform_specific/shopify/shop.rb +4 -0
  74. data/lib/e_plat/resource/platform_specific/shopify/webhook.rb +4 -0
  75. data/lib/e_plat/resource/product/image.rb +8 -5
  76. data/lib/e_plat/resource/product/option.rb +2 -3
  77. data/lib/e_plat/resource/product/variant/option_value.rb +17 -0
  78. data/lib/e_plat/resource/product/variant.rb +6 -14
  79. data/lib/e_plat/resource/product.rb +23 -11
  80. data/lib/e_plat/session.rb +3 -2
  81. data/lib/e_plat/type_coercer.rb +4 -2
  82. data/lib/e_plat/version.rb +1 -1
  83. data/lib/e_plat.rb +33 -4
  84. data/lib/hash.rb +39 -0
  85. metadata +163 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85b0fb58fb552bdd494649429de66feb12612b53ee0cf49bda4b1a87e14e81b7
4
- data.tar.gz: e5702192f1057e1f65736e20c88d7c35a4d6490db785d0dc4ef95381015cc6b2
3
+ metadata.gz: d10eb52dda105627cb32fb58161da4777a8a020f6ea70ba4111da4487441e743
4
+ data.tar.gz: 00ef52bdc6790981c6fcfb35615982c06b82152279d9a5f301ff3c84ad50747b
5
5
  SHA512:
6
- metadata.gz: ac493807a5ffc4e61a7eb7d5fa4b28777697a9aa5c50a8cb145e8d1327bef821f8efcdacc672e6652778fb3b3c5c5961d76d5844d4a874a2f2bdacdf3b7896e8
7
- data.tar.gz: c69b4fb8c31be9eecaaf6e587bbdd964a4a7ff046a844f0e3c81063d95a156fffe5667d9273a40e3e25fed5460e780bf02b2a5f29b7eb215d55c7806b15d718d
6
+ metadata.gz: f5951156f87b275af28cefeed42eff062aeb85155454a8b498c54d795843be40acd5245d1f20b5e724912abef7ef43b0dc47c4e09f2084ad1ad1fbab8418aafa
7
+ data.tar.gz: 0af92dd3962135ec69c738eab60bc320e8add2de57832cc793ed11ab5118e1515a7a048623f75537e3c126ae1e78e9c109cab49685335d7a9860da655d611bdc
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <strong>EPlat <small>(E-commerce Platform)</small> </br></strong>
4
4
  A single interface for interacting with E-commerce platform APIs.
5
5
 
6
- Goals are:
6
+ Goals:
7
7
  <ul>
8
8
  <li>
9
9
  Make it easy to use and request API resources from different platforms.
@@ -12,7 +12,7 @@ Goals are:
12
12
  Offer a universal alias interface for interacting with common natured attributes. e.g. Shopify's product.body_html and BigCommerce's product.description.
13
13
  </li>
14
14
  <li>
15
- Have a simple, easy-to-understand, lightweight project structure.
15
+ Have a simple, easy-to-understand project structure.
16
16
  </li>
17
17
  <li>
18
18
  The e_plat alias interface mimics Shopify's API schema names and types.
@@ -43,15 +43,37 @@ You can configure which platform APIs are used by updating the EPlat config: <br
43
43
  #initializers/e_plat.rb
44
44
  EPlat.config.shopify_api_version = "2024-01"
45
45
  EPlat.config.bigcommerce_api_version = "v3"
46
- EPlat.config.woocommerce_api_version = "v3"
47
46
 
48
47
  # EPlat.api_display_name.shopify #=> "2024-01" # presents as the platform would display in URL paths
49
48
  # EPlat.config.shopify_api_version #=> "2024_01" # coerced interally for creating constants
49
+ # EPlat.config.print_graphql_requests #=> false # prints out Shopify graphql queries/mutations to the console
50
50
  ```
51
51
  <br>
52
52
 
53
- ## Relasing new version
53
+ ## Testing
54
+
55
+ To run the test for the default versions of all supported platforms:
56
+ ```
57
+ bundle exec rails test
58
+ ```
59
+
60
+ To run with specific api versions, you can set globals inline
61
+ ```
62
+ EPLAT_SHOPIFY_API_VERSION=2024_07 EPLAT_BIGCOMMERCE_API_VERSION=v3 rails test
63
+ ```
64
+
65
+ To print out Shopify GraphQL queries/mutations
66
+ ```
67
+ EPLAT_PRINT_GRAPHQL_REQUESTS=true rails test
68
+ ```
69
+
70
+ <br>
71
+
72
+ ## Releasing a new version
54
73
  https://dev.to/doctolib/release-a-new-gem-version-je0
74
+
75
+ <br>
76
+
55
77
  <br>
56
78
 
57
79
  ## Usage
@@ -62,7 +84,7 @@ EPlat::Session.new(
62
84
  platform: :shopify,
63
85
  store_url: "test-store.myshopify.com",
64
86
  api_token: "123",
65
- # store_hash: optional BigCommerce store hash
87
+ # store_hash: "optional BigCommerce store hash"
66
88
  )
67
89
  ```
68
90
 
@@ -71,7 +93,7 @@ EPlat::Session.new(
71
93
  EPlat::Product.find(id: 123)
72
94
  ```
73
95
 
74
- 3. Which will return an instance of:
96
+ 3. Which will return a platform resource instance that inherits from:
75
97
  ```ruby
76
98
  EPlat::Product
77
99
  ```
@@ -212,10 +234,8 @@ EPlat is designed to let you mostly use it's universal interface, but then easil
212
234
  | options | array | * | * | nil |
213
235
  | product_type | string | * | type | nil |
214
236
  | published_at | datetime | * | nil | nil |
215
- | published_scope | string | * | nil | nil |
216
237
  | status | string | * | availability | nil |
217
238
  | tags | string | * | nil | nil |
218
- | admin_graphql_api_id | string | * | nil | nil |
219
239
  | template_suffix | string | * | nil | nil |
220
240
  | title | string | * | name | nil |
221
241
  | updated_at | datetime | * | date_modified| nil |
@@ -225,68 +245,62 @@ EPlat is designed to let you mostly use it's universal interface, but then easil
225
245
 
226
246
  ### EPlat::Product::Variant
227
247
 
228
-
229
- | Alias | Type | Shopify | BigCommerce | Etc |
230
- | --------------------- | -------- | ------- | ----------------------| ------------|
231
- | id | integer | * | id | nil |
232
- | product_id | integer | * | product_id | nil |
233
- | title | string | * | option_values&.map(&:label)&.join(' ') | nil |
234
- | price | string | * | price | nil |
235
- | sku | string | * | sku | nil |
236
- | position | integer | * | nil | nil |
237
- | inventory_policy | string | * | nil | nil |
238
- | compare_at_price | string | * | nil | nil |
239
- | fulfillment_service | string | * | nil | nil |
240
- | inventory_management | string | * | nil | nil |
241
- | option1 | string | * | option_values[0].label| nil |
242
- | option2 | string | * | nil | nil |
243
- | option3 | string | * | nil | nil |
244
- | created_at | datetime | * | nil | nil |
245
- | updated_at | datetime | * | nil | nil |
246
- | taxable | boolean | * | nil | nil |
247
- | barcode | string | * | nil | nil |
248
- | grams | integer | * | nil | nil |
249
- | image_id | integer | * | nil | nil |
250
- | weight | float | * | weight | nil |
251
- | weight_unit | string | * | nil | nil |
252
- | inventory_item_id | integer | * | nil | nil |
253
- | inventory_quantity | integer | * | inventory_level | nil |
254
- | old_inventory_quantity| integer | * | nil | nil |
255
- | presentment_prices | array | * | nil | nil |
256
- | tax_code | string | * | nil | nil |
257
- | requires_shipping | boolean | * | nil | nil |
258
- | admin_graphql_api_id | string | * | nil | nil |
259
-
248
+
249
+ | Alias | Type | Shopify | BigCommerce | Etc |
250
+ |-----------------------|----------|---------|--------------------------------------|-----|
251
+ | id | integer | * | id | nil |
252
+ | title | string | * | option_values&.map(&:label)&.join(' ') | nil |
253
+ | price | string | * | price | nil |
254
+ | sku | string | * | sku | nil |
255
+ | position | integer | * | nil | nil |
256
+ | inventory_policy | string | * | nil | nil |
257
+ | compare_at_price | string | * | nil | nil |
258
+ | inventory_management | boolean | inventoryItem[tracked] | nil | nil |
259
+ | created_at | datetime | * | nil | nil |
260
+ | updated_at | datetime | * | nil | nil |
261
+ | taxable | boolean | * | nil | nil |
262
+ | barcode | string | * | nil | nil |
263
+ | grams | integer | getter only: converted node.inventoryItem[measurement][weight][value] | nil | nil |
264
+ | weight | float | getter only: node.inventoryItem[measurement][weight][value] | weight |
265
+ | weight_unit | string | getter only: node.inventoryItem[measurement][weight][unit] | nil |
266
+ | inventory_item_id | integer | getter only: node.inventoryItem[id]| nil | nil |
267
+ | inventory_quantity | integer | getter only: node.inventoryQuantity | inventory_level | nil |
268
+ | tax_code | string | * | nil | nil |
269
+ | requires_shipping | boolean | InventoryItem[requiresShipping] | nil | nil |
260
270
  *Bigcommerce variant.title= setter is not supported
261
271
 
262
272
 
263
273
  ### EPlat::Product::Option
264
274
 
265
- | Alias | Type | Shopify | BigCommerce| Etc |
266
- | --------- | -------- | ------- | -----------| ------------|
267
- | id | integer | * | nil | nil |
268
- | product_id| integer | * | nil | nil |
269
- | name | string | * | nil | nil |
270
- | position | integer | * | nil | nil |
271
- | values | array | * | nil | nil |
272
-
275
+ | Alias | Type | Shopify | BigCommerce | Etc |
276
+ | ---------- | -------- | ------- | ---------------------------- | --- |
277
+ | id | integer | * | id | nil |
278
+ | name | string | * | display_name | nil |
279
+ | position | integer | * | sort_order | nil |
280
+ | values | array | * | option_values[i][label] | nil |
281
+
273
282
 
274
283
  ### EPlat::Product::Image
275
284
 
276
285
  | Alias | Type | Shopify | BigCommerce | Etc |
277
286
  | -------------------- | -------- | ------- | ----------- | ------------|
278
287
  | id | integer | * | id | nil |
279
- | product_id | integer | * | product_id | nil |
280
288
  | position | integer | * | nil | nil |
281
- | created_at | datetime | * | date_created | nil |
282
- | updated_at | datetime | * | date_modified| nil |
283
289
  | alt | string | * | nil | nil |
284
290
  | width | integer | * | nil | nil |
285
291
  | height | integer | * | nil | nil |
286
292
  | src | string | * | url_standard | nil |
287
293
  | variant_ids | array | * | nil | nil |
288
- | admin_graphql_api_id | string | * | nil | nil |
289
294
 
295
+
296
+ ### EPlat::Product::Variant::OptionValue
297
+ (not supported for Shopify API v2024_01)
298
+
299
+ | Alias | Type | Shopify | BigCommerce | Etc |
300
+ | -------------------- | -------- | ------------------------------------------ | ------------------ | --- |
301
+ | id | integer | [selected_options][option_value][id] | id | nil |
302
+ | name | string | [selected_options][name] | option_display_name| nil |
303
+ | value | string | [selected_options][value] | label | nil |
290
304
  </details>
291
305
 
292
306
  <details>
@@ -412,6 +426,26 @@ EPlat is designed to let you mostly use it's universal interface, but then easil
412
426
  | longitude | float | * | nil | nil |
413
427
 
414
428
 
429
+ ### EPlat::Order::BillingAddress
430
+
431
+ | Alias | Type | Shopify | BigCommerce | Etc |
432
+ |---------------|---------|---------|-------------|-------------|
433
+ | address1 | string | * | street_1 | nil |
434
+ | address2 | string | * | street_2 | nil |
435
+ | city | string | * | city | nil |
436
+ | company | string | * | company | nil |
437
+ | country | string | * | country | nil |
438
+ | first_name | string | * | first_name | nil |
439
+ | last_name | string | * | last_name | nil |
440
+ | phone | string | * | phone | nil |
441
+ | province | string | * | state | nil |
442
+ | zip | string | * | zip | nil |
443
+ | country_code | string | * | country_iso2| nil |
444
+ | province_code | string | * | nil | nil |
445
+ | latitude | float | * | nil | nil |
446
+ | longitude | float | * | nil | nil |
447
+
448
+
415
449
  ### EPlat::Order::LineItem
416
450
 
417
451
  | Attribute | Type | Shopify | BigCommerce | Etc |
@@ -565,11 +599,12 @@ Unfortunately it's in a Time Integer format. Haven't yet got dynamic conversion
565
599
  | ::Product.find_by(attr: '') | * | * | |
566
600
  | ::Product.create(attr:) | * | * | |
567
601
  | ::Product.save | * | * | |
568
- | .save saves nested resources | * | | |
602
+ | .save saves nested resources | only variants | | |
569
603
  | ::Product.delete(id) | * | * | |
570
604
  | ::Product.count | * | * | |
571
605
  | product.dup | * | * | |
572
606
  | product.variants | * | * | |
607
+ | product.load_all_variants | * | * | |
573
608
  | product.find_variant(id) | * | * | |
574
609
  | product.images | * | * | |
575
610
  | products.next_page? | * | * | |
@@ -580,11 +615,23 @@ Unfortunately it's in a Time Integer format. Haven't yet got dynamic conversion
580
615
  | products.next_page_info | * | * | |
581
616
 
582
617
  ```ruby
583
- # How you might safely handle pagination via user input
584
- # <%= link_to "previous products", "/", page_info: products.previous_page_info %>
585
- # <%= link_to "Next products", "/", page_info: products.next_page_info %>
586
-
587
- EPlat::Product.find(:all, params: {limit: 2, EPlat::Current.e_plat_session.pagination_param => params['page_info'] })
618
+ # The 2024 increased Shopify variants limit
619
+ @product.load_all_variants #returns all variants. In Shopify's case it will keep on requesting in batches until it has the full amount (capped at 10x requests of 200 currently i.e. 2,000 variants)
620
+
621
+ ### Pagination
622
+ # ...How you might handle pagination.
623
+
624
+ # Add pagination cursors to your link's params. This is available on any EPlat::Collection instance
625
+ <%= link_to "previous products", "/", forward_page_info: products.previous_page_info %>
626
+ <%= link_to "Next products", "/", backward_page_info: products.next_page_info %>
627
+
628
+ # Then on the server, let EPlat handle the correct platform specific arguments to request with.
629
+ EPlat::Product.find(:all, params: {
630
+ EPlat::Current.e_plat_session.pagination_param(:forward) => params['forward_page_info']
631
+ })
632
+ EPlat::Product.find(:all, params: {
633
+ EPlat::Current.e_plat_session.pagination_param(:backward) => params['backward_page_info']
634
+ })
588
635
  ```
589
636
 
590
637
 
@@ -749,7 +796,7 @@ Unfortunately it's in a Time Integer format. Haven't yet got dynamic conversion
749
796
  (although should be kept track of locally)
750
797
  </li>
751
798
  <li>
752
- <strong>GraphQL</strong>. EPlat just handles REST
799
+ <strong>GraphQL</strong>. EPlat just handles REST (for now, although we plan to change the internals for Shopify product to use Graphql under the hood)
753
800
  <ul>
754
801
  </details>
755
802
 
@@ -786,12 +833,14 @@ EPlat::Product.find(my_id).destroy
786
833
 
787
834
  ### save record
788
835
  product = EPlat::Product.new(title: 't-shirt')
789
- product.save
836
+ product.save # true or false
837
+ product.errors # active record like errors if .save returned false
790
838
 
791
839
  product.full_response # <Net::HTTPOK>
792
840
  product.headers # { "date"=>"Fri, 17 Nov 2023 14:25:53 GMT", ...}
793
841
  JSON.parse(product.full_response.body) # "{...}"
794
842
 
843
+
795
844
  ### get records
796
845
  EPlat::Product.find(101) # GET EPlat::Product.first(args)) (or EPlat::Product.last(args))
797
846
  EPlat::Product.all
@@ -10,7 +10,7 @@ module EPlat
10
10
  {}
11
11
  when :bigcommerce
12
12
  {
13
- "include" => "variants,images"
13
+ "include" => "variants,images,options"
14
14
  }
15
15
  when :woocommerce
16
16
  {}
data/lib/e_plat/client.rb CHANGED
@@ -4,18 +4,34 @@ module EPlat
4
4
  class Client
5
5
  include Client::PlatformConvenienceMethods, Client::DefaultRequestArgs
6
6
 
7
- SHOPIFY_PAGINATION_PARAM = "page_info"
8
- BIGCOMMERCE_PAGINATION_PARAM = "page"
7
+ SHOPIFY_REST_PAGINATION_PARAM = "page_info"
8
+ SHOPIFY_GRAPHQL_FORWARD_PAGINATION_PARAM = "after"
9
+ SHOPIFY_GRAPHQL_BACKWARD_PAGINATION_PARAM = "before"
10
+ BIGCOMMERCE_PAGINATION_PARAM = "page"
9
11
 
10
12
  attr_reader :platform, :store_url, :api_token, :api_version, :store_hash
11
13
 
12
- def initialize(platform: nil, store_url: nil, api_token: nil, store_hash: nil)
13
- @platform, @store_url, @api_token, @store_hash = platform&.to_sym, store_url, api_token, store_hash
14
+ def initialize(platform: nil, store_url: nil, api_token: nil, store_hash: nil, api_version: nil)
15
+ @platform, @store_url, @api_token, @store_hash, @api_version = platform&.to_sym, store_url, api_token, store_hash, api_version
14
16
  end
15
17
 
16
18
  def headers
17
19
  platform_headers
18
20
  end
21
+
22
+ # Dynamically determines the class based on the platform
23
+ # needs to return nil if there isn't a more specific class than the klass passed in
24
+ def platform_klass(klass)
25
+ return if klass.to_s.include? "EPlat::#{platform.capitalize}"
26
+ platform_specific_class_name = klass.to_s.gsub("EPlat::", "EPlat::#{platform.capitalize}::")
27
+
28
+ platform_specific_class = platform_specific_class_name.safe_constantize
29
+ if platform_specific_class_name != klass.to_s && platform_specific_class
30
+ platform_specific_class
31
+ else
32
+ nil
33
+ end
34
+ end
19
35
 
20
36
  def inspect
21
37
  "#<#{self.class} platform=#{platform.inspect} store_url=#{store_url.inspect} api_version=#{api_version.inspect}>"
@@ -42,8 +58,14 @@ module EPlat
42
58
 
43
59
  def url_prefix(klass: nil)
44
60
  # for nested resources like "/products/:product/variants/:id"
61
+ klass_without_platform_scoping = nil
62
+ EPlat::SUPPORTED_PLATFORMS.each do |platform|
63
+ klass_without_platform_scoping = klass.to_s.gsub!("#{ platform.capitalize }::", "") if klass.to_s.include?("#{ platform.capitalize }::")
64
+ end
65
+ klass = klass_without_platform_scoping&.safe_constantize || klass
66
+
45
67
  collection_path =
46
- if klass.to_s.scan("::").length == 2
68
+ if klass.to_s.scan("::").length > 1
47
69
  parent_klass = klass.to_s.split("::")[1].underscore
48
70
  "#{ parent_klass.pluralize }/:#{ parent_klass }/"
49
71
  else
@@ -63,6 +85,19 @@ module EPlat
63
85
  "/" # not yet supported
64
86
  end
65
87
  end
88
+
89
+ def graphql_request_url
90
+ case platform
91
+ when :shopify
92
+ "https://#{ store_url }/admin/api/#{ api_version.dasherize }/graphql.json"
93
+ else
94
+ raise EPlat::Error, "GraphQL is not supported for #{ platform }"
95
+ end
96
+ end
97
+
98
+ def uses_graphql_for_products?
99
+ platform == :shopify && api_version != "2024_01"
100
+ end
66
101
 
67
102
  def platform_headers
68
103
  case platform
@@ -87,6 +122,8 @@ module EPlat
87
122
  end
88
123
 
89
124
  def api_version
125
+ return @api_version if @api_version.present?
126
+
90
127
  case platform
91
128
  when :shopify
92
129
  EPlat.config.shopify_api_version
@@ -97,6 +134,10 @@ module EPlat
97
134
  end
98
135
  end
99
136
 
137
+ def shopify_graphql_version
138
+ "V202407"
139
+ end
140
+
100
141
  def can_update_nested_resources?
101
142
  case platform
102
143
  when :shopify then true
@@ -105,11 +146,16 @@ module EPlat
105
146
  end
106
147
  end
107
148
 
108
- def pagination_param
149
+ def pagination_param(direction=:forward)
109
150
  case platform
110
- when :shopify then SHOPIFY_PAGINATION_PARAM
111
- when :bigcommerce then BIGCOMMERCE_PAGINATION_PARAM
112
- when :woocommerce then nil
151
+ when :shopify
152
+ if uses_graphql_for_products?
153
+ direction == :backward ? SHOPIFY_GRAPHQL_BACKWARD_PAGINATION_PARAM : SHOPIFY_GRAPHQL_FORWARD_PAGINATION_PARAM
154
+ else
155
+ SHOPIFY_REST_PAGINATION_PARAM
156
+ end
157
+ when :bigcommerce
158
+ BIGCOMMERCE_PAGINATION_PARAM
113
159
  end
114
160
  end
115
161
 
@@ -0,0 +1,26 @@
1
+ module EPlat
2
+ class Initializer
3
+ class << self
4
+
5
+ REQUIRED_CLASSES = EPlat::SUPPORTED_RESOURCES.map do |resource|
6
+ [
7
+ "EPlat::#{ resource.classify }",
8
+ EPlat::SUPPORTED_PLATFORMS.map do |platform|
9
+ "EPlat::#{ platform.classify }::#{ resource.classify }"
10
+ end
11
+ ]
12
+ end.flatten.freeze
13
+
14
+ def check_required_classes!
15
+ REQUIRED_CLASSES.each do |klass|
16
+ unless Object.const_defined?(klass)
17
+ raise EPlat::Error, "Required class #{klass} not defined"
18
+ end
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,58 @@
1
+
2
+
3
+ module EPlat
4
+ class Mapping
5
+ module Bigcommerce
6
+ module V3
7
+ class Product
8
+ class Option < EPlat::Mapping::Base
9
+
10
+ def native_top_key
11
+ "data"
12
+ end
13
+
14
+ def native_attributes
15
+ super.concat([
16
+ "id",
17
+ "product_id",
18
+ "display_name",
19
+ "type",
20
+ "config",
21
+ "sort_order",
22
+ "option_values",
23
+ "modifiers",
24
+ "option_set_id",
25
+ "option_set_display",
26
+ "variants"
27
+ ])
28
+ end
29
+
30
+ def native_attribute_aliases
31
+ super.concat([
32
+ {
33
+ existing_entry: {native_key: "id", e_plat_key: "id"}
34
+ },
35
+ {
36
+ alias_attribute: {native_key: "display_name", e_plat_key: "name"}
37
+ },
38
+ {
39
+ alias_attribute: {native_key: "sort_order", e_plat_key: "position"}
40
+ },
41
+ {
42
+ alias_attribute: {native_key: "option_values", e_plat_key: "values",
43
+ custom_e_plat_getter: '-> (option_values) {
44
+ option_values.map{|val| val.label}
45
+ }',
46
+ custom_native_setter: '-> (option) { raise EPlat::Error.new "EPlat does not yet support native setting back to .option_values[i][:label]" }'
47
+ }
48
+ }
49
+
50
+ ])
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,42 @@
1
+
2
+
3
+ module EPlat
4
+ class Mapping
5
+ module Bigcommerce
6
+ module V3
7
+ class Product::Variant
8
+ class OptionValue < EPlat::Mapping::Base
9
+
10
+ def native_top_key
11
+ "data"
12
+ end
13
+
14
+ def native_attributes
15
+ super.concat([
16
+ "id",
17
+ "label",
18
+ "option_id",
19
+ "option_display_name"
20
+ ])
21
+ end
22
+
23
+ def native_attribute_aliases
24
+ super.concat([
25
+ {
26
+ existing_entry: {native_key: "id", e_plat_key: "id"}
27
+ },
28
+ {
29
+ alias_attribute: {native_key: "option_display_name", e_plat_key: "name"}
30
+ },
31
+ {
32
+ alias_attribute: {native_key: "label", e_plat_key: "value"}
33
+ }
34
+ ])
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module EPlat
2
+ class Mapping
3
+ module Shopify
4
+ module V202407 #< :module
5
+ class Metafield < EPlat::Mapping::Base
6
+
7
+ def native_top_key
8
+ "metafield"
9
+ end
10
+
11
+ def native_attributes
12
+ super.concat([
13
+ ])
14
+ end
15
+
16
+ def native_attribute_aliases
17
+ super.concat([
18
+ ])
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,14 @@
1
+
2
+
3
+ module EPlat
4
+ class Mapping
5
+ module Shopify
6
+ module V202407
7
+ class Order
8
+ class BillingAddress < ShippingAddress; end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,30 @@
1
+
2
+
3
+ module EPlat
4
+ class Mapping
5
+ module Shopify
6
+ module V202407
7
+ class Order
8
+ class ShippingAddress < EPlat::Mapping::Base
9
+
10
+ def native_top_key
11
+ :itself
12
+ end
13
+
14
+ def native_attributes
15
+ super.concat([
16
+ ])
17
+ end
18
+
19
+ def native_attribute_aliases
20
+ super.concat([
21
+ ])
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,26 @@
1
+ module EPlat
2
+ class Mapping
3
+ module Shopify
4
+ module V202407 #< :module
5
+ class Order < EPlat::Mapping::Base
6
+
7
+ def native_top_key
8
+ "order"
9
+ end
10
+
11
+ def native_attributes
12
+ super.concat([
13
+ ])
14
+ end
15
+
16
+ def native_attribute_aliases
17
+ super.concat([
18
+ ])
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+