hooksniff 1.1.1 → 1.3.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 +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +45 -20
- data/hooksniff.gemspec +1 -1
- data/lib/hooksniff/api/alert.rb +34 -0
- data/lib/hooksniff/api/analytics.rb +21 -0
- data/lib/hooksniff/api/api_key.rb +26 -0
- data/lib/hooksniff/api/application.rb +30 -0
- data/lib/hooksniff/api/audit_log.rb +17 -0
- data/lib/hooksniff/api/authentication.rb +0 -13
- data/lib/hooksniff/api/background_task.rb +21 -0
- data/lib/hooksniff/api/billing.rb +34 -0
- data/lib/hooksniff/api/connector.rb +33 -0
- data/lib/hooksniff/api/custom_domain.rb +26 -0
- data/lib/hooksniff/api/environment.rb +47 -0
- data/lib/hooksniff/api/inbound.rb +30 -0
- data/lib/hooksniff/api/integration.rb +8 -8
- data/lib/hooksniff/api/message_poller.rb +21 -0
- data/lib/hooksniff/api/notification.rb +30 -0
- data/lib/hooksniff/api/operational_webhook.rb +34 -0
- data/lib/hooksniff/api/playground.rb +17 -0
- data/lib/hooksniff/api/portal.rb +33 -0
- data/lib/hooksniff/api/rate_limit.rb +26 -0
- data/lib/hooksniff/api/routing.rb +21 -0
- data/lib/hooksniff/api/schema.rb +25 -0
- data/lib/hooksniff/api/search.rb +13 -0
- data/lib/hooksniff/api/service_token.rb +22 -0
- data/lib/hooksniff/api/sso.rb +26 -0
- data/lib/hooksniff/api/statistics.rb +0 -13
- data/lib/hooksniff/api/stream.rb +28 -9
- data/lib/hooksniff/api/team.rb +42 -0
- data/lib/hooksniff/api/template.rb +21 -0
- data/lib/hooksniff/errors.rb +79 -0
- data/lib/hooksniff/hooksniff_http_client.rb +48 -9
- data/lib/hooksniff/models/aggregate_event_types_out.rb +59 -0
- data/lib/hooksniff/models/message_attempt_recovered_event.rb +53 -0
- data/lib/hooksniff/models/message_attempt_recovered_event_data.rb +70 -0
- data/lib/hooksniff/models/message_in.rb +1 -0
- data/lib/hooksniff/options.rb +31 -0
- data/lib/hooksniff/paginator.rb +45 -0
- data/lib/hooksniff/response_metadata.rb +48 -0
- data/lib/hooksniff/version.rb +1 -1
- data/lib/hooksniff/webhook.rb +62 -0
- data/lib/hooksniff/webhook_event.rb +295 -0
- data/lib/hooksniff.rb +135 -66
- data/test/test_hooksniff.rb +0 -11
- data/test/test_typed_events.rb +260 -0
- metadata +36 -13
- data/lib/hooksniff/background_task.rb +0 -21
- data/lib/hooksniff/connector.rb +0 -33
- data/lib/hooksniff/environment.rb +0 -53
- data/lib/hooksniff/inbound.rb +0 -25
- data/lib/hooksniff/message_poller.rb +0 -32
- data/lib/hooksniff/operational_webhook.rb +0 -12
data/lib/hooksniff.rb
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
4
|
-
require "
|
|
5
|
-
require "
|
|
6
|
-
require "
|
|
7
|
-
require "
|
|
3
|
+
require "hooksniff/version"
|
|
4
|
+
require "hooksniff/hooksniff_http_client"
|
|
5
|
+
require "hooksniff/api_error"
|
|
6
|
+
require "hooksniff/errors"
|
|
7
|
+
require "hooksniff/util"
|
|
8
|
+
require "hooksniff/webhook_event"
|
|
9
|
+
require "hooksniff/response_metadata"
|
|
10
|
+
require "hooksniff/options"
|
|
11
|
+
require "hooksniff/webhook"
|
|
8
12
|
|
|
9
|
-
#
|
|
13
|
+
# Original resources
|
|
10
14
|
require "hooksniff/api/authentication"
|
|
11
15
|
require "hooksniff/api/endpoint"
|
|
12
16
|
require "hooksniff/api/event_type"
|
|
@@ -15,64 +19,129 @@ require "hooksniff/api/message"
|
|
|
15
19
|
require "hooksniff/api/message_attempt"
|
|
16
20
|
require "hooksniff/api/statistics"
|
|
17
21
|
|
|
18
|
-
#
|
|
19
|
-
require "hooksniff/
|
|
20
|
-
require "hooksniff/
|
|
21
|
-
require "hooksniff/
|
|
22
|
-
require "hooksniff/
|
|
23
|
-
require "hooksniff/
|
|
24
|
-
require "hooksniff/
|
|
25
|
-
require "hooksniff/
|
|
26
|
-
require "hooksniff/
|
|
27
|
-
require "hooksniff/models/endpoint_enabled_event_data"
|
|
28
|
-
require "hooksniff/models/endpoint_headers_in"
|
|
29
|
-
require "hooksniff/models/endpoint_headers_out"
|
|
30
|
-
require "hooksniff/models/endpoint_headers_patch_in"
|
|
31
|
-
require "hooksniff/models/endpoint_in"
|
|
32
|
-
require "hooksniff/models/endpoint_out"
|
|
33
|
-
require "hooksniff/models/endpoint_patch"
|
|
34
|
-
require "hooksniff/models/endpoint_secret_out"
|
|
35
|
-
require "hooksniff/models/endpoint_secret_rotate_in"
|
|
36
|
-
require "hooksniff/models/endpoint_update"
|
|
37
|
-
require "hooksniff/models/endpoint_updated_event"
|
|
38
|
-
require "hooksniff/models/endpoint_updated_event_data"
|
|
39
|
-
require "hooksniff/models/event_in"
|
|
40
|
-
require "hooksniff/models/event_out"
|
|
41
|
-
require "hooksniff/models/event_type_in"
|
|
42
|
-
require "hooksniff/models/event_type_out"
|
|
43
|
-
require "hooksniff/models/event_type_patch"
|
|
44
|
-
require "hooksniff/models/event_type_update"
|
|
45
|
-
require "hooksniff/models/list_response_endpoint_out"
|
|
46
|
-
require "hooksniff/models/list_response_event_type_out"
|
|
47
|
-
require "hooksniff/models/list_response_message_attempt_out"
|
|
48
|
-
require "hooksniff/models/list_response_message_out"
|
|
49
|
-
require "hooksniff/models/message_attempt_exhausted_event"
|
|
50
|
-
require "hooksniff/models/message_attempt_exhausted_event_data"
|
|
51
|
-
require "hooksniff/models/message_attempt_failed_data"
|
|
52
|
-
require "hooksniff/models/message_attempt_failing_event"
|
|
53
|
-
require "hooksniff/models/message_attempt_failing_event_data"
|
|
54
|
-
require "hooksniff/models/message_attempt_log"
|
|
55
|
-
require "hooksniff/models/message_attempt_log_event"
|
|
56
|
-
require "hooksniff/models/message_attempt_out"
|
|
57
|
-
require "hooksniff/models/message_attempt_recovered_event"
|
|
58
|
-
require "hooksniff/models/message_attempt_recovered_event_data"
|
|
59
|
-
require "hooksniff/models/message_attempt_trigger_type"
|
|
60
|
-
require "hooksniff/models/message_in"
|
|
61
|
-
require "hooksniff/models/message_out"
|
|
62
|
-
require "hooksniff/models/message_status"
|
|
63
|
-
require "hooksniff/models/message_status_text"
|
|
64
|
-
require "hooksniff/models/ordering"
|
|
65
|
-
require "hooksniff/models/status_code_class"
|
|
22
|
+
# Faz 8-15 resources
|
|
23
|
+
require "hooksniff/api/environment"
|
|
24
|
+
require "hooksniff/api/background_task"
|
|
25
|
+
require "hooksniff/api/operational_webhook"
|
|
26
|
+
require "hooksniff/api/message_poller"
|
|
27
|
+
require "hooksniff/api/inbound"
|
|
28
|
+
require "hooksniff/api/connector"
|
|
29
|
+
require "hooksniff/api/integration"
|
|
30
|
+
require "hooksniff/api/stream"
|
|
66
31
|
|
|
67
|
-
#
|
|
68
|
-
require "hooksniff/
|
|
69
|
-
require "hooksniff/
|
|
70
|
-
require "hooksniff/
|
|
71
|
-
require "hooksniff/
|
|
72
|
-
require "hooksniff/
|
|
73
|
-
require "hooksniff/
|
|
74
|
-
require "hooksniff/
|
|
75
|
-
require "hooksniff/
|
|
76
|
-
require "hooksniff/
|
|
77
|
-
require "hooksniff/
|
|
78
|
-
require "hooksniff/
|
|
32
|
+
# Additional resources
|
|
33
|
+
require "hooksniff/api/application"
|
|
34
|
+
require "hooksniff/api/api_key"
|
|
35
|
+
require "hooksniff/api/search"
|
|
36
|
+
require "hooksniff/api/alert"
|
|
37
|
+
require "hooksniff/api/analytics"
|
|
38
|
+
require "hooksniff/api/billing"
|
|
39
|
+
require "hooksniff/api/portal"
|
|
40
|
+
require "hooksniff/api/team"
|
|
41
|
+
require "hooksniff/api/notification"
|
|
42
|
+
require "hooksniff/api/sso"
|
|
43
|
+
require "hooksniff/api/audit_log"
|
|
44
|
+
require "hooksniff/api/custom_domain"
|
|
45
|
+
require "hooksniff/api/rate_limit"
|
|
46
|
+
require "hooksniff/api/routing"
|
|
47
|
+
require "hooksniff/api/template"
|
|
48
|
+
require "hooksniff/api/schema"
|
|
49
|
+
require "hooksniff/api/playground"
|
|
50
|
+
require "hooksniff/api/service_token"
|
|
51
|
+
|
|
52
|
+
module HookSniff
|
|
53
|
+
class HookSniffOptions
|
|
54
|
+
attr_accessor :debug
|
|
55
|
+
attr_accessor :server_url
|
|
56
|
+
|
|
57
|
+
def initialize(debug = false, server_url = nil)
|
|
58
|
+
@debug = debug
|
|
59
|
+
@server_url = server_url
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class Client
|
|
64
|
+
# Original resources
|
|
65
|
+
attr_accessor :authentication
|
|
66
|
+
attr_accessor :endpoint
|
|
67
|
+
attr_accessor :event_type
|
|
68
|
+
attr_accessor :health
|
|
69
|
+
attr_accessor :message
|
|
70
|
+
attr_accessor :message_attempt
|
|
71
|
+
attr_accessor :statistics
|
|
72
|
+
|
|
73
|
+
# Faz 8-15 resources
|
|
74
|
+
attr_accessor :environment
|
|
75
|
+
attr_accessor :background_task
|
|
76
|
+
attr_accessor :operational_webhook
|
|
77
|
+
attr_accessor :message_poller
|
|
78
|
+
attr_accessor :inbound
|
|
79
|
+
attr_accessor :connector
|
|
80
|
+
attr_accessor :integration
|
|
81
|
+
attr_accessor :stream
|
|
82
|
+
|
|
83
|
+
# Additional resources
|
|
84
|
+
attr_accessor :application
|
|
85
|
+
attr_accessor :api_key
|
|
86
|
+
attr_accessor :search
|
|
87
|
+
attr_accessor :alert
|
|
88
|
+
attr_accessor :analytics
|
|
89
|
+
attr_accessor :billing
|
|
90
|
+
attr_accessor :portal
|
|
91
|
+
attr_accessor :team
|
|
92
|
+
attr_accessor :notification
|
|
93
|
+
attr_accessor :sso
|
|
94
|
+
attr_accessor :audit_log
|
|
95
|
+
attr_accessor :custom_domain
|
|
96
|
+
attr_accessor :rate_limit
|
|
97
|
+
attr_accessor :routing
|
|
98
|
+
attr_accessor :template
|
|
99
|
+
attr_accessor :schema
|
|
100
|
+
attr_accessor :playground
|
|
101
|
+
attr_accessor :service_token
|
|
102
|
+
|
|
103
|
+
def initialize(auth_token, options = HookSniffOptions.new)
|
|
104
|
+
uri = URI(options.server_url || "https://hooksniff-api-1046140057667.europe-west1.run.app")
|
|
105
|
+
api_client = HookSniffHttpClient.new(auth_token, uri)
|
|
106
|
+
|
|
107
|
+
# Original
|
|
108
|
+
@authentication = Authentication.new(api_client)
|
|
109
|
+
@endpoint = Endpoint.new(api_client)
|
|
110
|
+
@event_type = EventType.new(api_client)
|
|
111
|
+
@health = Health.new(api_client)
|
|
112
|
+
@message = Message.new(api_client)
|
|
113
|
+
@message_attempt = MessageAttempt.new(api_client)
|
|
114
|
+
@statistics = Statistics.new(api_client)
|
|
115
|
+
|
|
116
|
+
# Faz 8-15
|
|
117
|
+
@environment = Environment.new(api_client)
|
|
118
|
+
@background_task = BackgroundTask.new(api_client)
|
|
119
|
+
@operational_webhook = OperationalWebhook.new(api_client)
|
|
120
|
+
@message_poller = MessagePoller.new(api_client)
|
|
121
|
+
@inbound = Inbound.new(api_client)
|
|
122
|
+
@connector = Connector.new(api_client)
|
|
123
|
+
@integration = IntegrationApi.new(api_client)
|
|
124
|
+
@stream = StreamApi.new(api_client)
|
|
125
|
+
|
|
126
|
+
# Additional
|
|
127
|
+
@application = Application.new(api_client)
|
|
128
|
+
@api_key = ApiKey.new(api_client)
|
|
129
|
+
@search = Search.new(api_client)
|
|
130
|
+
@alert = Alert.new(api_client)
|
|
131
|
+
@analytics = Analytics.new(api_client)
|
|
132
|
+
@billing = Billing.new(api_client)
|
|
133
|
+
@portal = Portal.new(api_client)
|
|
134
|
+
@team = Team.new(api_client)
|
|
135
|
+
@notification = Notification.new(api_client)
|
|
136
|
+
@sso = Sso.new(api_client)
|
|
137
|
+
@audit_log = AuditLog.new(api_client)
|
|
138
|
+
@custom_domain = CustomDomain.new(api_client)
|
|
139
|
+
@rate_limit = RateLimit.new(api_client)
|
|
140
|
+
@routing = Routing.new(api_client)
|
|
141
|
+
@template = Template.new(api_client)
|
|
142
|
+
@schema = Schema.new(api_client)
|
|
143
|
+
@playground = Playground.new(api_client)
|
|
144
|
+
@service_token = ServiceToken.new(api_client)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
data/test/test_hooksniff.rb
CHANGED
|
@@ -56,17 +56,6 @@ class WebhookTest < Minitest::Test
|
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
def test_svix_branded_headers
|
|
60
|
-
wh = HookSniff::Webhook.new(SECRET)
|
|
61
|
-
sig = sign(SECRET, MSG_ID, TIMESTAMP, PAYLOAD)
|
|
62
|
-
headers = {
|
|
63
|
-
"svix-id" => MSG_ID,
|
|
64
|
-
"svix-timestamp" => TIMESTAMP.to_s,
|
|
65
|
-
"svix-signature" => sig,
|
|
66
|
-
}
|
|
67
|
-
result = wh.verify(PAYLOAD, headers)
|
|
68
|
-
assert_equal({"event" => "test"}, result)
|
|
69
|
-
end
|
|
70
59
|
end
|
|
71
60
|
|
|
72
61
|
class ErrorTest < Minitest::Test
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest/autorun"
|
|
4
|
+
require_relative "../lib/hooksniff/webhook_event"
|
|
5
|
+
|
|
6
|
+
class TypedWebhookEventTest < Minitest::Test
|
|
7
|
+
def test_endpoint_created
|
|
8
|
+
event = HookSniff::WebhookEvent.parse(
|
|
9
|
+
event: "endpoint.created",
|
|
10
|
+
data: { appId: "a1", endpointId: "e1", appUid: "u1" },
|
|
11
|
+
timestamp: "2026-05-19"
|
|
12
|
+
)
|
|
13
|
+
assert_instance_of HookSniff::EndpointCreatedEvent, event
|
|
14
|
+
assert_instance_of HookSniff::EndpointCreatedEventData, event.data
|
|
15
|
+
assert_equal "a1", event.data.app_id
|
|
16
|
+
assert_equal "e1", event.data.endpoint_id
|
|
17
|
+
assert_equal "u1", event.data.app_uid
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_endpoint_disabled
|
|
21
|
+
event = HookSniff::WebhookEvent.parse(
|
|
22
|
+
event: "endpoint.disabled",
|
|
23
|
+
data: { appId: "a1", endpointId: "e1", failSince: "2026-01", trigger: "repeated-failure" },
|
|
24
|
+
timestamp: ""
|
|
25
|
+
)
|
|
26
|
+
assert_instance_of HookSniff::EndpointDisabledEvent, event
|
|
27
|
+
assert_equal "2026-01", event.data.fail_since
|
|
28
|
+
assert_equal "repeated-failure", event.data.trigger
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_message_attempt_exhausted
|
|
32
|
+
event = HookSniff::WebhookEvent.parse(
|
|
33
|
+
event: "message.attempt.exhausted",
|
|
34
|
+
data: { appId: "a1", msgId: "m1", lastAttempt: { id: "att", timestamp: "t", responseStatusCode: 500 } },
|
|
35
|
+
timestamp: ""
|
|
36
|
+
)
|
|
37
|
+
assert_instance_of HookSniff::MessageAttemptExhaustedEvent, event
|
|
38
|
+
assert_equal "m1", event.data.msg_id
|
|
39
|
+
assert_equal 500, event.data.last_attempt.response_status_code
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_message_attempt_failing
|
|
43
|
+
event = HookSniff::WebhookEvent.parse(
|
|
44
|
+
event: "message.attempt.failing",
|
|
45
|
+
data: { appId: "a1", msgId: "m1", attempt: { id: "att", timestamp: "t", responseStatusCode: 429 } },
|
|
46
|
+
timestamp: ""
|
|
47
|
+
)
|
|
48
|
+
assert_instance_of HookSniff::MessageAttemptFailingEvent, event
|
|
49
|
+
assert_equal 429, event.data.attempt.response_status_code
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_message_attempt_recovered
|
|
53
|
+
event = HookSniff::WebhookEvent.parse(
|
|
54
|
+
event: "message.attempt.recovered",
|
|
55
|
+
data: { appId: "a1", msgId: "m1", attempt: { id: "att", timestamp: "t", responseStatusCode: 200 } },
|
|
56
|
+
timestamp: ""
|
|
57
|
+
)
|
|
58
|
+
assert_instance_of HookSniff::MessageAttemptRecoveredEvent, event
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_unknown_event_fallback
|
|
62
|
+
event = HookSniff::WebhookEvent.parse(
|
|
63
|
+
event: "custom.unknown",
|
|
64
|
+
data: { x: 1 },
|
|
65
|
+
timestamp: ""
|
|
66
|
+
)
|
|
67
|
+
assert_instance_of HookSniff::WebhookEvent, event
|
|
68
|
+
assert_equal 1, event.data[:x]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_backward_compat_get
|
|
72
|
+
event = HookSniff::WebhookEvent.parse(
|
|
73
|
+
event: "endpoint.created",
|
|
74
|
+
data: { appId: "a1", endpointId: "e1" },
|
|
75
|
+
timestamp: "t"
|
|
76
|
+
)
|
|
77
|
+
assert_equal "a1", event.get("app_id")
|
|
78
|
+
assert_equal "a1", event["app_id"]
|
|
79
|
+
assert event.key?("app_id")
|
|
80
|
+
assert_equal "endpoint.created", event.event_type
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_snake_case_fields
|
|
84
|
+
event = HookSniff::WebhookEvent.parse(
|
|
85
|
+
event: "endpoint.created",
|
|
86
|
+
data: { app_id: "a1", endpoint_id: "e1" },
|
|
87
|
+
timestamp: ""
|
|
88
|
+
)
|
|
89
|
+
assert_equal "a1", event.data.app_id
|
|
90
|
+
assert_equal "e1", event.data.endpoint_id
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_empty_data
|
|
94
|
+
event = HookSniff::WebhookEvent.parse(
|
|
95
|
+
event: "endpoint.created",
|
|
96
|
+
data: {},
|
|
97
|
+
timestamp: ""
|
|
98
|
+
)
|
|
99
|
+
assert_equal "", event.data.app_id
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_missing_data
|
|
103
|
+
event = HookSniff::WebhookEvent.parse(
|
|
104
|
+
event: "endpoint.created",
|
|
105
|
+
timestamp: ""
|
|
106
|
+
)
|
|
107
|
+
assert_equal "", event.data.app_id
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_unknown_event_keeps_raw_data
|
|
111
|
+
event = HookSniff::WebhookEvent.parse(
|
|
112
|
+
event: "custom.unknown",
|
|
113
|
+
data: { "x" => 1 },
|
|
114
|
+
timestamp: ""
|
|
115
|
+
)
|
|
116
|
+
assert_instance_of HookSniff::WebhookEvent, event
|
|
117
|
+
assert_equal 1, event.get("x")
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def test_unicode_data
|
|
121
|
+
event = HookSniff::WebhookEvent.parse(
|
|
122
|
+
event: "endpoint.created",
|
|
123
|
+
data: { appId: "ünïcödé", endpointId: "日本語" },
|
|
124
|
+
timestamp: ""
|
|
125
|
+
)
|
|
126
|
+
assert_equal "ünïcödé", event.data.app_id
|
|
127
|
+
assert_equal "日本語", event.data.endpoint_id
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_event_type_map_count
|
|
131
|
+
assert_equal 10, HookSniff::WebhookEvent::EVENT_TYPE_MAP.size
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_endpoint_updated
|
|
135
|
+
event = HookSniff::WebhookEvent.parse(
|
|
136
|
+
event: "endpoint.updated",
|
|
137
|
+
data: { appId: "a1", endpointId: "e1" },
|
|
138
|
+
timestamp: ""
|
|
139
|
+
)
|
|
140
|
+
assert_instance_of HookSniff::EndpointUpdatedEvent, event
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_endpoint_deleted
|
|
144
|
+
event = HookSniff::WebhookEvent.parse(
|
|
145
|
+
event: "endpoint.deleted",
|
|
146
|
+
data: { appId: "a1", endpointId: "e1" },
|
|
147
|
+
timestamp: ""
|
|
148
|
+
)
|
|
149
|
+
assert_instance_of HookSniff::EndpointDeletedEvent, event
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def test_endpoint_enabled
|
|
153
|
+
event = HookSniff::WebhookEvent.parse(
|
|
154
|
+
event: "endpoint.enabled",
|
|
155
|
+
data: { appId: "a1", endpointId: "e1" },
|
|
156
|
+
timestamp: ""
|
|
157
|
+
)
|
|
158
|
+
assert_instance_of HookSniff::EndpointEnabledEvent, event
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def test_unicode_data
|
|
162
|
+
event = HookSniff::WebhookEvent.parse(
|
|
163
|
+
event: "endpoint.created",
|
|
164
|
+
data: { appId: "ünïcödé", endpointId: "日本語" },
|
|
165
|
+
timestamp: ""
|
|
166
|
+
)
|
|
167
|
+
assert_equal "ünïcödé", event.data.app_id
|
|
168
|
+
assert_equal "日本語", event.data.endpoint_id
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_large_data
|
|
172
|
+
event = HookSniff::WebhookEvent.parse(
|
|
173
|
+
event: "endpoint.created",
|
|
174
|
+
data: { appId: "a" * 10000, endpointId: "e" * 10000 },
|
|
175
|
+
timestamp: ""
|
|
176
|
+
)
|
|
177
|
+
assert_equal 10000, event.data.app_id.length
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def test_special_characters
|
|
181
|
+
event = HookSniff::WebhookEvent.parse(
|
|
182
|
+
event: "endpoint.created",
|
|
183
|
+
data: { appId: "a@b.c", endpointId: "e#1" },
|
|
184
|
+
timestamp: ""
|
|
185
|
+
)
|
|
186
|
+
assert_equal "a@b.c", event.data.app_id
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_trigger_none
|
|
190
|
+
event = HookSniff::WebhookEvent.parse(
|
|
191
|
+
event: "endpoint.disabled",
|
|
192
|
+
data: { appId: "a", endpointId: "e", trigger: "none" },
|
|
193
|
+
timestamp: ""
|
|
194
|
+
)
|
|
195
|
+
assert_equal "none", event.data.trigger
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_trigger_first_failure
|
|
199
|
+
event = HookSniff::WebhookEvent.parse(
|
|
200
|
+
event: "endpoint.disabled",
|
|
201
|
+
data: { appId: "a", endpointId: "e", trigger: "first-failure" },
|
|
202
|
+
timestamp: ""
|
|
203
|
+
)
|
|
204
|
+
assert_equal "first-failure", event.data.trigger
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_all_event_types
|
|
208
|
+
%w[endpoint.created endpoint.updated endpoint.deleted endpoint.enabled endpoint.disabled
|
|
209
|
+
message.attempt.exhausted message.attempt.failing message.attempt.recovered].each do |et|
|
|
210
|
+
event = HookSniff::WebhookEvent.parse(event: et, data: { appId: "a" }, timestamp: "")
|
|
211
|
+
assert_equal et, event.event
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def test_get_with_symbol_key
|
|
216
|
+
event = HookSniff::WebhookEvent.parse(
|
|
217
|
+
event: "endpoint.created",
|
|
218
|
+
data: { appId: "a1" },
|
|
219
|
+
timestamp: ""
|
|
220
|
+
)
|
|
221
|
+
assert_equal "a1", event.get(:appId)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def test_bracket_with_symbol
|
|
225
|
+
event = HookSniff::WebhookEvent.parse(
|
|
226
|
+
event: "endpoint.created",
|
|
227
|
+
data: { appId: "a1" },
|
|
228
|
+
timestamp: ""
|
|
229
|
+
)
|
|
230
|
+
assert_equal "a1", event[:appId]
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def test_key_with_symbol
|
|
234
|
+
event = HookSniff::WebhookEvent.parse(
|
|
235
|
+
event: "endpoint.created",
|
|
236
|
+
data: { appId: "a1" },
|
|
237
|
+
timestamp: ""
|
|
238
|
+
)
|
|
239
|
+
assert event.key?(:appId)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def test_to_s
|
|
243
|
+
event = HookSniff::WebhookEvent.parse(
|
|
244
|
+
event: "endpoint.created",
|
|
245
|
+
data: {},
|
|
246
|
+
timestamp: "2026-05-19"
|
|
247
|
+
)
|
|
248
|
+
assert_match(/EndpointCreatedEvent/, event.to_s)
|
|
249
|
+
assert_match(/2026-05-19/, event.to_s)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def test_inspect
|
|
253
|
+
event = HookSniff::WebhookEvent.parse(
|
|
254
|
+
event: "endpoint.created",
|
|
255
|
+
data: {},
|
|
256
|
+
timestamp: "2026-05-19"
|
|
257
|
+
)
|
|
258
|
+
assert_equal event.to_s, event.inspect
|
|
259
|
+
end
|
|
260
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hooksniff
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- HookSniff
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: base64
|
|
@@ -82,7 +81,7 @@ dependencies:
|
|
|
82
81
|
version: '3.25'
|
|
83
82
|
description: HookSniff makes webhooks easy and reliable. Learn more at https://hooksniff.vercel.app
|
|
84
83
|
email:
|
|
85
|
-
-
|
|
84
|
+
- servetarslan02@gmail.com
|
|
86
85
|
executables: []
|
|
87
86
|
extensions: []
|
|
88
87
|
extra_rdoc_files: []
|
|
@@ -93,27 +92,47 @@ files:
|
|
|
93
92
|
- Rakefile
|
|
94
93
|
- hooksniff.gemspec
|
|
95
94
|
- lib/hooksniff.rb
|
|
95
|
+
- lib/hooksniff/api/alert.rb
|
|
96
|
+
- lib/hooksniff/api/analytics.rb
|
|
97
|
+
- lib/hooksniff/api/api_key.rb
|
|
98
|
+
- lib/hooksniff/api/application.rb
|
|
99
|
+
- lib/hooksniff/api/audit_log.rb
|
|
96
100
|
- lib/hooksniff/api/authentication.rb
|
|
101
|
+
- lib/hooksniff/api/background_task.rb
|
|
102
|
+
- lib/hooksniff/api/billing.rb
|
|
103
|
+
- lib/hooksniff/api/connector.rb
|
|
104
|
+
- lib/hooksniff/api/custom_domain.rb
|
|
97
105
|
- lib/hooksniff/api/endpoint.rb
|
|
106
|
+
- lib/hooksniff/api/environment.rb
|
|
98
107
|
- lib/hooksniff/api/event_type.rb
|
|
99
108
|
- lib/hooksniff/api/health.rb
|
|
109
|
+
- lib/hooksniff/api/inbound.rb
|
|
100
110
|
- lib/hooksniff/api/integration.rb
|
|
101
111
|
- lib/hooksniff/api/message.rb
|
|
102
112
|
- lib/hooksniff/api/message_attempt.rb
|
|
113
|
+
- lib/hooksniff/api/message_poller.rb
|
|
114
|
+
- lib/hooksniff/api/notification.rb
|
|
115
|
+
- lib/hooksniff/api/operational_webhook.rb
|
|
116
|
+
- lib/hooksniff/api/playground.rb
|
|
117
|
+
- lib/hooksniff/api/portal.rb
|
|
118
|
+
- lib/hooksniff/api/rate_limit.rb
|
|
119
|
+
- lib/hooksniff/api/routing.rb
|
|
120
|
+
- lib/hooksniff/api/schema.rb
|
|
121
|
+
- lib/hooksniff/api/search.rb
|
|
122
|
+
- lib/hooksniff/api/service_token.rb
|
|
123
|
+
- lib/hooksniff/api/sso.rb
|
|
103
124
|
- lib/hooksniff/api/statistics.rb
|
|
104
125
|
- lib/hooksniff/api/stream.rb
|
|
126
|
+
- lib/hooksniff/api/team.rb
|
|
127
|
+
- lib/hooksniff/api/template.rb
|
|
105
128
|
- lib/hooksniff/api_error.rb
|
|
106
|
-
- lib/hooksniff/background_task.rb
|
|
107
|
-
- lib/hooksniff/connector.rb
|
|
108
|
-
- lib/hooksniff/environment.rb
|
|
109
129
|
- lib/hooksniff/errors.rb
|
|
110
130
|
- lib/hooksniff/hooksniff.rb
|
|
111
131
|
- lib/hooksniff/hooksniff_http_client.rb
|
|
112
132
|
- lib/hooksniff/http_error_out.rb
|
|
113
133
|
- lib/hooksniff/http_validation_error.rb
|
|
114
|
-
- lib/hooksniff/inbound.rb
|
|
115
134
|
- lib/hooksniff/internal.rb
|
|
116
|
-
- lib/hooksniff/
|
|
135
|
+
- lib/hooksniff/models/aggregate_event_types_out.rb
|
|
117
136
|
- lib/hooksniff/models/endpoint_created_event.rb
|
|
118
137
|
- lib/hooksniff/models/endpoint_created_event_data.rb
|
|
119
138
|
- lib/hooksniff/models/endpoint_deleted_event.rb
|
|
@@ -151,6 +170,8 @@ files:
|
|
|
151
170
|
- lib/hooksniff/models/message_attempt_log.rb
|
|
152
171
|
- lib/hooksniff/models/message_attempt_log_event.rb
|
|
153
172
|
- lib/hooksniff/models/message_attempt_out.rb
|
|
173
|
+
- lib/hooksniff/models/message_attempt_recovered_event.rb
|
|
174
|
+
- lib/hooksniff/models/message_attempt_recovered_event_data.rb
|
|
154
175
|
- lib/hooksniff/models/message_attempt_trigger_type.rb
|
|
155
176
|
- lib/hooksniff/models/message_endpoint_out.rb
|
|
156
177
|
- lib/hooksniff/models/message_in.rb
|
|
@@ -159,12 +180,16 @@ files:
|
|
|
159
180
|
- lib/hooksniff/models/message_status_text.rb
|
|
160
181
|
- lib/hooksniff/models/ordering.rb
|
|
161
182
|
- lib/hooksniff/models/status_code_class.rb
|
|
162
|
-
- lib/hooksniff/
|
|
183
|
+
- lib/hooksniff/options.rb
|
|
184
|
+
- lib/hooksniff/paginator.rb
|
|
185
|
+
- lib/hooksniff/response_metadata.rb
|
|
163
186
|
- lib/hooksniff/util.rb
|
|
164
187
|
- lib/hooksniff/validation_error.rb
|
|
165
188
|
- lib/hooksniff/version.rb
|
|
166
189
|
- lib/hooksniff/webhook.rb
|
|
190
|
+
- lib/hooksniff/webhook_event.rb
|
|
167
191
|
- test/test_hooksniff.rb
|
|
192
|
+
- test/test_typed_events.rb
|
|
168
193
|
homepage: https://hooksniff.vercel.app
|
|
169
194
|
licenses:
|
|
170
195
|
- MIT
|
|
@@ -172,7 +197,6 @@ metadata:
|
|
|
172
197
|
allowed_push_host: https://rubygems.org
|
|
173
198
|
homepage_uri: https://hooksniff.vercel.app
|
|
174
199
|
source_code_uri: https://github.com/servetarslan02/HookSniff
|
|
175
|
-
post_install_message:
|
|
176
200
|
rdoc_options: []
|
|
177
201
|
require_paths:
|
|
178
202
|
- lib
|
|
@@ -187,8 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
187
211
|
- !ruby/object:Gem::Version
|
|
188
212
|
version: '0'
|
|
189
213
|
requirements: []
|
|
190
|
-
rubygems_version:
|
|
191
|
-
signing_key:
|
|
214
|
+
rubygems_version: 4.0.6
|
|
192
215
|
specification_version: 4
|
|
193
216
|
summary: HookSniff webhooks API client and webhook verification library
|
|
194
217
|
test_files: []
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module HookSniff
|
|
4
|
-
class BackgroundTask
|
|
5
|
-
def initialize(api_client)
|
|
6
|
-
@api_client = api_client
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def list
|
|
10
|
-
@api_client.execute(method: :get, path: "/api/v1/background-tasks")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def get(task_id)
|
|
14
|
-
@api_client.execute(method: :get, path: "/api/v1/background-tasks/#{task_id}")
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def cancel(task_id)
|
|
18
|
-
@api_client.execute(method: :put, path: "/api/v1/background-tasks/#{task_id}")
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
data/lib/hooksniff/connector.rb
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module HookSniff
|
|
4
|
-
class Connector
|
|
5
|
-
def initialize(client)
|
|
6
|
-
@client = client
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def list
|
|
10
|
-
@client.request(:get, "/api/v1/connectors")
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def get(id)
|
|
14
|
-
@client.request(:get, "/api/v1/connectors/#{id}")
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def list_configs
|
|
18
|
-
@client.request(:get, "/api/v1/connectors/configs")
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def create_config(body)
|
|
22
|
-
@client.request(:post, "/api/v1/connectors/configs", body: body)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def update_config(id, body)
|
|
26
|
-
@client.request(:put, "/api/v1/connectors/configs/#{id}", body: body)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def delete_config(id)
|
|
30
|
-
@client.request(:delete, "/api/v1/connectors/configs/#{id}")
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|