amazon-ads 0.2.0 → 0.4.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -13
  3. data/lib/amazon_ads/api.rb +21 -13
  4. data/lib/amazon_ads/apis/ad_associations.rb +1 -2
  5. data/lib/amazon_ads/apis/ad_extensions.rb +1 -2
  6. data/lib/amazon_ads/apis/ad_groups.rb +1 -2
  7. data/lib/amazon_ads/apis/ads.rb +1 -2
  8. data/lib/amazon_ads/apis/advertising_deal_targets.rb +1 -2
  9. data/lib/amazon_ads/apis/advertising_deals.rb +1 -2
  10. data/lib/amazon_ads/apis/brand_store_edition_publish_versions.rb +1 -2
  11. data/lib/amazon_ads/apis/brand_store_editions.rb +0 -1
  12. data/lib/amazon_ads/apis/brand_store_pages.rb +1 -2
  13. data/lib/amazon_ads/apis/brand_stores.rb +1 -2
  14. data/lib/amazon_ads/apis/branded_keywords_pricings.rb +0 -1
  15. data/lib/amazon_ads/apis/campaign_forecasts.rb +0 -1
  16. data/lib/amazon_ads/apis/campaigns.rb +1 -2
  17. data/lib/amazon_ads/apis/commitment_spends.rb +0 -1
  18. data/lib/amazon_ads/apis/commitments.rb +0 -1
  19. data/lib/amazon_ads/apis/keyword_reservation_validations.rb +0 -1
  20. data/lib/amazon_ads/apis/marketing_stream.rb +4 -5
  21. data/lib/amazon_ads/apis/profiles.rb +0 -1
  22. data/lib/amazon_ads/apis/recommendation_types.rb +0 -1
  23. data/lib/amazon_ads/apis/recommendations.rb +0 -1
  24. data/lib/amazon_ads/apis/reporting.rb +0 -1
  25. data/lib/amazon_ads/apis/targets.rb +1 -2
  26. data/lib/amazon_ads/error.rb +41 -0
  27. data/lib/amazon_ads/lwa.rb +7 -13
  28. data/lib/amazon_ads/version.rb +1 -1
  29. data/lib/amazon_ads.rb +28 -32
  30. metadata +7 -33
  31. data/sig/generated/amazon_ads/api.rbs +0 -43
  32. data/sig/generated/amazon_ads/apis/ad_associations.rbs +0 -21
  33. data/sig/generated/amazon_ads/apis/ad_extensions.rbs +0 -17
  34. data/sig/generated/amazon_ads/apis/ad_groups.rbs +0 -21
  35. data/sig/generated/amazon_ads/apis/ads.rbs +0 -21
  36. data/sig/generated/amazon_ads/apis/advertising_deal_targets.rbs +0 -17
  37. data/sig/generated/amazon_ads/apis/advertising_deals.rbs +0 -21
  38. data/sig/generated/amazon_ads/apis/brand_store_edition_publish_versions.rbs +0 -13
  39. data/sig/generated/amazon_ads/apis/brand_store_editions.rbs +0 -9
  40. data/sig/generated/amazon_ads/apis/brand_store_pages.rbs +0 -9
  41. data/sig/generated/amazon_ads/apis/brand_stores.rbs +0 -9
  42. data/sig/generated/amazon_ads/apis/branded_keywords_pricings.rbs +0 -9
  43. data/sig/generated/amazon_ads/apis/campaign_forecasts.rbs +0 -9
  44. data/sig/generated/amazon_ads/apis/campaigns.rbs +0 -21
  45. data/sig/generated/amazon_ads/apis/commitment_spends.rbs +0 -9
  46. data/sig/generated/amazon_ads/apis/commitments.rbs +0 -21
  47. data/sig/generated/amazon_ads/apis/keyword_reservation_validations.rbs +0 -9
  48. data/sig/generated/amazon_ads/apis/marketing_stream.rbs +0 -56
  49. data/sig/generated/amazon_ads/apis/profiles.rbs +0 -22
  50. data/sig/generated/amazon_ads/apis/recommendation_types.rbs +0 -9
  51. data/sig/generated/amazon_ads/apis/recommendations.rbs +0 -9
  52. data/sig/generated/amazon_ads/apis/reporting.rbs +0 -23
  53. data/sig/generated/amazon_ads/apis/sponsored_products.rbs +0 -52
  54. data/sig/generated/amazon_ads/apis/streams.rbs +0 -40
  55. data/sig/generated/amazon_ads/apis/targets.rbs +0 -21
  56. data/sig/generated/amazon_ads/lwa.rbs +0 -37
  57. data/sig/generated/amazon_ads.rbs +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 576fb2a70351a890db1f8792fb65fca433b06f9aa33ce4b037b674b2bcc8beff
