volley-ruby 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 940af3ec50cfcfc56d2893bade22ebbbb44c7cc5144e300501f2b58d1d3191b9
4
+ data.tar.gz: ea237641f9c32ec904746ae2c19594eeba3027190974aa5fa5292df6f565c898
5
+ SHA512:
6
+ metadata.gz: 348df765bfee9e5532d372313e1d53a922608de93da701e02520cc94d596edbf6162c3736fdbfdaade08952ce2385c93eca4f3202d6f60f7331015e6a6dea998
7
+ data.tar.gz: 47bb9e624a10a3cf375cd3e726b373179788bcf9f8b01ab497d9e08ad3af5317e067fc430c82d9f9f48b8b8932ca6675b90fd2d8e9ef1424818330b401df262d
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Volley Ruby SDK will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-01-16
9
+
10
+ ### Added
11
+ - Initial release of the Volley Ruby SDK
12
+ - Full API coverage for all Volley endpoints:
13
+ - Organizations (list, get, create)
14
+ - Projects (list, create, update, delete)
15
+ - Sources (list, create, get, update, delete)
16
+ - Destinations (list, create, get, update, delete)
17
+ - Connections (create, get, update, delete)
18
+ - Events (list, get, replay)
19
+ - Delivery Attempts (list with filters)
20
+ - Webhooks (send)
21
+ - Type-safe models for all API request/response structures
22
+ - Custom exception class (`VolleyException`) with HTTP status code tracking
23
+ - Organization context management
24
+ - Comprehensive unit tests with mocked HTTP responses
25
+ - Integration tests for real API calls
26
+ - Full documentation (README, TESTING, RELEASING)
27
+ - Example code demonstrating SDK usage
28
+ - Ruby 2.7.0+ support
29
+ - Gem package ready for RubyGems
30
+
31
+ [1.0.0]: https://github.com/volleyhq/volley-ruby/releases/tag/v1.0.0
32
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Volley
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # Volley Ruby SDK
2
+
3
+ Official Ruby SDK for the Volley API. This SDK provides a convenient way to interact with the Volley webhook infrastructure API.
4
+
5
+ [Volley](https://volleyhooks.com) is a webhook infrastructure platform that provides reliable webhook delivery, rate limiting, retries, monitoring, and more.
6
+
7
+ ## Resources
8
+
9
+ - **Documentation**: [https://docs.volleyhooks.com](https://docs.volleyhooks.com)
10
+ - **Getting Started Guide**: [https://docs.volleyhooks.com/getting-started](https://docs.volleyhooks.com/getting-started)
11
+ - **API Reference**: [https://docs.volleyhooks.com/api](https://docs.volleyhooks.com/api)
12
+ - **Authentication Guide**: [https://docs.volleyhooks.com/authentication](https://docs.volleyhooks.com/authentication)
13
+ - **Security Guide**: [https://docs.volleyhooks.com/security](https://docs.volleyhooks.com/security)
14
+ - **Console**: [https://app.volleyhooks.com](https://app.volleyhooks.com)
15
+ - **Website**: [https://volleyhooks.com](https://volleyhooks.com)
16
+
17
+ ## Requirements
18
+
19
+ - Ruby 2.7.0 or higher
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'volley-ruby'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ ```bash
32
+ bundle install
33
+ ```
34
+
35
+ Or install it yourself as:
36
+
37
+ ```bash
38
+ gem install volley-ruby
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ```ruby
44
+ require 'volley'
45
+
46
+ # Create a client with your API token
47
+ client = Volley::VolleyClient.new('your-api-token')
48
+
49
+ # Optionally set organization context
50
+ client.set_organization_id(123)
51
+
52
+ # List organizations
53
+ orgs = client.organizations.list
54
+ orgs.each do |org|
55
+ puts "Organization: #{org.name} (ID: #{org.id})"
56
+ end
57
+ ```
58
+
59
+ ## Authentication
60
+
61
+ Volley uses API tokens for authentication. These are long-lived tokens designed for programmatic access.
62
+
63
+ ### Getting Your API Token
64
+
65
+ 1. Log in to the [Volley Console](https://app.volleyhooks.com)
66
+ 2. Navigate to **Settings → Account → API Token**
67
+ 3. Click **View Token** (you may need to verify your password)
68
+ 4. Copy the token and store it securely
69
+
70
+ **Important**: API tokens are non-expiring and provide full access to your account. Keep them secure and rotate them if compromised. See the [Security Guide](https://docs.volleyhooks.com/security) for best practices.
71
+
72
+ ```ruby
73
+ client = Volley::VolleyClient.new('your-api-token')
74
+ ```
75
+
76
+ For more details on authentication, API tokens, and security, see the [Authentication Guide](https://docs.volleyhooks.com/authentication) and [Security Guide](https://docs.volleyhooks.com/security).
77
+
78
+ ## Organization Context
79
+
80
+ When you have multiple organizations, you need to specify which organization context to use for API requests. The API verifies that resources (like projects) belong to the specified organization.
81
+
82
+ You can set the organization context in two ways:
83
+
84
+ ```ruby
85
+ # Method 1: Set organization ID for all subsequent requests
86
+ client.set_organization_id(123)
87
+
88
+ # Method 2: Create client with organization ID
89
+ client = Volley::VolleyClient.new('your-api-token', organization_id: 123)
90
+
91
+ # Clear organization context (uses first accessible organization)
92
+ client.clear_organization_id
93
+ ```
94
+
95
+ **Note**: If you don't set an organization ID, the API uses your first accessible organization by default. For more details, see the [API Reference - Organization Context](https://docs.volleyhooks.com/api#organization-context).
96
+
97
+ ## Examples
98
+
99
+ ### Organizations
100
+
101
+ ```ruby
102
+ # List all organizations
103
+ orgs = client.organizations.list
104
+
105
+ # Get current organization
106
+ org = client.organizations.get # nil = use default
107
+
108
+ # Create organization
109
+ new_org = client.organizations.create(name: 'My Organization')
110
+ ```
111
+
112
+ ### Projects
113
+
114
+ ```ruby
115
+ # List projects (requires organization context)
116
+ client.set_organization_id(123)
117
+ projects = client.projects.list
118
+
119
+ # Create project
120
+ project = client.projects.create(name: 'My Project')
121
+
122
+ # Update project
123
+ updated = client.projects.update(project_id: project.id, name: 'Updated Name')
124
+
125
+ # Delete project
126
+ client.projects.delete(project_id: project.id)
127
+ ```
128
+
129
+ ### Sources
130
+
131
+ ```ruby
132
+ # List sources for a project
133
+ sources = client.sources.list(project_id: project_id)
134
+
135
+ # Create source
136
+ source = client.sources.create(
137
+ project_id: project_id,
138
+ slug: 'my-source',
139
+ type: 'webhook',
140
+ eps: 100,
141
+ verify_signature: true
142
+ )
143
+
144
+ # Get source
145
+ source = client.sources.get(project_id: project_id, source_id: source_id)
146
+
147
+ # Update source
148
+ updated = client.sources.update(
149
+ project_id: project_id,
150
+ source_id: source_id,
151
+ slug: 'new-slug',
152
+ eps: 200
153
+ )
154
+
155
+ # Delete source
156
+ client.sources.delete(project_id: project_id, source_id: source_id)
157
+ ```
158
+
159
+ ### Destinations
160
+
161
+ ```ruby
162
+ # List destinations for a project
163
+ destinations = client.destinations.list(project_id: project_id)
164
+
165
+ # Create destination
166
+ destination = client.destinations.create(
167
+ project_id: project_id,
168
+ name: 'My Destination',
169
+ url: 'https://example.com/webhook',
170
+ eps: 50
171
+ )
172
+
173
+ # Get destination
174
+ destination = client.destinations.get(project_id: project_id, destination_id: destination_id)
175
+
176
+ # Update destination
177
+ updated = client.destinations.update(
178
+ project_id: project_id,
179
+ destination_id: destination_id,
180
+ name: 'Updated Name',
181
+ url: 'https://new.example.com/webhook'
182
+ )
183
+
184
+ # Delete destination
185
+ client.destinations.delete(project_id: project_id, destination_id: destination_id)
186
+ ```
187
+
188
+ ### Connections
189
+
190
+ ```ruby
191
+ # Create connection
192
+ connection = client.connections.create(
193
+ project_id: project_id,
194
+ source_id: source_id,
195
+ destination_id: destination_id,
196
+ status: 'active',
197
+ max_retries: 3
198
+ )
199
+
200
+ # Get connection
201
+ connection = client.connections.get(connection_id: connection_id)
202
+
203
+ # Update connection
204
+ updated = client.connections.update(
205
+ connection_id: connection_id,
206
+ status: 'paused',
207
+ eps: 100
208
+ )
209
+
210
+ # Delete connection
211
+ client.connections.delete(connection_id: connection_id)
212
+ ```
213
+
214
+ ### Events
215
+
216
+ ```ruby
217
+ # List events with filters
218
+ result = client.events.list(
219
+ project_id: project_id,
220
+ limit: 10,
221
+ offset: 0,
222
+ source_id: 'src_123',
223
+ status: 'failed'
224
+ )
225
+
226
+ result[:events].each do |event|
227
+ puts "Event ID: #{event.event_id}, Status: #{event.status}"
228
+ end
229
+
230
+ # Get event by ID
231
+ event = client.events.get(project_id: project_id, event_id: 'evt_abc123xyz')
232
+
233
+ # Replay a failed event
234
+ message = client.events.replay(event_id: 'evt_abc123xyz')
235
+ ```
236
+
237
+ ### Delivery Attempts
238
+
239
+ ```ruby
240
+ # List delivery attempts with filters
241
+ result = client.delivery_attempts.list(
242
+ project_id: project_id,
243
+ event_id: 'evt_abc123xyz',
244
+ status: 'failed',
245
+ limit: 20
246
+ )
247
+
248
+ result[:attempts].each do |attempt|
249
+ puts "Attempt ID: #{attempt.id}, Status: #{attempt.status}"
250
+ end
251
+ ```
252
+
253
+ ### Webhooks
254
+
255
+ ```ruby
256
+ # Send a webhook
257
+ message = client.webhooks.send(
258
+ source_id: source_id,
259
+ destination_id: destination_id,
260
+ body: { key: 'value', data: 'test' },
261
+ headers: { 'X-Custom-Header' => 'value' }
262
+ )
263
+ ```
264
+
265
+ ## Error Handling
266
+
267
+ The SDK raises `VolleyException` for API errors. The exception includes the HTTP status code and error message:
268
+
269
+ ```ruby
270
+ begin
271
+ org = client.organizations.get(organization_id: 999)
272
+ rescue Volley::VolleyException => e
273
+ puts "Error: #{e.message}"
274
+ puts "Status Code: #{e.status_code}"
275
+
276
+ # Check specific error types
277
+ if e.not_found?
278
+ puts 'Organization not found'
279
+ elsif e.unauthorized?
280
+ puts 'Authentication failed'
281
+ end
282
+ end
283
+ ```
284
+
285
+ ## Client Options
286
+
287
+ You can customize the client with additional options:
288
+
289
+ ```ruby
290
+ require 'faraday'
291
+
292
+ # Custom base URL (for testing)
293
+ client = Volley::VolleyClient.new(
294
+ 'your-api-token',
295
+ base_url: 'https://api.staging.volleyhooks.com'
296
+ )
297
+
298
+ # Custom HTTP client
299
+ http_client = Faraday.new do |f|
300
+ f.request :retry, { max: 5, interval: 2 }
301
+ end
302
+ client = Volley::VolleyClient.new(
303
+ 'your-api-token',
304
+ http_client: http_client
305
+ )
306
+ ```
307
+
308
+ ## Development
309
+
310
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
311
+
312
+ To install this gem onto your local machine, run `bundle exec rake install`.
313
+
314
+ ## Contributing
315
+
316
+ Bug reports and pull requests are welcome on GitHub at https://github.com/volleyhq/volley-ruby.
317
+
318
+ ## License
319
+
320
+ The gem is available as open source under the terms of the [MIT License](LICENSE).
321
+
322
+ ## Support
323
+
324
+ - **Documentation**: [https://docs.volleyhooks.com](https://docs.volleyhooks.com)
325
+ - **Issues**: [https://github.com/volleyhq/volley-ruby/issues](https://github.com/volleyhq/volley-ruby/issues)
326
+ - **Email**: support@volleyhooks.com
327
+
data/RELEASING.md ADDED
@@ -0,0 +1,131 @@
1
+ # Releasing the Volley Ruby SDK
2
+
3
+ This document describes the process for releasing a new version of the Volley Ruby SDK.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. Ensure all tests pass:
8
+ ```bash
9
+ bundle install
10
+ bundle exec rspec
11
+ ```
12
+
13
+ 2. Update version numbers:
14
+ - Update `VERSION` in `lib/volley/version.rb`
15
+ - Update version in `volley-ruby.gemspec` (if needed)
16
+
17
+ 3. Update CHANGELOG.md with the new version and changes
18
+
19
+ 4. Ensure code quality:
20
+ ```bash
21
+ bundle exec rubocop
22
+ ```
23
+
24
+ ## Release Process
25
+
26
+ ### 1. Build the Gem
27
+
28
+ ```bash
29
+ gem build volley-ruby.gemspec
30
+ ```
31
+
32
+ This creates a `.gem` file (e.g., `volley-ruby-1.0.0.gem`).
33
+
34
+ ### 2. Test the Gem Locally
35
+
36
+ ```bash
37
+ gem install ./volley-ruby-1.0.0.gem
38
+ ```
39
+
40
+ Test in a separate directory:
41
+
42
+ ```ruby
43
+ require 'volley'
44
+ client = Volley::VolleyClient.new('test-token')
45
+ # Test basic functionality
46
+ ```
47
+
48
+ ### 3. Create a Git Tag
49
+
50
+ ```bash
51
+ git tag -a v1.0.0 -m "Release version 1.0.0"
52
+ git push origin v1.0.0
53
+ ```
54
+
55
+ ### 4. Create a GitHub Release
56
+
57
+ 1. Go to the [GitHub repository](https://github.com/volleyhq/volley-ruby)
58
+ 2. Click "Releases" → "Draft a new release"
59
+ 3. Select the tag you just created
60
+ 4. Add release notes (copy from CHANGELOG.md)
61
+ 5. Publish the release
62
+
63
+ ### 5. Publish to RubyGems
64
+
65
+ ```bash
66
+ gem push volley-ruby-1.0.0.gem
67
+ ```
68
+
69
+ **Note**: You need to be logged in to RubyGems. If not already logged in:
70
+
71
+ ```bash
72
+ gem signin
73
+ ```
74
+
75
+ Enter your RubyGems credentials.
76
+
77
+ ### 6. Verify Release
78
+
79
+ 1. Verify the gem is available on RubyGems:
80
+ ```bash
81
+ gem search volley-ruby
82
+ ```
83
+
84
+ 2. Test installation:
85
+ ```bash
86
+ gem install volley-ruby
87
+ ```
88
+
89
+ 3. Verify the version:
90
+ ```ruby
91
+ require 'volley'
92
+ puts Volley::VERSION
93
+ ```
94
+
95
+ ## Version Numbering
96
+
97
+ Follow [Semantic Versioning](https://semver.org/):
98
+ - **MAJOR** version for incompatible API changes
99
+ - **MINOR** version for new functionality in a backward-compatible manner
100
+ - **PATCH** version for backward-compatible bug fixes
101
+
102
+ ## Post-Release Checklist
103
+
104
+ - [ ] All tests pass
105
+ - [ ] Version numbers updated
106
+ - [ ] CHANGELOG.md updated
107
+ - [ ] Code quality checks pass (RuboCop)
108
+ - [ ] Gem built and tested locally
109
+ - [ ] Git tag created and pushed
110
+ - [ ] GitHub release created
111
+ - [ ] Gem published to RubyGems
112
+ - [ ] Package available on RubyGems.org
113
+ - [ ] Documentation updated (if needed)
114
+ - [ ] Announcement posted (if major release)
115
+
116
+ ## Troubleshooting
117
+
118
+ ### Gem Push Fails
119
+
120
+ If `gem push` fails with authentication errors:
121
+ 1. Check you're logged in: `gem signin`
122
+ 2. Verify your credentials are correct
123
+ 3. Check if the gem name is already taken (should be `volley-ruby`)
124
+
125
+ ### Version Already Exists
126
+
127
+ If you get an error that the version already exists:
128
+ 1. Check RubyGems.org to see if the version is already published
129
+ 2. If it's a mistake, you'll need to yank the version: `gem yank volley-ruby -v 1.0.0`
130
+ 3. Then republish with the correct version
131
+
data/TESTING.md ADDED
@@ -0,0 +1,155 @@
1
+ # Testing the Volley Ruby SDK
2
+
3
+ This document describes how to run tests for the Volley Ruby SDK.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. Install dependencies:
8
+ ```bash
9
+ bundle install
10
+ ```
11
+
12
+ 2. Ensure RSpec is installed (included in dev dependencies):
13
+ ```bash
14
+ bundle exec rspec --version
15
+ ```
16
+
17
+ ## Running Tests
18
+
19
+ ### Unit Tests
20
+
21
+ Unit tests use mocked HTTP responses with WebMock and don't require a real API token:
22
+
23
+ ```bash
24
+ bundle exec rspec spec/
25
+ ```
26
+
27
+ Or run specific test files:
28
+
29
+ ```bash
30
+ bundle exec rspec spec/volley_client_spec.rb
31
+ bundle exec rspec spec/organizations_resource_spec.rb
32
+ ```
33
+
34
+ ### Integration Tests
35
+
36
+ Integration tests make real API calls to the Volley API. These tests are skipped unless `VOLLEY_API_TOKEN` is set.
37
+
38
+ To run integration tests:
39
+
40
+ 1. Set your API token:
41
+ ```bash
42
+ export VOLLEY_API_TOKEN=your-api-token-here
43
+ ```
44
+
45
+ 2. Run integration tests:
46
+ ```bash
47
+ bundle exec rspec spec/integration_spec.rb
48
+ ```
49
+
50
+ **Note**: Integration tests may create, modify, or delete resources in your account. Use a test account or be prepared to clean up test data.
51
+
52
+ ### Running All Tests
53
+
54
+ To run all tests (unit and integration):
55
+
56
+ ```bash
57
+ bundle exec rspec
58
+ ```
59
+
60
+ ## Test Coverage
61
+
62
+ To generate a test coverage report, you can use SimpleCov:
63
+
64
+ 1. Add SimpleCov to your Gemfile:
65
+ ```ruby
66
+ group :test do
67
+ gem 'simplecov', require: false
68
+ end
69
+ ```
70
+
71
+ 2. Add to `spec/spec_helper.rb`:
72
+ ```ruby
73
+ require 'simplecov'
74
+ SimpleCov.start
75
+ ```
76
+
77
+ 3. Run tests:
78
+ ```bash
79
+ bundle exec rspec
80
+ ```
81
+
82
+ Coverage reports will be generated in the `coverage/` directory.
83
+
84
+ ## Writing Tests
85
+
86
+ ### Unit Tests
87
+
88
+ Unit tests should mock HTTP responses using WebMock:
89
+
90
+ ```ruby
91
+ require 'webmock/rspec'
92
+
93
+ RSpec.describe Volley::VolleyClient do
94
+ it 'makes successful request' do
95
+ stub_request(:get, 'https://api.volleyhooks.com/api/org')
96
+ .with(headers: { 'Authorization' => 'Bearer test-token' })
97
+ .to_return(status: 200, body: '{"id": 1, "name": "Test"}')
98
+
99
+ client = Volley::VolleyClient.new('test-token')
100
+ response = client.request('GET', '/api/org')
101
+ expect(response['id']).to eq(1)
102
+ end
103
+ end
104
+ ```
105
+
106
+ ### Integration Tests
107
+
108
+ Integration tests should:
109
+ - Check for `VOLLEY_API_TOKEN` environment variable
110
+ - Skip if not set
111
+ - Clean up any resources created during tests
112
+ - Use descriptive test names
113
+
114
+ Example:
115
+
116
+ ```ruby
117
+ RSpec.describe 'Integration Tests', type: :integration do
118
+ let(:api_token) { ENV['VOLLEY_API_TOKEN'] }
119
+ let(:client) { Volley::VolleyClient.new(api_token) if api_token }
120
+
121
+ before do
122
+ skip 'VOLLEY_API_TOKEN environment variable is not set' unless api_token
123
+ end
124
+
125
+ it 'lists organizations' do
126
+ orgs = client.organizations.list
127
+ expect(orgs).to be_a(Array)
128
+ end
129
+ end
130
+ ```
131
+
132
+ ## Continuous Integration
133
+
134
+ The SDK includes RSpec configuration that can be used in CI/CD pipelines. The configuration:
135
+
136
+ - Runs all tests in the `spec/` directory
137
+ - Excludes integration tests by default (unless `VOLLEY_API_TOKEN` is set)
138
+ - Uses documentation format for better output
139
+
140
+ ## Code Quality
141
+
142
+ ### RuboCop
143
+
144
+ To check code style:
145
+
146
+ ```bash
147
+ bundle exec rubocop
148
+ ```
149
+
150
+ To auto-fix issues:
151
+
152
+ ```bash
153
+ bundle exec rubocop -a
154
+ ```
155
+
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/volley'
5
+
6
+ # Initialize the client
7
+ client = Volley::VolleyClient.new('your-api-token')
8
+
9
+ # List organizations
10
+ orgs = client.organizations.list
11
+ orgs.each do |org|
12
+ puts "Organization: #{org.name} (ID: #{org.id})"
13
+ end
14
+
15
+ # Get the first organization
16
+ unless orgs.empty?
17
+ org = client.organizations.get(organization_id: orgs[0].id)
18
+ puts "Current organization: #{org.name}"
19
+
20
+ # Set organization context
21
+ client.set_organization_id(org.id)
22
+
23
+ # List projects
24
+ projects = client.projects.list
25
+ projects.each do |project|
26
+ puts "Project: #{project.name} (ID: #{project.id})"
27
+ end
28
+
29
+ # Create a new project
30
+ unless projects.empty?
31
+ project = projects[0]
32
+
33
+ # List sources
34
+ sources = client.sources.list(project_id: project.id)
35
+ puts "Found #{sources.length} sources"
36
+
37
+ # List events
38
+ events_result = client.events.list(project_id: project.id, limit: 10)
39
+ puts "Found #{events_result[:total]} events"
40
+ end
41
+ end
42
+