helo-email-sdk 1.0.0.pre.beta.1
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/lib/helo/api_error.rb +23 -0
- data/lib/helo/apis/activity.rb +24 -0
- data/lib/helo/apis/broadcasts.rb +30 -0
- data/lib/helo/apis/channels.rb +35 -0
- data/lib/helo/apis/domains.rb +45 -0
- data/lib/helo/apis/sending.rb +43 -0
- data/lib/helo/apis/statistics.rb +25 -0
- data/lib/helo/apis/suppressions.rb +25 -0
- data/lib/helo/apis/webhooks.rb +40 -0
- data/lib/helo/client.rb +20 -0
- data/lib/helo/configuration.rb +9 -0
- data/lib/helo/core/api.rb +22 -0
- data/lib/helo/core/api_error.rb +23 -0
- data/lib/helo/core/array_type.rb +32 -0
- data/lib/helo/core/client.rb +75 -0
- data/lib/helo/core/configuration.rb +18 -0
- data/lib/helo/core/model.rb +129 -0
- data/lib/helo/core/model_type.rb +32 -0
- data/lib/helo/enums/attachment_disposition.rb +12 -0
- data/lib/helo/enums/broadcast_status.rb +14 -0
- data/lib/helo/enums/delivery_type.rb +12 -0
- data/lib/helo/enums/dns_record_status.rb +14 -0
- data/lib/helo/enums/dns_record_type.rb +12 -0
- data/lib/helo/enums/event_type.rb +19 -0
- data/lib/helo/enums/mail_type.rb +12 -0
- data/lib/helo/enums/suppression_reason.rb +14 -0
- data/lib/helo/enums/webhook_event.rb +19 -0
- data/lib/helo/models/accepted_webhook_payload.rb +17 -0
- data/lib/helo/models/activity_event.rb +19 -0
- data/lib/helo/models/activity_list_events_request.rb +20 -0
- data/lib/helo/models/activity_list_messages_request.rb +19 -0
- data/lib/helo/models/activity_mail_address.rb +10 -0
- data/lib/helo/models/attachment.rb +13 -0
- data/lib/helo/models/bounced_webhook_payload.rb +18 -0
- data/lib/helo/models/broadcast_content.rb +15 -0
- data/lib/helo/models/broadcast_content_attachment.rb +11 -0
- data/lib/helo/models/broadcast_content_template.rb +11 -0
- data/lib/helo/models/broadcast_details_response.rb +19 -0
- data/lib/helo/models/broadcast_failure_response.rb +12 -0
- data/lib/helo/models/broadcast_response.rb +14 -0
- data/lib/helo/models/broadcast_statistics.rb +15 -0
- data/lib/helo/models/broadcast_tracking.rb +10 -0
- data/lib/helo/models/broadcasts_list_failures_request.rb +11 -0
- data/lib/helo/models/broadcasts_list_request.rb +14 -0
- data/lib/helo/models/broadcasts_list_suppressions_request.rb +11 -0
- data/lib/helo/models/channel_basic_response.rb +12 -0
- data/lib/helo/models/channel_details_response.rb +14 -0
- data/lib/helo/models/channel_tracking.rb +10 -0
- data/lib/helo/models/channels_list_request.rb +14 -0
- data/lib/helo/models/clicked_webhook_payload.rb +18 -0
- data/lib/helo/models/complained_webhook_payload.rb +18 -0
- data/lib/helo/models/create_channel_request.rb +11 -0
- data/lib/helo/models/create_channel_tracking.rb +10 -0
- data/lib/helo/models/create_domain_request.rb +10 -0
- data/lib/helo/models/create_suppressions_request.rb +11 -0
- data/lib/helo/models/create_suppressions_response.rb +9 -0
- data/lib/helo/models/create_webhook_request.rb +13 -0
- data/lib/helo/models/delivered_webhook_payload.rb +18 -0
- data/lib/helo/models/delivery_stats.rb +15 -0
- data/lib/helo/models/dns_record_response.rb +13 -0
- data/lib/helo/models/dns_records_response.rb +13 -0
- data/lib/helo/models/domain_channel_response.rb +12 -0
- data/lib/helo/models/domain_response.rb +13 -0
- data/lib/helo/models/domain_with_dns_response.rb +14 -0
- data/lib/helo/models/domains_list_request.rb +13 -0
- data/lib/helo/models/error_response.rb +16 -0
- data/lib/helo/models/mail_address.rb +10 -0
- data/lib/helo/models/message.rb +17 -0
- data/lib/helo/models/message_details_response.rb +30 -0
- data/lib/helo/models/message_details_response_attachment.rb +11 -0
- data/lib/helo/models/message_details_response_event.rb +12 -0
- data/lib/helo/models/message_details_response_tracking.rb +10 -0
- data/lib/helo/models/opened_webhook_payload.rb +18 -0
- data/lib/helo/models/paginated_events_response.rb +11 -0
- data/lib/helo/models/paginated_messages_response.rb +11 -0
- data/lib/helo/models/paginated_response_of_broadcast.rb +10 -0
- data/lib/helo/models/paginated_response_of_broadcast_failure.rb +10 -0
- data/lib/helo/models/paginated_response_of_broadcast_suppression.rb +10 -0
- data/lib/helo/models/paginated_response_of_domain_response.rb +10 -0
- data/lib/helo/models/paginated_response_of_suppression_response.rb +10 -0
- data/lib/helo/models/pagination_result_of_channel_basic_response.rb +10 -0
- data/lib/helo/models/pagination_result_of_webhook_response.rb +10 -0
- data/lib/helo/models/processed_webhook_payload.rb +17 -0
- data/lib/helo/models/recipient_event_fields.rb +10 -0
- data/lib/helo/models/recipient_headers.rb +11 -0
- data/lib/helo/models/remove_suppression_result.rb +11 -0
- data/lib/helo/models/remove_suppressions_request.rb +11 -0
- data/lib/helo/models/remove_suppressions_response.rb +9 -0
- data/lib/helo/models/resubscribed_webhook_payload.rb +18 -0
- data/lib/helo/models/send_broadcast_request.rb +17 -0
- data/lib/helo/models/send_broadcast_request_message.rb +15 -0
- data/lib/helo/models/send_broadcast_request_template.rb +13 -0
- data/lib/helo/models/send_broadcast_request_tracking.rb +10 -0
- data/lib/helo/models/send_broadcast_response.rb +10 -0
- data/lib/helo/models/send_message_accepted_response.rb +11 -0
- data/lib/helo/models/send_message_batch_request.rb +9 -0
- data/lib/helo/models/send_message_batch_response.rb +9 -0
- data/lib/helo/models/send_message_failed_response.rb +11 -0
- data/lib/helo/models/send_message_request.rb +22 -0
- data/lib/helo/models/send_message_request_template.rb +13 -0
- data/lib/helo/models/send_message_request_tracking.rb +10 -0
- data/lib/helo/models/send_message_response.rb +8 -0
- data/lib/helo/models/statistics_daily_response.rb +9 -0
- data/lib/helo/models/statistics_daily_response_result.rb +11 -0
- data/lib/helo/models/statistics_hourly_response.rb +9 -0
- data/lib/helo/models/statistics_hourly_response_result.rb +11 -0
- data/lib/helo/models/statistics_retrieve_daily_request.rb +14 -0
- data/lib/helo/models/statistics_retrieve_hourly_request.rb +13 -0
- data/lib/helo/models/statistics_retrieve_totals_request.rb +13 -0
- data/lib/helo/models/statistics_totals_response.rb +10 -0
- data/lib/helo/models/suppression_response.rb +11 -0
- data/lib/helo/models/suppression_result.rb +11 -0
- data/lib/helo/models/suppressions_list_request.rb +15 -0
- data/lib/helo/models/unsubscribed_webhook_payload.rb +18 -0
- data/lib/helo/models/update_channel_request.rb +11 -0
- data/lib/helo/models/update_channel_tracking.rb +10 -0
- data/lib/helo/models/update_domain_request.rb +9 -0
- data/lib/helo/models/update_webhook_request.rb +13 -0
- data/lib/helo/models/validation_error.rb +9 -0
- data/lib/helo/models/webhook_header.rb +10 -0
- data/lib/helo/models/webhook_last_response.rb +11 -0
- data/lib/helo/models/webhook_payload_common.rb +15 -0
- data/lib/helo/models/webhook_response.rb +16 -0
- data/lib/helo/models/webhooks_list_request.rb +12 -0
- data/lib/helo/version.rb +5 -0
- data/lib/helo-email-sdk.rb +3 -0
- data/lib/helo.rb +35 -0
- metadata +239 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 298571a7c53335cc539139041493cb71bdb10a8c94cb01bf88bf64027b59bfec
|
|
4
|
+
data.tar.gz: eeadd57916455673769b3918e151651b47f677d6b918a8a1fb43bab81caa51bd
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 30bf674dca548f389a28f107da2f878ac9b4b7bb9e27b2ca25964421ddfd4f5e9f519b81a6c1439fa9b013e1cd98181ea9adf2e52ecffd5d00305914c766e0ce
|
|
7
|
+
data.tar.gz: ec8aa5f075af43c849b1ec6d3c37d650e6fbdf1a473bc597729acc381467e3f8762f80424e468c1b5d6090e11bf64c53eda7d4a3578c1dbbf1863c3063b74c79
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Helo
|
|
6
|
+
class APIError < Helo::Core::APIError
|
|
7
|
+
def detail
|
|
8
|
+
json_response.fetch(:detail, ["API Error", code, @message].compact.join(" - "))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def errors
|
|
12
|
+
json_response
|
|
13
|
+
.fetch(:errors, {})
|
|
14
|
+
.transform_keys(&:to_s)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def json_response
|
|
20
|
+
@_json_response ||= response_body.try(:deep_symbolize_keys) || {}
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Activity < API
|
|
5
|
+
def list_events(request_data = {})
|
|
6
|
+
request = ActivityListEventsRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/activity/events", params: request.to_params)
|
|
8
|
+
PaginatedEventsResponse.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def list_messages(request_data = {})
|
|
12
|
+
request = ActivityListMessagesRequest.new(request_data)
|
|
13
|
+
response = @client.request(:get, "/activity/messages", params: request.to_params)
|
|
14
|
+
PaginatedMessagesResponse.from_hash(response.body)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve_message(id)
|
|
18
|
+
response = @client.request(:get, "/activity/messages/#{id}")
|
|
19
|
+
MessageDetailsResponse.from_hash(response.body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class_methods :list_events, :list_messages, :retrieve_message
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Broadcasts < API
|
|
5
|
+
def list(request_data = {})
|
|
6
|
+
request = BroadcastsListRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/broadcasts", params: request.to_params)
|
|
8
|
+
PaginatedResponseOfBroadcast.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def retrieve(id)
|
|
12
|
+
response = @client.request(:get, "/broadcasts/#{id}")
|
|
13
|
+
BroadcastDetailsResponse.from_hash(response.body)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def list_failures(id, request_data = {})
|
|
17
|
+
request = BroadcastsListFailuresRequest.new(request_data)
|
|
18
|
+
response = @client.request(:get, "/broadcasts/#{id}/failures", params: request.to_params)
|
|
19
|
+
PaginatedResponseOfBroadcastFailure.from_hash(response.body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def list_suppressions(id, request_data = {})
|
|
23
|
+
request = BroadcastsListSuppressionsRequest.new(request_data)
|
|
24
|
+
response = @client.request(:get, "/broadcasts/#{id}/suppressions", params: request.to_params)
|
|
25
|
+
PaginatedResponseOfBroadcastSuppression.from_hash(response.body)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class_methods :list, :retrieve, :list_failures, :list_suppressions
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Channels < API
|
|
5
|
+
def list(request_data = {})
|
|
6
|
+
request = ChannelsListRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/channels", params: request.to_params)
|
|
8
|
+
PaginationResultOfChannelBasicResponse.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create(request_data)
|
|
12
|
+
request = CreateChannelRequest.new(request_data)
|
|
13
|
+
response = @client.request(:post, "/channels", body: request.to_params)
|
|
14
|
+
ChannelDetailsResponse.from_hash(response.body)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve(id)
|
|
18
|
+
response = @client.request(:get, "/channels/#{id}")
|
|
19
|
+
ChannelDetailsResponse.from_hash(response.body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update(id, request_data)
|
|
23
|
+
request = UpdateChannelRequest.new(request_data)
|
|
24
|
+
response = @client.request(:patch, "/channels/#{id}", body: request.to_params)
|
|
25
|
+
ChannelDetailsResponse.from_hash(response.body)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(id)
|
|
29
|
+
response = @client.request(:delete, "/channels/#{id}")
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class_methods :list, :create, :retrieve, :update, :delete
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Domains < API
|
|
5
|
+
def list(request_data = {})
|
|
6
|
+
request = DomainsListRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/domains", params: request.to_params)
|
|
8
|
+
PaginatedResponseOfDomainResponse.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create(request_data)
|
|
12
|
+
request = CreateDomainRequest.new(request_data)
|
|
13
|
+
response = @client.request(:post, "/domains", body: request.to_params)
|
|
14
|
+
DomainWithDnsResponse.from_hash(response.body)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve(id)
|
|
18
|
+
response = @client.request(:get, "/domains/#{id}")
|
|
19
|
+
DomainWithDnsResponse.from_hash(response.body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update(id, request_data)
|
|
23
|
+
request = UpdateDomainRequest.new(request_data)
|
|
24
|
+
response = @client.request(:patch, "/domains/#{id}", body: request.to_params)
|
|
25
|
+
DomainResponse.from_hash(response.body)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(id)
|
|
29
|
+
response = @client.request(:delete, "/domains/#{id}")
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def verify(id)
|
|
34
|
+
response = @client.request(:post, "/domains/#{id}/verify")
|
|
35
|
+
DnsRecordsResponse.from_hash(response.body)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def rotate_key(id)
|
|
39
|
+
response = @client.request(:post, "/domains/#{id}/rotate-key")
|
|
40
|
+
DnsRecordResponse.from_hash(response.body)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class_methods :list, :create, :retrieve, :update, :delete, :verify, :rotate_key
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Sending < API
|
|
5
|
+
def transactional(request_data, channel_id: nil, idempotency_key: nil)
|
|
6
|
+
request = SendMessageRequest.new(request_data)
|
|
7
|
+
headers = {}
|
|
8
|
+
headers["X-Helo-Channel-Id"] = channel_id unless channel_id.nil?
|
|
9
|
+
headers["X-Helo-Idempotency-Key"] = idempotency_key unless idempotency_key.nil?
|
|
10
|
+
response = @client.request(:post, "/send/transactional", body: request.to_params, headers: headers)
|
|
11
|
+
SendMessageAcceptedResponse.from_hash(response.body)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def transactional_batch(request_data, channel_id: nil, idempotency_key: nil)
|
|
15
|
+
request = SendMessageBatchRequest.new(request_data)
|
|
16
|
+
headers = {}
|
|
17
|
+
headers["X-Helo-Channel-Id"] = channel_id unless channel_id.nil?
|
|
18
|
+
headers["X-Helo-Idempotency-Key"] = idempotency_key unless idempotency_key.nil?
|
|
19
|
+
response = @client.request(:post, "/send/transactional/batch", body: request.to_params, headers: headers)
|
|
20
|
+
SendMessageBatchResponse.from_hash(response.body)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def broadcast(request_data, channel_id: nil, idempotency_key: nil)
|
|
24
|
+
request = SendBroadcastRequest.new(request_data)
|
|
25
|
+
headers = {}
|
|
26
|
+
headers["X-Helo-Channel-Id"] = channel_id unless channel_id.nil?
|
|
27
|
+
headers["X-Helo-Idempotency-Key"] = idempotency_key unless idempotency_key.nil?
|
|
28
|
+
response = @client.request(:post, "/send/broadcast", body: request.to_params, headers: headers)
|
|
29
|
+
SendBroadcastResponse.from_hash(response.body)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def broadcast_message(request_data, channel_id: nil, idempotency_key: nil)
|
|
33
|
+
request = SendMessageRequest.new(request_data)
|
|
34
|
+
headers = {}
|
|
35
|
+
headers["X-Helo-Channel-Id"] = channel_id unless channel_id.nil?
|
|
36
|
+
headers["X-Helo-Idempotency-Key"] = idempotency_key unless idempotency_key.nil?
|
|
37
|
+
response = @client.request(:post, "/send/broadcast/message", body: request.to_params, headers: headers)
|
|
38
|
+
SendMessageAcceptedResponse.from_hash(response.body)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class_methods :transactional, :transactional_batch, :broadcast, :broadcast_message
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Statistics < API
|
|
5
|
+
def retrieve_hourly(request_data = {})
|
|
6
|
+
request = StatisticsRetrieveHourlyRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/activity/statistics/hourly", params: request.to_params)
|
|
8
|
+
StatisticsHourlyResponse.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def retrieve_daily(request_data = {})
|
|
12
|
+
request = StatisticsRetrieveDailyRequest.new(request_data)
|
|
13
|
+
response = @client.request(:get, "/activity/statistics/daily", params: request.to_params)
|
|
14
|
+
StatisticsDailyResponse.from_hash(response.body)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve_totals(request_data = {})
|
|
18
|
+
request = StatisticsRetrieveTotalsRequest.new(request_data)
|
|
19
|
+
response = @client.request(:get, "/activity/statistics/totals", params: request.to_params)
|
|
20
|
+
StatisticsTotalsResponse.from_hash(response.body)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class_methods :retrieve_hourly, :retrieve_daily, :retrieve_totals
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Suppressions < API
|
|
5
|
+
def list(request_data = {})
|
|
6
|
+
request = SuppressionsListRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/suppressions", params: request.to_params)
|
|
8
|
+
PaginatedResponseOfSuppressionResponse.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create(request_data)
|
|
12
|
+
request = CreateSuppressionsRequest.new(request_data)
|
|
13
|
+
response = @client.request(:post, "/suppressions", body: request.to_params)
|
|
14
|
+
CreateSuppressionsResponse.from_hash(response.body)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def remove(request_data)
|
|
18
|
+
request = RemoveSuppressionsRequest.new(request_data)
|
|
19
|
+
response = @client.request(:post, "/suppressions/remove", body: request.to_params)
|
|
20
|
+
RemoveSuppressionsResponse.from_hash(response.body)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class_methods :list, :create, :remove
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Webhooks < API
|
|
5
|
+
def list(request_data = {})
|
|
6
|
+
request = WebhooksListRequest.new(request_data)
|
|
7
|
+
response = @client.request(:get, "/webhooks", params: request.to_params)
|
|
8
|
+
PaginationResultOfWebhookResponse.from_hash(response.body)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create(request_data)
|
|
12
|
+
request = CreateWebhookRequest.new(request_data)
|
|
13
|
+
response = @client.request(:post, "/webhooks", body: request.to_params)
|
|
14
|
+
WebhookResponse.from_hash(response.body)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def retrieve(id)
|
|
18
|
+
response = @client.request(:get, "/webhooks/#{id}")
|
|
19
|
+
WebhookResponse.from_hash(response.body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def update(id, request_data)
|
|
23
|
+
request = UpdateWebhookRequest.new(request_data)
|
|
24
|
+
response = @client.request(:patch, "/webhooks/#{id}", body: request.to_params)
|
|
25
|
+
WebhookResponse.from_hash(response.body)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete(id)
|
|
29
|
+
response = @client.request(:delete, "/webhooks/#{id}")
|
|
30
|
+
nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def regenerate_signing_key(id)
|
|
34
|
+
response = @client.request(:post, "/webhooks/#{id}/regenerate-signing-key")
|
|
35
|
+
WebhookResponse.from_hash(response.body)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class_methods :list, :create, :retrieve, :update, :delete, :regenerate_signing_key
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/helo/client.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo
|
|
4
|
+
class Client < Helo::Core::Client
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def handle_error_response(response)
|
|
8
|
+
raise APIError.new(
|
|
9
|
+
"Request failed",
|
|
10
|
+
code: response.status,
|
|
11
|
+
response_body: response.body,
|
|
12
|
+
response_headers: response.headers
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def handle_connection_error(exception)
|
|
17
|
+
raise APIError.new("Connection failed: #{exception.message}")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/class/attribute"
|
|
4
|
+
|
|
5
|
+
module Helo::Core
|
|
6
|
+
# Base class for all API resources
|
|
7
|
+
class API
|
|
8
|
+
class_attribute :default_client
|
|
9
|
+
|
|
10
|
+
def self.class_methods(*methods)
|
|
11
|
+
methods.each do |method|
|
|
12
|
+
define_singleton_method(method) do |*args, **kwargs, &block|
|
|
13
|
+
new(default_client).public_send(method, *args, **kwargs, &block)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(client)
|
|
19
|
+
@client = client
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo::Core
|
|
4
|
+
class APIError < StandardError
|
|
5
|
+
attr_reader :code, :response_body, :response_headers
|
|
6
|
+
|
|
7
|
+
def initialize(message = nil, code: nil, response_body: nil, response_headers: nil)
|
|
8
|
+
@message = message
|
|
9
|
+
@code = code
|
|
10
|
+
@response_body = response_body
|
|
11
|
+
@response_headers = response_headers
|
|
12
|
+
super(message)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def message
|
|
16
|
+
msg = @message
|
|
17
|
+
msg += "\nHTTP status code: #{code}" if code
|
|
18
|
+
msg += "\nResponse headers: #{response_headers}" if response_headers
|
|
19
|
+
msg += "\nResponse body: #{response_body}" if response_body
|
|
20
|
+
msg
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_model"
|
|
4
|
+
|
|
5
|
+
module Helo::Core
|
|
6
|
+
# Custom ActiveModel type for arrays of model objects
|
|
7
|
+
class ArrayType < ActiveModel::Type::Value
|
|
8
|
+
def initialize(model_class_name)
|
|
9
|
+
@model_class_name = model_class_name
|
|
10
|
+
super()
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def cast(value)
|
|
14
|
+
return if value.nil?
|
|
15
|
+
|
|
16
|
+
value.map do |item|
|
|
17
|
+
case item
|
|
18
|
+
when model_class
|
|
19
|
+
item
|
|
20
|
+
when Hash
|
|
21
|
+
model_class.from_hash(item)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def model_class
|
|
29
|
+
@_model_class ||= @model_class_name.constantize
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "faraday"
|
|
4
|
+
|
|
5
|
+
module Helo::Core
|
|
6
|
+
class Client
|
|
7
|
+
attr_reader :configuration
|
|
8
|
+
|
|
9
|
+
def initialize(configuration)
|
|
10
|
+
raise ArgumentError, "base_url is not configured" if configuration.base_url.to_s.empty?
|
|
11
|
+
|
|
12
|
+
@configuration = configuration
|
|
13
|
+
@connection = Faraday.new(url: configuration.base_url) do |f|
|
|
14
|
+
f.request :json
|
|
15
|
+
f.response :json
|
|
16
|
+
f.adapter Faraday.default_adapter
|
|
17
|
+
f.options.params_encoder = Faraday::FlatParamsEncoder
|
|
18
|
+
|
|
19
|
+
# Allow custom Faraday configuration
|
|
20
|
+
configuration.faraday_configuration_block&.call(f)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def request(method, path, params: {}, body: nil, headers: {})
|
|
25
|
+
response = connection.public_send(method, path) do |req|
|
|
26
|
+
req.params = params
|
|
27
|
+
req.body = body
|
|
28
|
+
|
|
29
|
+
# Set Authorization header with dynamic or static token
|
|
30
|
+
token = current_api_key
|
|
31
|
+
req.headers["Authorization"] = "Bearer #{token}" if token
|
|
32
|
+
|
|
33
|
+
# Apply per-request headers verbatim (already in wire form)
|
|
34
|
+
headers.each do |key, value|
|
|
35
|
+
req.headers[key.to_s] = value.to_s
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
handle_response(response)
|
|
40
|
+
rescue Faraday::ConnectionFailed, Faraday::TimeoutError => e
|
|
41
|
+
handle_connection_error(e)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
attr_reader :connection
|
|
47
|
+
|
|
48
|
+
def current_api_key
|
|
49
|
+
token = configuration.api_key
|
|
50
|
+
token.respond_to?(:call) ? token.call : token
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def handle_response(response)
|
|
54
|
+
case response.status
|
|
55
|
+
when 200..299
|
|
56
|
+
response
|
|
57
|
+
else
|
|
58
|
+
handle_error_response(response)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def handle_error_response(response)
|
|
63
|
+
raise APIError.new(
|
|
64
|
+
"Request failed",
|
|
65
|
+
code: response.status,
|
|
66
|
+
response_body: response.body,
|
|
67
|
+
response_headers: response.headers
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def handle_connection_error(exception)
|
|
72
|
+
raise APIError.new("Connection failed: #{exception.message}")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Helo::Core
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_accessor :base_url, :api_key
|
|
6
|
+
attr_reader :faraday_configuration_block
|
|
7
|
+
|
|
8
|
+
def initialize(base_url: nil, api_key: nil)
|
|
9
|
+
@base_url = base_url
|
|
10
|
+
@api_key = api_key
|
|
11
|
+
@faraday_configuration_block = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def configure_faraday_connection(&block)
|
|
15
|
+
@faraday_configuration_block = block
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_model"
|
|
4
|
+
require "active_support/concern"
|
|
5
|
+
require "date"
|
|
6
|
+
|
|
7
|
+
module Helo::Core
|
|
8
|
+
module Model
|
|
9
|
+
extend ActiveSupport::Concern
|
|
10
|
+
|
|
11
|
+
included do
|
|
12
|
+
include ActiveModel::AttributeAssignment
|
|
13
|
+
include ActiveModel::Attributes
|
|
14
|
+
include ActiveModel::Serializers::JSON
|
|
15
|
+
|
|
16
|
+
class_attribute :_api_attributes, default: {}
|
|
17
|
+
|
|
18
|
+
def initialize(attributes = {})
|
|
19
|
+
super()
|
|
20
|
+
assign_attributes(attributes) if attributes
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Serialize to hash for API requests (camelCase keys)
|
|
24
|
+
def to_params
|
|
25
|
+
result = {}
|
|
26
|
+
self.class._api_attributes.each do |attr_name, meta|
|
|
27
|
+
value = attributes[attr_name.to_s]
|
|
28
|
+
|
|
29
|
+
if value.nil?
|
|
30
|
+
next unless meta[:nullable] && @_explicitly_set&.include?(attr_name)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
result[meta[:json_key]] = serialize_for_api(value, meta)
|
|
34
|
+
end
|
|
35
|
+
result
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def to_h
|
|
39
|
+
attributes.to_h do |key, value|
|
|
40
|
+
[ key.to_sym, deep_to_h(value) ]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def slice(*keys)
|
|
45
|
+
attributes.symbolize_keys.slice(*keys.map(&:to_sym))
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def [](key)
|
|
49
|
+
attributes[key.to_s]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def []=(key, value)
|
|
53
|
+
assign_attributes(key => value)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def inspect
|
|
57
|
+
attrs = attributes.map { |k, v| "#{k}: #{v.inspect}" }.join(", ")
|
|
58
|
+
"#<#{self.class.name} #{attrs}>"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def _write_attribute(attr_name, value)
|
|
64
|
+
@_explicitly_set ||= Set.new
|
|
65
|
+
@_explicitly_set << attr_name.to_sym
|
|
66
|
+
super
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def deep_to_h(value)
|
|
70
|
+
if value.nil?
|
|
71
|
+
nil
|
|
72
|
+
elsif value.is_a?(Array)
|
|
73
|
+
value.map { |item| deep_to_h(item) }
|
|
74
|
+
elsif value.respond_to?(:to_h)
|
|
75
|
+
value.to_h
|
|
76
|
+
else
|
|
77
|
+
value
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def serialize_for_api(value, meta = {})
|
|
82
|
+
return value if value.nil?
|
|
83
|
+
|
|
84
|
+
case value
|
|
85
|
+
when Array
|
|
86
|
+
serialized = value.map { |item| serialize_for_api(item) }
|
|
87
|
+
meta[:explode] == false ? serialized.join(",") : serialized
|
|
88
|
+
when Time, DateTime
|
|
89
|
+
value.utc.iso8601
|
|
90
|
+
when Date
|
|
91
|
+
value.to_s
|
|
92
|
+
else
|
|
93
|
+
value.respond_to?(:to_params) ? value.to_params : value
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class_methods do
|
|
99
|
+
def new(input = {})
|
|
100
|
+
return input if input.is_a?(self)
|
|
101
|
+
super(input)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def api_attribute(name, type = nil, key:, nullable: false, explode: true)
|
|
105
|
+
attribute(name, type)
|
|
106
|
+
|
|
107
|
+
self._api_attributes[name] = {
|
|
108
|
+
json_key: key,
|
|
109
|
+
nullable: nullable,
|
|
110
|
+
explode: explode
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def from_hash(hash)
|
|
115
|
+
return if hash.nil?
|
|
116
|
+
|
|
117
|
+
hash = hash.transform_keys(&:to_sym)
|
|
118
|
+
|
|
119
|
+
attributes = _api_attributes.to_h do |attr_name, meta|
|
|
120
|
+
json_key = meta.fetch(:json_key).to_sym
|
|
121
|
+
value = hash[json_key] || hash[attr_name]
|
|
122
|
+
[ attr_name, value ]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
new(attributes)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_model"
|
|
4
|
+
|
|
5
|
+
module Helo::Core
|
|
6
|
+
# Custom ActiveModel type for nested model objects
|
|
7
|
+
class ModelType < ActiveModel::Type::Value
|
|
8
|
+
def initialize(model_class_name)
|
|
9
|
+
@model_class_name = model_class_name
|
|
10
|
+
super()
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def cast(value)
|
|
14
|
+
return if value.nil?
|
|
15
|
+
|
|
16
|
+
case value
|
|
17
|
+
when model_class
|
|
18
|
+
value
|
|
19
|
+
when Hash
|
|
20
|
+
model_class.from_hash(value)
|
|
21
|
+
else
|
|
22
|
+
raise ArgumentError, "Expected #{@model_class_name}, got #{value.class}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def model_class
|
|
29
|
+
@_model_class ||= @model_class_name.constantize
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|