4
- data.tar.gz: 4326197b234cd8917b176645c7732a9ab77e66fc1fe79173907b7ff2c1640381
3
+ metadata.gz: 5e6d25250dfeb3f930a2c3253a1f0ed8da99226ba0d5290948b8e3ca8cfba483
4
+ data.tar.gz: 073acd8350a1446de8ea3a2ec207491506d3c996ffbad5d444b4bec2c77e2b7e
5
5
  SHA512:
6
- metadata.gz: dac34993c1d5100be01ded6aedaf59bc6819bae76fb18817eff7839a43723468e1d54419f9ae4ba0b7cf8bb4cd53bd85a5a98cc6891b8804c9350728d167fc0c
7
- data.tar.gz: 2f2de968113e103e2422b61687b1e01b10962c628c188d60e3c0dabc69895814bb216013e35744a8f17551b515f832179ed1a6e5c563ecbc5b74dd7ec66aa592
6
+ metadata.gz: ed62d0a64d560078cd3ca2d3d564e5cac7ae3e1da59ba00766fd4f0701b362d89980e879347e91f2ac5049176769580d9ce8cdc0e796770fdd24180a527023b4
7
+ data.tar.gz: 4e083231e7f90868aa5207b124f8affc757b452b8ce77d03319f83945822fa754e7e7b0286e9fb1b4271db327780b61b59746ef86dae28ba5fe4fcd44b6c91cc
data/README.md CHANGED
@@ -42,31 +42,42 @@ Make requests:
42
42
 
43
43
  ```ruby
44
44
  # List advertising profiles
45
- profiles = AmazonAds::Profiles.new(region: :na, access_token: access_token)
45
+ profiles = AmazonAds::Profiles.new(region: "NA", access_token:)
46
46
  profiles.list_profiles
47
47
 
48
48
  # List campaigns under a profile
49
49
  campaigns = AmazonAds::Campaigns.new(
50
- region: :na,
51
- access_token: access_token,
50
+ region: "NA",
51
+ access_token:,
52
52
  profile_id: "123456789",
53
53
  )
54
54
  campaigns.list_campaigns
55
55
  ```
56
56
 
57
- ## Development
57
+ ## Error handling
58
58
 
