duodealer_api 1.0.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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +13 -0
- data/.rubocop.yml +8 -0
- data/.travis.yml +23 -0
- data/Gemfile +5 -0
- data/Gemfile_ar41 +5 -0
- data/Gemfile_ar50 +5 -0
- data/Gemfile_ar51 +5 -0
- data/Gemfile_ar_master +5 -0
- data/RELEASING +13 -0
- data/Rakefile +44 -0
- data/docker-compose.yml +13 -0
- data/docs/graphql.md +191 -0
- data/duodealer_api.gemspec +38 -0
- data/lib/active_resource/connection_ext.rb +10 -0
- data/lib/active_resource/detailed_log_subscriber.rb +52 -0
- data/lib/active_resource/json_errors.rb +31 -0
- data/lib/duodealer_api.rb +33 -0
- data/lib/duodealer_api/api_version.rb +205 -0
- data/lib/duodealer_api/connection.rb +35 -0
- data/lib/duodealer_api/countable.rb +14 -0
- data/lib/duodealer_api/disable_prefix_check.rb +31 -0
- data/lib/duodealer_api/events.rb +7 -0
- data/lib/duodealer_api/graphql.rb +79 -0
- data/lib/duodealer_api/graphql/http_client.rb +22 -0
- data/lib/duodealer_api/graphql/railtie.rb +17 -0
- data/lib/duodealer_api/graphql/task.rake +97 -0
- data/lib/duodealer_api/limits.rb +76 -0
- data/lib/duodealer_api/message_enricher.rb +23 -0
- data/lib/duodealer_api/meta.rb +15 -0
- data/lib/duodealer_api/metafields.rb +20 -0
- data/lib/duodealer_api/paginated_collection.rb +69 -0
- data/lib/duodealer_api/pagination_link_headers.rb +33 -0
- data/lib/duodealer_api/resources.rb +3 -0
- data/lib/duodealer_api/resources/abandoned_checkout.rb +7 -0
- data/lib/duodealer_api/resources/access_scope.rb +10 -0
- data/lib/duodealer_api/resources/access_token.rb +8 -0
- data/lib/duodealer_api/resources/address.rb +4 -0
- data/lib/duodealer_api/resources/announcement.rb +4 -0
- data/lib/duodealer_api/resources/api_permission.rb +9 -0
- data/lib/duodealer_api/resources/application_charge.rb +15 -0
- data/lib/duodealer_api/resources/application_credit.rb +4 -0
- data/lib/duodealer_api/resources/array_base.rb +13 -0
- data/lib/duodealer_api/resources/article.rb +21 -0
- data/lib/duodealer_api/resources/asset.rb +100 -0
- data/lib/duodealer_api/resources/assigned_fulfillment_order.rb +16 -0
- data/lib/duodealer_api/resources/base.rb +162 -0
- data/lib/duodealer_api/resources/billing_address.rb +4 -0
- data/lib/duodealer_api/resources/blog.rb +10 -0
- data/lib/duodealer_api/resources/carrier_service.rb +4 -0
- data/lib/duodealer_api/resources/cart.rb +4 -0
- data/lib/duodealer_api/resources/checkout.rb +30 -0
- data/lib/duodealer_api/resources/collect.rb +6 -0
- data/lib/duodealer_api/resources/collection.rb +14 -0
- data/lib/duodealer_api/resources/collection_listing.rb +18 -0
- data/lib/duodealer_api/resources/collection_publication.rb +10 -0
- data/lib/duodealer_api/resources/comment.rb +9 -0
- data/lib/duodealer_api/resources/country.rb +4 -0
- data/lib/duodealer_api/resources/currency.rb +6 -0
- data/lib/duodealer_api/resources/custom_collection.rb +19 -0
- data/lib/duodealer_api/resources/customer.rb +29 -0
- data/lib/duodealer_api/resources/customer_group.rb +5 -0
- data/lib/duodealer_api/resources/customer_invite.rb +4 -0
- data/lib/duodealer_api/resources/customer_saved_search.rb +11 -0
- data/lib/duodealer_api/resources/discount_code.rb +9 -0
- data/lib/duodealer_api/resources/draft_order.rb +14 -0
- data/lib/duodealer_api/resources/draft_order_invoice.rb +4 -0
- data/lib/duodealer_api/resources/event.rb +8 -0
- data/lib/duodealer_api/resources/fulfillment.rb +47 -0
- data/lib/duodealer_api/resources/fulfillment_event.rb +15 -0
- data/lib/duodealer_api/resources/fulfillment_order.rb +137 -0
- data/lib/duodealer_api/resources/fulfillment_order_locations_for_move.rb +4 -0
- data/lib/duodealer_api/resources/fulfillment_request.rb +15 -0
- data/lib/duodealer_api/resources/fulfillment_service.rb +4 -0
- data/lib/duodealer_api/resources/fulfillment_v2.rb +20 -0
- data/lib/duodealer_api/resources/gift_card.rb +7 -0
- data/lib/duodealer_api/resources/image.rb +16 -0
- data/lib/duodealer_api/resources/inventory_item.rb +6 -0
- data/lib/duodealer_api/resources/inventory_level.rb +55 -0
- data/lib/duodealer_api/resources/line_item.rb +14 -0
- data/lib/duodealer_api/resources/location.rb +8 -0
- data/lib/duodealer_api/resources/marketing_event.rb +10 -0
- data/lib/duodealer_api/resources/metafield.rb +13 -0
- data/lib/duodealer_api/resources/note_attribute.rb +4 -0
- data/lib/duodealer_api/resources/option.rb +4 -0
- data/lib/duodealer_api/resources/order.rb +43 -0
- data/lib/duodealer_api/resources/order_risk.rb +8 -0
- data/lib/duodealer_api/resources/page.rb +6 -0
- data/lib/duodealer_api/resources/payment.rb +7 -0
- data/lib/duodealer_api/resources/payment_details.rb +4 -0
- data/lib/duodealer_api/resources/ping.rb +3 -0
- data/lib/duodealer_api/resources/policy.rb +7 -0
- data/lib/duodealer_api/resources/price_rule.rb +8 -0
- data/lib/duodealer_api/resources/product.rb +35 -0
- data/lib/duodealer_api/resources/product_listing.rb +16 -0
- data/lib/duodealer_api/resources/product_publication.rb +10 -0
- data/lib/duodealer_api/resources/province.rb +5 -0
- data/lib/duodealer_api/resources/publication.rb +5 -0
- data/lib/duodealer_api/resources/receipt.rb +4 -0
- data/lib/duodealer_api/resources/recurring_application_charge.rb +31 -0
- data/lib/duodealer_api/resources/redirect.rb +4 -0
- data/lib/duodealer_api/resources/refund.rb +14 -0
- data/lib/duodealer_api/resources/report.rb +4 -0
- data/lib/duodealer_api/resources/resource_feedback.rb +19 -0
- data/lib/duodealer_api/resources/rule.rb +4 -0
- data/lib/duodealer_api/resources/script_tag.rb +4 -0
- data/lib/duodealer_api/resources/shipping_address.rb +4 -0
- data/lib/duodealer_api/resources/shipping_line.rb +4 -0
- data/lib/duodealer_api/resources/shipping_rate.rb +7 -0
- data/lib/duodealer_api/resources/shipping_zone.rb +4 -0
- data/lib/duodealer_api/resources/shop.rb +25 -0
- data/lib/duodealer_api/resources/smart_collection.rb +19 -0
- data/lib/duodealer_api/resources/storefront_access_token.rb +4 -0
- data/lib/duodealer_api/resources/tax_line.rb +4 -0
- data/lib/duodealer_api/resources/tax_service.rb +4 -0
- data/lib/duodealer_api/resources/tender_transaction.rb +6 -0
- data/lib/duodealer_api/resources/theme.rb +4 -0
- data/lib/duodealer_api/resources/transaction.rb +5 -0
- data/lib/duodealer_api/resources/usage_charge.rb +5 -0
- data/lib/duodealer_api/resources/user.rb +4 -0
- data/lib/duodealer_api/resources/variant.rb +8 -0
- data/lib/duodealer_api/resources/webhook.rb +4 -0
- data/lib/duodealer_api/session.rb +171 -0
- data/lib/duodealer_api/version.rb +3 -0
- data/shipit.rubygems.yml +1 -0
- data/test/abandoned_checkouts_test.rb +29 -0
- data/test/access_scope_test.rb +23 -0
- data/test/access_token_test.rb +19 -0
- data/test/active_resource/json_errors_test.rb +19 -0
- data/test/api_permission_test.rb +9 -0
- data/test/api_version_test.rb +157 -0
- data/test/application_charge_test.rb +79 -0
- data/test/application_credit_test.rb +35 -0
- data/test/article_test.rb +73 -0
- data/test/asset_test.rb +18 -0
- data/test/assigned_fulfillment_order_test.rb +77 -0
- data/test/base_test.rb +198 -0
- data/test/blog_test.rb +8 -0
- data/test/carrier_service_test.rb +17 -0
- data/test/cart_test.rb +13 -0
- data/test/checkouts_test.rb +77 -0
- data/test/collect_test.rb +9 -0
- data/test/collection_listing_test.rb +79 -0
- data/test/collection_publication_test.rb +40 -0
- data/test/collection_test.rb +49 -0
- data/test/countable_test.rb +13 -0
- data/test/currency_test.rb +21 -0
- data/test/custom_collection_test.rb +9 -0
- data/test/customer_saved_search_test.rb +27 -0
- data/test/customer_test.rb +50 -0
- data/test/detailed_log_subscriber_test.rb +139 -0
- data/test/discount_code_test.rb +53 -0
- data/test/draft_order_test.rb +151 -0
- data/test/fixtures/abandoned_checkout.json +184 -0
- data/test/fixtures/abandoned_checkouts.json +186 -0
- data/test/fixtures/access_scopes.json +10 -0
- data/test/fixtures/access_token_delegate.json +4 -0
- data/test/fixtures/api_versions.json +38 -0
- data/test/fixtures/apis.json +42 -0
- data/test/fixtures/application_charge.json +16 -0
- data/test/fixtures/application_charges.json +57 -0
- data/test/fixtures/application_credit.json +12 -0
- data/test/fixtures/application_credits.json +24 -0
- data/test/fixtures/article.json +15 -0
- data/test/fixtures/articles.json +39 -0
- data/test/fixtures/asset.json +9 -0
- data/test/fixtures/assets.json +136 -0
- data/test/fixtures/assigned_fulfillment_orders.json +78 -0
- data/test/fixtures/authors.json +1 -0
- data/test/fixtures/blog.json +13 -0
- data/test/fixtures/blogs.json +13 -0
- data/test/fixtures/carrier_service.json +9 -0
- data/test/fixtures/carts.json +43 -0
- data/test/fixtures/checkout.json +160 -0
- data/test/fixtures/checkouts.json +162 -0
- data/test/fixtures/collect.json +12 -0
- data/test/fixtures/collection.json +17 -0
- data/test/fixtures/collection_listing.json +11 -0
- data/test/fixtures/collection_listing_product_ids.json +1 -0
- data/test/fixtures/collection_listing_product_ids2.json +1 -0
- data/test/fixtures/collection_listings.json +13 -0
- data/test/fixtures/collection_products.json +47 -0
- data/test/fixtures/collection_publication.json +11 -0
- data/test/fixtures/collection_publications.json +13 -0
- data/test/fixtures/currencies.json +25 -0
- data/test/fixtures/custom_collection.json +17 -0
- data/test/fixtures/customer_invite.json +9 -0
- data/test/fixtures/customer_saved_search.json +9 -0
- data/test/fixtures/customer_saved_search_customers.json +60 -0
- data/test/fixtures/customers.json +59 -0
- data/test/fixtures/customers_account_activation_url.json +3 -0
- data/test/fixtures/customers_search.json +60 -0
- data/test/fixtures/discount_code.json +10 -0
- data/test/fixtures/discount_codes.json +12 -0
- data/test/fixtures/draft_order.json +159 -0
- data/test/fixtures/draft_order_completed.json +159 -0
- data/test/fixtures/draft_order_invoice.json +9 -0
- data/test/fixtures/draft_orders.json +161 -0
- data/test/fixtures/engagement.json +15 -0
- data/test/fixtures/events.json +31 -0
- data/test/fixtures/fulfillment.json +49 -0
- data/test/fixtures/fulfillment_event.json +12 -0
- data/test/fixtures/fulfillment_order.json +38 -0
- data/test/fixtures/fulfillment_order_locations_for_move.json +18 -0
- data/test/fixtures/fulfillment_orders.json +78 -0
- data/test/fixtures/fulfillment_request.json +28 -0
- data/test/fixtures/fulfillment_service.json +10 -0
- data/test/fixtures/fulfillments.json +53 -0
- data/test/fixtures/gift_card.json +20 -0
- data/test/fixtures/gift_card_disabled.json +20 -0
- data/test/fixtures/graphql/2019-10.json +1083 -0
- data/test/fixtures/graphql/dummy_schema.rb +16 -0
- data/test/fixtures/graphql/unstable.json +1083 -0
- data/test/fixtures/image.json +10 -0
- data/test/fixtures/images.json +20 -0
- data/test/fixtures/inventory_level.json +7 -0
- data/test/fixtures/inventory_levels.json +24 -0
- data/test/fixtures/marketing_event.json +28 -0
- data/test/fixtures/marketing_events.json +54 -0
- data/test/fixtures/metafield.json +12 -0
- data/test/fixtures/metafields.json +34 -0
- data/test/fixtures/order.json +297 -0
- data/test/fixtures/order_risk.json +14 -0
- data/test/fixtures/order_risks.json +28 -0
- data/test/fixtures/order_with_properties.json +373 -0
- data/test/fixtures/orders.json +299 -0
- data/test/fixtures/payment.json +7 -0
- data/test/fixtures/payments.json +9 -0
- data/test/fixtures/ping/conversation.json +1 -0
- data/test/fixtures/ping/failed_delivery_confirmation.json +1 -0
- data/test/fixtures/ping/message.json +1 -0
- data/test/fixtures/ping/successful_delivery_confirmation.json +1 -0
- data/test/fixtures/policies.json +8 -0
- data/test/fixtures/price_rule.json +27 -0
- data/test/fixtures/price_rules.json +28 -0
- data/test/fixtures/product.json +116 -0
- data/test/fixtures/product_listing.json +86 -0
- data/test/fixtures/product_listing_product_ids.json +1 -0
- data/test/fixtures/product_listing_product_ids2.json +1 -0
- data/test/fixtures/product_listings.json +174 -0
- data/test/fixtures/product_publication.json +11 -0
- data/test/fixtures/product_publications.json +13 -0
- data/test/fixtures/publications.json +9 -0
- data/test/fixtures/recurring_application_charge.json +22 -0
- data/test/fixtures/recurring_application_charge_adjustment.json +5 -0
- data/test/fixtures/recurring_application_charges.json +106 -0
- data/test/fixtures/redirect.json +7 -0
- data/test/fixtures/refund.json +112 -0
- data/test/fixtures/report.json +9 -0
- data/test/fixtures/reports.json +11 -0
- data/test/fixtures/script_tag.json +10 -0
- data/test/fixtures/script_tags.json +18 -0
- data/test/fixtures/shipping_rates.json +12 -0
- data/test/fixtures/shipping_zones.json +315 -0
- data/test/fixtures/shop.json +26 -0
- data/test/fixtures/smart_collection.json +21 -0
- data/test/fixtures/smart_collection_products.json +155 -0
- data/test/fixtures/storefront_access_token.json +9 -0
- data/test/fixtures/storefront_access_tokens.json +18 -0
- data/test/fixtures/tags.json +1 -0
- data/test/fixtures/tax_service.json +9 -0
- data/test/fixtures/tender_transactions.json +52 -0
- data/test/fixtures/transaction.json +29 -0
- data/test/fixtures/usage_charge.json +11 -0
- data/test/fixtures/usage_charges.json +23 -0
- data/test/fixtures/user.json +21 -0
- data/test/fixtures/users.json +42 -0
- data/test/fixtures/variant.json +23 -0
- data/test/fixtures/variants.json +88 -0
- data/test/fixtures/webhook.json +10 -0
- data/test/fixtures/webhooks.json +18 -0
- data/test/fulfillment_event_test.rb +69 -0
- data/test/fulfillment_order_test.rb +462 -0
- data/test/fulfillment_order_test_helper.rb +7 -0
- data/test/fulfillment_request_test.rb +33 -0
- data/test/fulfillment_service_test.rb +17 -0
- data/test/fulfillment_test.rb +224 -0
- data/test/fulfillment_v2_test.rb +62 -0
- data/test/gift_card_test.rb +22 -0
- data/test/graphql/http_client_test.rb +26 -0
- data/test/graphql_test.rb +147 -0
- data/test/image_test.rb +39 -0
- data/test/inventory_level_test.rb +59 -0
- data/test/lib/webmock_extensions/last_request.rb +16 -0
- data/test/limits_test.rb +38 -0
- data/test/location_test.rb +14 -0
- data/test/marketing_event_test.rb +68 -0
- data/test/message_enricher_test.rb +45 -0
- data/test/meta_test.rb +49 -0
- data/test/metafield_test.rb +46 -0
- data/test/order_risk_test.rb +46 -0
- data/test/order_test.rb +125 -0
- data/test/pagination_test.rb +257 -0
- data/test/payment_test.rb +19 -0
- data/test/policy_test.rb +19 -0
- data/test/price_rule_test.rb +65 -0
- data/test/product_listing_test.rb +97 -0
- data/test/product_publication_test.rb +40 -0
- data/test/product_test.rb +60 -0
- data/test/publication_test.rb +12 -0
- data/test/recurring_application_charge_test.rb +142 -0
- data/test/redirect_test.rb +9 -0
- data/test/refund_test.rb +32 -0
- data/test/report_test.rb +35 -0
- data/test/resource_feedback_test.rb +42 -0
- data/test/script_tag_test.rb +30 -0
- data/test/session_test.rb +366 -0
- data/test/shipping_rate_test.rb +17 -0
- data/test/shipping_zone_test.rb +10 -0
- data/test/shop_test.rb +68 -0
- data/test/smart_collection_test.rb +35 -0
- data/test/storefront_access_token_test.rb +32 -0
- data/test/tax_service_test.rb +9 -0
- data/test/tender_transaction_test.rb +18 -0
- data/test/test_helper.rb +124 -0
- data/test/transaction_test.rb +17 -0
- data/test/usage_charge_test.rb +21 -0
- data/test/user_test.rb +17 -0
- data/test/variant_test.rb +46 -0
- data/test/webhook_test.rb +21 -0
- metadata +541 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'rails/railtie'
|
|
3
|
+
|
|
4
|
+
module DuodealerAPI
|
|
5
|
+
module GraphQL
|
|
6
|
+
class Railtie < Rails::Railtie
|
|
7
|
+
initializer 'duodealer_api.initialize_graphql_clients' do |app|
|
|
8
|
+
DuodealerAPI::GraphQL.schema_location = app.root.join('db', DuodealerAPI::GraphQL.schema_location)
|
|
9
|
+
DuodealerAPI::GraphQL.initialize_clients
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
rake_tasks do
|
|
13
|
+
load 'duodealer_api/graphql/task.rake'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
namespace :duodealer_api do
|
|
5
|
+
namespace :graphql do
|
|
6
|
+
desc 'Dumps a local JSON schema file of the Duo Dealer Admin API'
|
|
7
|
+
task :dump do
|
|
8
|
+
usage = <<~USAGE
|
|
9
|
+
|
|
10
|
+
Usage: rake duodealer_api:graphql:dump [<args>]
|
|
11
|
+
|
|
12
|
+
Dumps a local JSON schema file of the Duo Dealer Admin API. The schema is specific to an
|
|
13
|
+
API version and authentication is required (either OAuth or private app).
|
|
14
|
+
|
|
15
|
+
Dump the schema file for the 2020-01 API version using private app authentication:
|
|
16
|
+
$ rake duodealer_api:graphql:dump SHOP_URL="https://API_KEY:PASSWORD@SHOP_NAME.duodealer.com" API_VERSION=2020-01
|
|
17
|
+
|
|
18
|
+
Dump the schema file for the unstable API version using an OAuth access token:
|
|
19
|
+
$ rake duodealer_api:graphql:dump SHOP_DOMAIN=SHOP_NAME.duodealer.com ACCESS_TOKEN=abc API_VERSION=unstable
|
|
20
|
+
|
|
21
|
+
Arguments:
|
|
22
|
+
ACCESS_TOKEN OAuth access token (shop specific)
|
|
23
|
+
API_VERSION API version handle [example: 2020-01]
|
|
24
|
+
SHOP_DOMAIN Shop domain (without path) [example: SHOP_NAME.duodealer.com]
|
|
25
|
+
SHOP_URL Shop URL for private apps [example: https://API_KEY:PASSWORD@SHOP_NAME.duodealer.com]
|
|
26
|
+
USAGE
|
|
27
|
+
|
|
28
|
+
access_token = ENV['ACCESS_TOKEN'] || ENV['access_token']
|
|
29
|
+
api_version = ENV['API_VERSION'] || ENV['api_version']
|
|
30
|
+
shop_url = ENV['SHOP_URL'] || ENV['shop_url']
|
|
31
|
+
shop_domain = ENV['SHOP_DOMAIN'] || ENV['shop_domain']
|
|
32
|
+
|
|
33
|
+
unless access_token || api_version || shop_url || shop_domain
|
|
34
|
+
puts usage
|
|
35
|
+
exit(1)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
unless shop_url || shop_domain
|
|
39
|
+
puts 'Error: either SHOP_DOMAIN or SHOP_URL is required for authentication'
|
|
40
|
+
puts usage
|
|
41
|
+
exit(1)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if shop_url && shop_domain
|
|
45
|
+
puts 'Error: SHOP_DOMAIN and SHOP_URL cannot be used together. Use one or the other for authentication.'
|
|
46
|
+
puts usage
|
|
47
|
+
exit(1)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if shop_domain && !access_token
|
|
51
|
+
puts 'Error: ACCESS_TOKEN required when SHOP_DOMAIN is used'
|
|
52
|
+
puts usage
|
|
53
|
+
exit(1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
unless api_version
|
|
57
|
+
puts 'Error: API_VERSION required. Example: 2020-01'
|
|
58
|
+
puts usage
|
|
59
|
+
exit(1)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
Rake::Task['environment'].invoke if Rake::Task.task_defined?('environment')
|
|
63
|
+
|
|
64
|
+
Duodealer::ApiVersion.fetch_known_versions
|
|
65
|
+
DuodealerAPI::ApiVersion.version_lookup_mode = :raise_on_unknown
|
|
66
|
+
|
|
67
|
+
duodealer_session = DuodealerAPI::Session.new(domain: shop_domain, token: access_token, api_version: api_version)
|
|
68
|
+
DuodealerAPI::Base.activate_session(duodealer_session)
|
|
69
|
+
|
|
70
|
+
if shop_url
|
|
71
|
+
DuodealerAPI::Base.site = shop_url
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
puts "Fetching schema for #{DuodealerAPI::Base.api_version.handle} API version..."
|
|
75
|
+
|
|
76
|
+
client = DuodealerAPI::GraphQL::HTTPClient.new(DuodealerAPI::Base.api_version)
|
|
77
|
+
document = GraphQL.parse('{ __schema { queryType { name } } }')
|
|
78
|
+
response = client.execute(document: document).to_h
|
|
79
|
+
|
|
80
|
+
unless response['data'].present?
|
|
81
|
+
puts "Error: failed to query the API."
|
|
82
|
+
puts "Response: #{response}"
|
|
83
|
+
puts 'Ensure your SHOP_DOMAIN or SHOP_URL are valid and you have valid authentication credentials.'
|
|
84
|
+
puts usage
|
|
85
|
+
exit(1)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
schema_location = DuodealerAPI::GraphQL.schema_location
|
|
89
|
+
FileUtils.mkdir_p(schema_location) unless Dir.exist?(schema_location)
|
|
90
|
+
|
|
91
|
+
schema_file = schema_location.join("#{api_version}.json")
|
|
92
|
+
GraphQL::Client.dump_schema(client, schema_file.to_s)
|
|
93
|
+
|
|
94
|
+
puts "Wrote file #{schema_file}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module DuodealerAPI
|
|
2
|
+
module Limits
|
|
3
|
+
class LimitUnavailable < StandardError; end
|
|
4
|
+
|
|
5
|
+
def self.included(klass)
|
|
6
|
+
klass.send(:extend, ClassMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
# Takes form <call count>/<bucket size>
|
|
11
|
+
# See https://help.duodealer.com/en/api/getting-started/api-call-limit
|
|
12
|
+
# Eg: 2/40
|
|
13
|
+
CREDIT_LIMIT_HEADER_PARAM = {
|
|
14
|
+
shop: 'X-DuoDealer-Shop-Api-Call-Limit',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# How many more API calls can I make?
|
|
19
|
+
# @return {Integer}
|
|
20
|
+
#
|
|
21
|
+
def credit_left
|
|
22
|
+
credit_limit(:shop) - credit_used(:shop)
|
|
23
|
+
end
|
|
24
|
+
alias_method :available_calls, :credit_left
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Have I reached my API call limit?
|
|
28
|
+
# @return {Boolean}
|
|
29
|
+
#
|
|
30
|
+
def credit_maxed?
|
|
31
|
+
credit_left <= 0
|
|
32
|
+
end
|
|
33
|
+
alias_method :maxed?, :credit_maxed?
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# How many total API calls can I make?
|
|
37
|
+
# NOTE: subtracting 1 from credit_limit because I think DuodealerAPI cuts off at 299 or shop limits.
|
|
38
|
+
# @param {Symbol} scope [:shop]
|
|
39
|
+
# @return {Integer}
|
|
40
|
+
#
|
|
41
|
+
def credit_limit(scope=:shop)
|
|
42
|
+
api_credit_limit_param(scope).pop.to_i - 1
|
|
43
|
+
end
|
|
44
|
+
alias_method :call_limit, :credit_limit
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# How many API calls have I made?
|
|
48
|
+
# @param {Symbol} scope [:shop]
|
|
49
|
+
# @return {Integer}
|
|
50
|
+
#
|
|
51
|
+
def credit_used(scope=:shop)
|
|
52
|
+
api_credit_limit_param(scope).shift.to_i
|
|
53
|
+
end
|
|
54
|
+
alias_method :call_count, :credit_used
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# @return {HTTPResonse}
|
|
58
|
+
#
|
|
59
|
+
def response
|
|
60
|
+
Shop.current unless DuodealerAPI::Base.connection.response
|
|
61
|
+
DuodealerAPI::Base.connection.response
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# @return {Array}
|
|
68
|
+
#
|
|
69
|
+
def api_credit_limit_param(scope)
|
|
70
|
+
header = response[CREDIT_LIMIT_HEADER_PARAM[scope]]
|
|
71
|
+
raise LimitUnavailable unless header
|
|
72
|
+
header.split('/')
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module DuodealerAPI
|
|
2
|
+
class MessageEnricher < SimpleDelegator
|
|
3
|
+
def message
|
|
4
|
+
return super unless (400...500).include?(code.to_i)
|
|
5
|
+
|
|
6
|
+
@_cached_message ||= begin
|
|
7
|
+
detailed_error = begin
|
|
8
|
+
parsed_body = JSON.parse(body)
|
|
9
|
+
|
|
10
|
+
if parsed_body['error']
|
|
11
|
+
parsed_body['error'].to_s
|
|
12
|
+
elsif parsed_body['errors']
|
|
13
|
+
Array(parsed_body['errors']).join('; ')
|
|
14
|
+
end
|
|
15
|
+
rescue JSON::ParserError
|
|
16
|
+
nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
detailed_error.present? ? "#{super} (#{detailed_error})" : super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DuodealerAPI
|
|
4
|
+
class Meta < ActiveResource::Base
|
|
5
|
+
self.site = "https://app.duodealer.com/services/"
|
|
6
|
+
self.element_name = 'api'
|
|
7
|
+
self.primary_key = :handle
|
|
8
|
+
self.timeout = 5
|
|
9
|
+
|
|
10
|
+
def self.admin_versions
|
|
11
|
+
all.find { |api| api.handle = :admin }.versions
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module DuodealerAPI
|
|
2
|
+
module Metafields
|
|
3
|
+
def metafields(**options)
|
|
4
|
+
options.merge! resource: self.class.collection_name, resource_id: id
|
|
5
|
+
|
|
6
|
+
Metafield.find :all, params: options
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def add_metafield(metafield)
|
|
10
|
+
raise ArgumentError, "You can only add metafields to resource that has been saved" if new?
|
|
11
|
+
|
|
12
|
+
metafield.prefix_options = {
|
|
13
|
+
:resource => self.class.collection_name,
|
|
14
|
+
:resource_id => id
|
|
15
|
+
}
|
|
16
|
+
metafield.save
|
|
17
|
+
metafield
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DuodealerAPI
|
|
4
|
+
class PaginatedCollection < ActiveResource::Collection
|
|
5
|
+
module CollectionPagination
|
|
6
|
+
def initialize(args)
|
|
7
|
+
@next_url = pagination_link_headers.next_link&.url&.to_s
|
|
8
|
+
@previous_url = pagination_link_headers.previous_link&.url&.to_s
|
|
9
|
+
super(args)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def next_page?
|
|
13
|
+
ensure_available
|
|
14
|
+
@next_url.present?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def previous_page?
|
|
18
|
+
ensure_available
|
|
19
|
+
@previous_url.present?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def fetch_next_page
|
|
23
|
+
fetch_page(@next_url)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def fetch_previous_page
|
|
27
|
+
fetch_page(@previous_url)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def next_page_info
|
|
31
|
+
extract_page_info(@next_url)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def previous_page_info
|
|
35
|
+
extract_page_info(@previous_url)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
AVAILABLE_IN_VERSION = DuodealerAPI::ApiVersion.find_version('2019-10')
|
|
41
|
+
AVAILABLE_IN_VERSION_EARLY = DuodealerAPI::ApiVersion.find_version('2019-07')
|
|
42
|
+
|
|
43
|
+
def fetch_page(url)
|
|
44
|
+
ensure_available
|
|
45
|
+
return [] unless url.present?
|
|
46
|
+
|
|
47
|
+
resource_class.all(from: url)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def pagination_link_headers
|
|
51
|
+
@pagination_link_headers ||= DuodealerAPI::PaginationLinkHeaders.new(
|
|
52
|
+
DuodealerAPI::Base.connection.response["Link"]
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def ensure_available
|
|
57
|
+
return if DuodealerAPI::Base.api_version >= AVAILABLE_IN_VERSION
|
|
58
|
+
return if DuodealerAPI::Base.api_version >= AVAILABLE_IN_VERSION_EARLY && resource_class.early_july_pagination?
|
|
59
|
+
raise NotImplementedError
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def extract_page_info(url)
|
|
63
|
+
CGI.escape(Rack::Utils.parse_query(URI(url).query)['page_info']) if url.present?
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
include CollectionPagination
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module DuodealerAPI
|
|
2
|
+
class InvalidPaginationLinksError < StandardError; end
|
|
3
|
+
|
|
4
|
+
class PaginationLinkHeaders
|
|
5
|
+
LinkHeader = Struct.new(:url, :rel)
|
|
6
|
+
attr_reader :previous_link, :next_link
|
|
7
|
+
|
|
8
|
+
def initialize(link_header)
|
|
9
|
+
links = parse_link_header(link_header)
|
|
10
|
+
@previous_link = links.find { |link| link.rel == :previous }
|
|
11
|
+
@next_link = links.find { |link| link.rel == :next }
|
|
12
|
+
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def parse_link_header(link_header)
|
|
19
|
+
return [] unless link_header.present?
|
|
20
|
+
links = link_header.split(',')
|
|
21
|
+
links.map do |link|
|
|
22
|
+
parts = link.split('; ')
|
|
23
|
+
raise DuodealerAPI::InvalidPaginationLinksError.new("Invalid link header: url and rel expected") unless parts.length == 2
|
|
24
|
+
|
|
25
|
+
url = parts[0][/<(.*)>/, 1]
|
|
26
|
+
rel = parts[1][/rel="(.*)"/, 1]&.to_sym
|
|
27
|
+
|
|
28
|
+
url = URI.parse(url)
|
|
29
|
+
LinkHeader.new(url, rel)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module DuodealerAPI
|
|
2
|
+
class ApplicationCharge < Base
|
|
3
|
+
undef_method :test
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
[:pending, :expired, :accepted, :declined].each do |status|
|
|
7
|
+
define_method(status) { (all || []).select { |c| c.status == status.to_s } }
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def activate
|
|
12
|
+
load_attributes_from_response(post(:activate))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|