59
- ```bash
60
- bin/setup # Install dependencies
61
- rake test # Run tests
62
- rake rubocop # Lint
63
- rake steep # Type check
59
+ Responses with a 4xx or 5xx status raise `AmazonAds::Error`, which carries the full response:
60
+
61
+ ```ruby
62
+ begin
63
+ campaigns.list_campaigns
64
+ rescue AmazonAds::Error => e
65
+ e.status # 400
66
+ e.response.body # Amazon's error document
67
+ end
64
68
  ```
65
69
 
66
- ## Contributing
70
+ The error supports pattern matching on status:
67
71
 
68
- Bug reports and pull requests are welcome on [GitHub](https://github.com/lineofflight/amazon-ads-ruby).
72
+ ```ruby
73
+ case error
74
+ in status: 429 then backoff
75
+ in status: 500..599 then retry
76
+ end
77
+ ```
69
78
 
70
- ## License
79
+ Network failures (`HTTP::ConnectionError`, `HTTP::TimeoutError`) raise as-is, whether or not retries are configured.
80
+
81
+ ## Development
71
82
 
72
- MIT
83
+ See [AGENTS.md](AGENTS.md).
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rbs_inline: enabled
4
-
5
3
  require "http"
6
4
 
7
5
  module AmazonAds
@@ -51,22 +49,28 @@ module AmazonAds
51
49
  .headers(default_headers)
52
50
  .use(:auto_inflate)
53
51
 
54
- if retries.zero?
55
- client.use(:raise_error)
56
- else
57
- client
58
- .use(raise_error: { ignore: [429] })
59
- .retriable(tries: retries + 1, retry_statuses: [429])
60
- end
52
+ return client if retries.zero?
53
+
54
+ client.retriable(tries: retries + 1, retry_statuses: [429])
61
55
  end
62
56
 
63
57
  private
64
58
 
65
- #: (Symbol, String, **untyped) -> HTTP::Response
59
+ #: (HTTP::verb, String, **untyped) -> HTTP::Response
66
60
  def request(method, path, **options)
67
61
  url = endpoint
68
62
  url.path = path
69
- http.request(method, url, **options)
63
+ response = http.request(method, url.to_s, **options)
64
+ raise Error.build(response) if response.code >= 400
65
+
66
+ response
67
+ rescue HTTP::OutOfRetriesError => e
68
+ response = e.response
69
+ raise Error.build(response) if response
70
+
71
+ # No response means a transport error; re-raise as if never retried
72
+ cause = e.cause #: Exception
73
+ raise cause
70
74
  end
71
75
 
72
76
  #: () -> Hash[String, String]
@@ -77,8 +81,12 @@ module AmazonAds
77
81
  "Content-Type" => "application/json",
78
82
  "Accept" => "application/json",
79
83
  }
80
- headers["Amazon-Advertising-API-Scope"] = profile_id if profile_id
81
- headers["Amazon-Ads-AccountId"] = account_id if account_id
84
+ if (scope = profile_id)
85
+ headers["Amazon-Advertising-API-Scope"] = scope
86
+ end
87
+ if (account = account_id)
88
+ headers["Amazon-Ads-AccountId"] = account
89
+ end
82
90
 
83
91
  headers
84
92
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class AdAssociations < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # Query Ad Association
19
- #: (?ad_association_id_filter: String?, ?ad_group_id_filter: String?, ?ad_id_filter: String?, ?max_results: Integer?, ?next_token: String?) -> HTTP::Response
18
+ #: (?ad_association_id_filter: untyped?, ?ad_group_id_filter: untyped?, ?ad_id_filter: untyped?, ?max_results: Integer?, ?next_token: String?) -> HTTP::Response
20
19
  def query_ad_association(ad_association_id_filter: nil, ad_group_id_filter: nil, ad_id_filter: nil, max_results: nil, next_token: nil)
21
20
  request(:post, "/adsApi/v1/query/adAssociations", json: { "adAssociationIdFilter" => ad_association_id_filter, "adGroupIdFilter" => ad_group_id_filter, "adIdFilter" => ad_id_filter, "maxResults" => max_results, "nextToken" => next_token }.compact)
22
21
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class AdExtensions < API
@@ -10,7 +9,7 @@ module AmazonAds
10
9
  end
11
10
 
12
11
  # Query ad_extension - API is in open beta
13
- #: (?ad_extension_id_filter: String?, ?ad_extension_status_filter: String?, ?ad_extension_type_filter: String?, ?ad_group_id_filter: String?, ?ad_id_filter: String?, ?ad_product_filter: String?, ?max_results: Integer?, ?next_token: String?, ?state_filter: String?) -> HTTP::Response
12
+ #: (?ad_extension_id_filter: untyped?, ?ad_extension_status_filter: untyped?, ?ad_extension_type_filter: untyped?, ?ad_group_id_filter: untyped?, ?ad_id_filter: untyped?, ?ad_product_filter: untyped?, ?max_results: Integer?, ?next_token: String?, ?state_filter: untyped?) -> HTTP::Response
14
13
  def query_ad_extension(ad_extension_id_filter: nil, ad_extension_status_filter: nil, ad_extension_type_filter: nil, ad_group_id_filter: nil, ad_id_filter: nil, ad_product_filter: nil, max_results: nil, next_token: nil, state_filter: nil)
15
14
  request(:post, "/adsApi/v1/query/adExtensions", json: { "adExtensionIdFilter" => ad_extension_id_filter, "adExtensionStatusFilter" => ad_extension_status_filter, "adExtensionTypeFilter" => ad_extension_type_filter, "adGroupIdFilter" => ad_group_id_filter, "adIdFilter" => ad_id_filter, "adProductFilter" => ad_product_filter, "maxResults" => max_results, "nextToken" => next_token, "stateFilter" => state_filter }.compact)
16
15
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class AdGroups < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # List ad groups
19
- #: (ad_product_filter: String, ?ad_group_id_filter: String?, ?campaign_id_filter: String?, ?marketplace_scope_filter: String?, ?max_results: Integer?, ?name_filter: String?, ?next_token: String?, ?state_filter: String?) -> HTTP::Response
18
+ #: (ad_product_filter: untyped, ?ad_group_id_filter: untyped?, ?campaign_id_filter: untyped?, ?marketplace_scope_filter: untyped?, ?max_results: Integer?, ?name_filter: untyped?, ?next_token: String?, ?state_filter: untyped?) -> HTTP::Response
20
19
  def query_ad_group(ad_product_filter:, ad_group_id_filter: nil, campaign_id_filter: nil, marketplace_scope_filter: nil, max_results: nil, name_filter: nil, next_token: nil, state_filter: nil)
21
20
  request(:post, "/adsApi/v1/query/adGroups", json: { "adGroupIdFilter" => ad_group_id_filter, "adProductFilter" => ad_product_filter, "campaignIdFilter" => campaign_id_filter, "marketplaceScopeFilter" => marketplace_scope_filter, "maxResults" => max_results, "nameFilter" => name_filter, "nextToken" => next_token, "stateFilter" => state_filter }.compact)
22
21
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class Ads < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # List ads
19
- #: (ad_product_filter: String, ?ad_group_id_filter: String?, ?ad_id_filter: String?, ?campaign_id_filter: String?, ?marketplace_scope_filter: String?, ?max_results: Integer?, ?name_filter: String?, ?next_token: String?, ?state_filter: String?) -> HTTP::Response
18
+ #: (ad_product_filter: untyped, ?ad_group_id_filter: untyped?, ?ad_id_filter: untyped?, ?campaign_id_filter: untyped?, ?marketplace_scope_filter: untyped?, ?max_results: Integer?, ?name_filter: untyped?, ?next_token: String?, ?state_filter: untyped?) -> HTTP::Response
20
19
  def query_ad(ad_product_filter:, ad_group_id_filter: nil, ad_id_filter: nil, campaign_id_filter: nil, marketplace_scope_filter: nil, max_results: nil, name_filter: nil, next_token: nil, state_filter: nil)
21
20
  request(:post, "/adsApi/v1/query/ads", json: { "adGroupIdFilter" => ad_group_id_filter, "adIdFilter" => ad_id_filter, "adProductFilter" => ad_product_filter, "campaignIdFilter" => campaign_id_filter, "marketplaceScopeFilter" => marketplace_scope_filter, "maxResults" => max_results, "nameFilter" => name_filter, "nextToken" => next_token, "stateFilter" => state_filter }.compact)
22
21
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class AdvertisingDealTargets < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # Query advertisingDealTarget
19
- #: (advertising_deal_id_filter: String, ?max_results: Integer?, ?next_token: String?) -> HTTP::Response
18
+ #: (advertising_deal_id_filter: untyped, ?max_results: Integer?, ?next_token: String?) -> HTTP::Response
20
19
  def sb_query_advertising_deal_target(advertising_deal_id_filter:, max_results: nil, next_token: nil)
21
20
  request(:post, "/adsApi/v1/query/advertisingDealTargets/sb", json: { "advertisingDealIdFilter" => advertising_deal_id_filter, "maxResults" => max_results, "nextToken" => next_token }.compact)
22
21
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class AdvertisingDeals < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # Query advertisingDeal
19
- #: (?advertising_deal_id_filter: String?, ?max_results: Integer?, ?name_filter: String?, ?next_token: String?) -> HTTP::Response
18
+ #: (?advertising_deal_id_filter: untyped?, ?max_results: Integer?, ?name_filter: untyped?, ?next_token: String?) -> HTTP::Response
20
19
  def sb_query_advertising_deal(advertising_deal_id_filter: nil, max_results: nil, name_filter: nil, next_token: nil)
21
20
  request(:post, "/adsApi/v1/query/advertisingDeals/sb", json: { "advertisingDealIdFilter" => advertising_deal_id_filter, "maxResults" => max_results, "nameFilter" => name_filter, "nextToken" => next_token }.compact)
22
21
  end
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class BrandStoreEditionPublishVersions < API
6
5
  # Query store edition publish versions
7
- #: (edition_id_filter: String, publish_status_filter: String, store_id_filter: String, ?max_results: Integer?, ?next_token: String?) -> HTTP::Response
6
+ #: (edition_id_filter: untyped, publish_status_filter: untyped, store_id_filter: untyped, ?max_results: Integer?, ?next_token: String?) -> HTTP::Response
8
7
  def query_brand_store_edition_publish_version(edition_id_filter:, publish_status_filter:, store_id_filter:, max_results: nil, next_token: nil)
9
8
  request(:post, "/adsApi/v1/query/brandStoreEditionPublishVersions", json: { "editionIdFilter" => edition_id_filter, "maxResults" => max_results, "nextToken" => next_token, "publishStatusFilter" => publish_status_filter, "storeIdFilter" => store_id_filter }.compact)
10
9
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class BrandStoreEditions < API
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class BrandStorePages < API
6
5
  # Retrieve brand store page content
7
- #: (edition_id_filter: String, page_id_filter: String, store_id_filter: String, ?max_results: Integer?, ?next_token: String?, ?store_edition_publish_id_filter: String?) -> HTTP::Response
6
+ #: (edition_id_filter: untyped, page_id_filter: untyped, store_id_filter: untyped, ?max_results: Integer?, ?next_token: String?, ?store_edition_publish_id_filter: untyped?) -> HTTP::Response
8
7
  def query_brand_store_page(edition_id_filter:, page_id_filter:, store_id_filter:, max_results: nil, next_token: nil, store_edition_publish_id_filter: nil)
9
8
  request(:post, "/adsApi/v1/query/brandStorePages", json: { "editionIdFilter" => edition_id_filter, "maxResults" => max_results, "nextToken" => next_token, "pageIdFilter" => page_id_filter, "storeEditionPublishIdFilter" => store_edition_publish_id_filter, "storeIdFilter" => store_id_filter }.compact)
10
9
  end
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class BrandStores < API
6
5
  # Query brand store content
7
- #: (store_name_filter: String, ?max_results: Integer?, ?next_token: String?, ?sort: Array[untyped]?) -> HTTP::Response
6
+ #: (store_name_filter: untyped, ?max_results: Integer?, ?next_token: String?, ?sort: Array[untyped]?) -> HTTP::Response
8
7
  def query_brand_store(store_name_filter:, max_results: nil, next_token: nil, sort: nil)
9
8
  request(:post, "/adsApi/v1/query/brandStores", json: { "maxResults" => max_results, "nextToken" => next_token, "sort" => sort, "storeNameFilter" => store_name_filter }.compact)
10
9
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class BrandedKeywordsPricings < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class CampaignForecasts < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class Campaigns < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # Query campaign
19
- #: (ad_product_filter: String, ?campaign_id_filter: String?, ?goal_filter: String?, ?marketplace_scope_filter: String?, ?max_results: Integer?, ?name_filter: String?, ?next_token: String?, ?portfolio_id_filter: String?, ?state_filter: String?) -> HTTP::Response
18
+ #: (ad_product_filter: untyped, ?campaign_id_filter: untyped?, ?goal_filter: untyped?, ?marketplace_scope_filter: untyped?, ?max_results: Integer?, ?name_filter: untyped?, ?next_token: String?, ?portfolio_id_filter: untyped?, ?state_filter: untyped?) -> HTTP::Response
20
19
  def query_campaign(ad_product_filter:, campaign_id_filter: nil, goal_filter: nil, marketplace_scope_filter: nil, max_results: nil, name_filter: nil, next_token: nil, portfolio_id_filter: nil, state_filter: nil)
21
20
  request(:post, "/adsApi/v1/query/campaigns", json: { "adProductFilter" => ad_product_filter, "campaignIdFilter" => campaign_id_filter, "goalFilter" => goal_filter, "marketplaceScopeFilter" => marketplace_scope_filter, "maxResults" => max_results, "nameFilter" => name_filter, "nextToken" => next_token, "portfolioIdFilter" => portfolio_id_filter, "stateFilter" => state_filter }.compact)
22
21
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class CommitmentSpends < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class Commitments < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class KeywordReservationValidations < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  # Amazon Marketing Stream
@@ -9,7 +8,7 @@ module AmazonAds
9
8
  # @rbs data_set_id: String -- Identifier of data set, callers can be subscribed to. Please refer to https://advertising.amazon.com/API/docs/en-us/amazon-marketing-stream/data-guide for the list of all data sets.
10
9
  # @rbs destination_arn: String -- AWS ARN of the destination endpoint associated with the subscription. Supported destination types: - SQS
11
10
  # @rbs notes: String -- Additional details associated with the subscription
12
- #: (client_request_token: String, data_set_id: String, ?destination: String?, ?destination_arn: String?, ?notes: String?) -> HTTP::Response
11
+ #: (client_request_token: String, data_set_id: String, ?destination: untyped?, ?destination_arn: String?, ?notes: String?) -> HTTP::Response
13
12
  def create_dsp_stream_subscription(client_request_token:, data_set_id:, destination: nil, destination_arn: nil, notes: nil)
14
13
  request(:post, "/dsp/streams/subscriptions", json: { "clientRequestToken" => client_request_token, "dataSetId" => data_set_id, "destination" => destination, "destinationArn" => destination_arn, "notes" => notes }.compact, headers: { "Content-Type" => "application/vnd.amazonmarketingstreamsubscriptions.v1+json" })
15
14
  end
@@ -19,7 +18,7 @@ module AmazonAds
19
18
  # @rbs data_set_id: String -- Identifier of data set, callers can be subscribed to. Please refer to https://advertising.amazon.com/API/docs/en-us/amazon-marketing-stream/data-guide for the list of all data sets.
20
19
  # @rbs destination_arn: String -- AWS ARN of the destination endpoint associated with the subscription. Supported destination types: - SQS
21
20
  # @rbs notes: String -- Additional details associated with the subscription
22
- #: (client_request_token: String, data_set_id: String, ?destination: String?, ?destination_arn: String?, ?notes: String?) -> HTTP::Response
21
+ #: (client_request_token: String, data_set_id: String, ?destination: untyped?, ?destination_arn: String?, ?notes: String?) -> HTTP::Response
23
22
  def create_stream_subscription(client_request_token:, data_set_id:, destination: nil, destination_arn: nil, notes: nil)
24
23
  request(:post, "/streams/subscriptions", json: { "clientRequestToken" => client_request_token, "dataSetId" => data_set_id, "destination" => destination, "destinationArn" => destination_arn, "notes" => notes }.compact, headers: { "Content-Type" => "application/vnd.amazonmarketingstreamsubscriptions.v1+json" })
25
24
  end
@@ -57,7 +56,7 @@ module AmazonAds
57
56
  # Update an existing subscription Note: trailing slash in request uri is not allowed
58
57
  # @rbs subscription_id: String -- Unique subscription identifier
59
58
  # @rbs notes: String -- Additional details associated with the subscription
60
- #: (String, ?notes: String?, ?status: String?) -> HTTP::Response
59
+ #: (String, ?notes: String?, ?status: untyped?) -> HTTP::Response
61
60
  def update_dsp_stream_subscription(subscription_id, notes: nil, status: nil)
62
61
  request(:put, "/dsp/streams/subscriptions/#{subscription_id}", json: { "notes" => notes, "status" => status }.compact, headers: { "Content-Type" => "application/vnd.amazonmarketingstreamsubscriptions.v1+json" })
63
62
  end
@@ -65,7 +64,7 @@ module AmazonAds
65
64
  # Update an existing subscription Note: trailing slash in request uri is not allowed
66
65
  # @rbs subscription_id: String -- Unique subscription identifier
67
66
  # @rbs notes: String -- Additional details associated with the subscription
68
- #: (String, ?notes: String?, ?status: String?) -> HTTP::Response
67
+ #: (String, ?notes: String?, ?status: untyped?) -> HTTP::Response
69
68
  def update_stream_subscription(subscription_id, notes: nil, status: nil)
70
69
  request(:put, "/streams/subscriptions/#{subscription_id}", json: { "notes" => notes, "status" => status }.compact, headers: { "Content-Type" => "application/vnd.amazonmarketingstreamsubscriptions.v1+json" })
71
70
  end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  # Amazon Ads API - Profiles
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class RecommendationTypes < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class Recommendations < API
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  # Offline Report
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rbs_inline: enabled
3
2
 
4
3
  module AmazonAds
5
4
  class Targets < API
@@ -16,7 +15,7 @@ module AmazonAds
16
15
  end
17
16
 
18
17
  # List target
19
- #: (ad_product_filter: String, ?ad_group_id_filter: String?, ?campaign_id_filter: String?, ?keyword_filter: String?, ?marketplace_scope_filter: String?, ?match_type_filter: String?, ?max_results: Integer?, ?native_language_locale_filter: String?, ?negative_filter: String?, ?next_token: String?, ?product_id_filter: String?, ?state_filter: String?, ?target_id_filter: String?, ?target_type_filter: String?) -> HTTP::Response
18
+ #: (ad_product_filter: untyped, ?ad_group_id_filter: untyped?, ?campaign_id_filter: untyped?, ?keyword_filter: untyped?, ?marketplace_scope_filter: untyped?, ?match_type_filter: untyped?, ?max_results: Integer?, ?native_language_locale_filter: untyped?, ?negative_filter: untyped?, ?next_token: String?, ?product_id_filter: untyped?, ?state_filter: untyped?, ?target_id_filter: untyped?, ?target_type_filter: untyped?) -> HTTP::Response
20
19
  def query_target(ad_product_filter:, ad_group_id_filter: nil, campaign_id_filter: nil, keyword_filter: nil, marketplace_scope_filter: nil, match_type_filter: nil, max_results: nil, native_language_locale_filter: nil, negative_filter: nil, next_token: nil, product_id_filter: nil, state_filter: nil, target_id_filter: nil, target_type_filter: nil)
21
20
  request(:post, "/adsApi/v1/query/targets", json: { "adGroupIdFilter" => ad_group_id_filter, "adProductFilter" => ad_product_filter, "campaignIdFilter" => campaign_id_filter, "keywordFilter" => keyword_filter, "marketplaceScopeFilter" => marketplace_scope_filter, "matchTypeFilter" => match_type_filter, "maxResults" => max_results, "nativeLanguageLocaleFilter" => native_language_locale_filter, "negativeFilter" => negative_filter, "nextToken" => next_token, "productIdFilter" => product_id_filter, "stateFilter" => state_filter, "targetIdFilter" => target_id_filter, "targetTypeFilter" => target_type_filter }.compact)
22
21
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "http"
4
+
5
+ module AmazonAds
6
+ # Raised when the API or LWA responds with a 4xx or 5xx
7
+ class Error < StandardError
8
+ # The failed response
9
+ attr_reader :response #: HTTP::Response?
10
+
11
+ #: (HTTP::Response) -> Error
12
+ def self.build(response)
13
+ response.flush # memoize the body while the connection is still readable
14
+ new(response.status.to_s, response)
15
+ end
16
+
17
+ #: (?String?, ?HTTP::Response?) -> void
18
+ def initialize(msg = nil, response = nil)
19
+ @response = response
20
+ super(msg)
21
+ end
22
+
23
+ #: () -> Integer?
24
+ def status
25
+ response&.status&.code
26
+ end
27
+
28
+ # Supports pattern matching on status
29
+ #
30
+ # case error
31
+ # in status: 429 then backoff
32
+ # in status: 500..599 then retry
33
+ # end
34
+ #
35
+ #: (Array[Symbol]?) -> Hash[Symbol, untyped]
36
+ def deconstruct_keys(keys)
37
+ hash = { status: status }
38
+ keys ? hash.slice(*keys) : hash
39
+ end
40
+ end
41
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rbs_inline: enabled
4
-
5
3
  require "http"
6
4
 
7
5
  module AmazonAds
@@ -14,11 +12,9 @@ module AmazonAds
14
12
  # The OAuth refresh token
15
13
  attr_reader :refresh_token #: String
16
14
 
17
- class << self
18
- #: (**untyped) -> Hash[String, untyped]
19
- def request(...)
20
- new(...).request
21
- end
15
+ #: (refresh_token: String, ?http: untyped) -> Hash[String, untyped]
16
+ def self.request(...)
17
+ new(...).request
22
18
  end
23
19
 
24
20
  #: (refresh_token: String, ?http: untyped) -> void
@@ -30,16 +26,14 @@ module AmazonAds
30
26
  # Requests a fresh access token from LWA
31
27
  #: () -> Hash[String, untyped]
32
28
  def request
33
- http.post(URL, form: params).parse
29
+ response = @http.post(URL, form: params)
30
+ raise Error.build(response) if response.code >= 400
31
+
32
+ response.parse
34
33
  end
35
34
 
36
35
  private
37
36
 
38
- #: () -> HTTP::Client
39
- def http
40
- @http.use(:raise_error)
41
- end
42
-
43
37
  #: () -> Hash[Symbol, String]
44
38
  def params
45
39
  {
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AmazonAds
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/amazon_ads.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rbs_inline: enabled
4
-
5
3
  require "zeitwerk"
6
4
 
7
5
  loader = Zeitwerk::Loader.for_gem
@@ -13,38 +11,36 @@ loader.setup
13
11
  # Amazon Ads API client for Ruby
14
12
  module AmazonAds
15
13
  class << self
16
- # Returns the client ID
17
- # Falls back to the `AMAZON_ADS_CLIENT_ID` env var
18
- #: () -> String?
19
- def client_id
20
- @client_id || ENV["AMAZON_ADS_CLIENT_ID"]
21
- end
22
-
23
14
  # Sets the client ID
24
- #: (String?) -> String?
25
- attr_writer :client_id
26
-
27
- # Returns the client ID or raises
28
- #: () -> String
29
- def client_id!
30
- client_id or raise ArgumentError, "client id is required"
31
- end
32
-
33
- # Returns the client secret
34
- # Falls back to the `AMAZON_ADS_CLIENT_SECRET` env var
35
- #: () -> String?
36
- def client_secret
37
- @client_secret || ENV["AMAZON_ADS_CLIENT_SECRET"]
38
- end
15
+ attr_writer :client_id #: String?
39
16
 
40
17
  # Sets the client secret
41
- #: (String?) -> String?
42
- attr_writer :client_secret
43
-
44
- # Returns the client secret or raises
45
- #: () -> String
46
- def client_secret!
47
- client_secret or raise ArgumentError, "client secret is required"
48
- end
18
+ attr_writer :client_secret #: String?
19
+ end
20
+
21
+ # Returns the client ID
22
+ # Falls back to the `AMAZON_ADS_CLIENT_ID` env var
23
+ #: () -> String?
24
+ def self.client_id
25
+ @client_id || ENV["AMAZON_ADS_CLIENT_ID"]
26
+ end
27
+
28
+ # Returns the client ID or raises
29
+ #: () -> String
30
+ def self.client_id!
31
+ client_id or raise ArgumentError, "client id is required"
32
+ end
33
+
34
+ # Returns the client secret
35
+ # Falls back to the `AMAZON_ADS_CLIENT_SECRET` env var
36
+ #: () -> String?
37
+ def self.client_secret
38
+ @client_secret || ENV["AMAZON_ADS_CLIENT_SECRET"]
39
+ end
40
+
41
+ # Returns the client secret or raises
42
+ #: () -> String
43
+ def self.client_secret!
44
+ client_secret or raise ArgumentError, "client secret is required"
49
45
  end
50
46
  end