sirv_rest_api 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +305 -0
- data/Rakefile +27 -0
- data/docs/index.html +539 -0
- data/examples/basic_usage.rb +68 -0
- data/icon.png +0 -0
- data/lib/sirv_rest_api/client.rb +882 -0
- data/lib/sirv_rest_api/errors.rb +56 -0
- data/lib/sirv_rest_api/models.rb +319 -0
- data/lib/sirv_rest_api/version.rb +5 -0
- data/lib/sirv_rest_api.rb +32 -0
- data/sirv_rest_api.gemspec +43 -0
- metadata +132 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7988f44acfb48928112d2a3f31248e986d17dcaf89e92958d801c7dfb6df2c61
|
|
4
|
+
data.tar.gz: b9d7df63ec359638f85eca234d9738bd59ffd4151e98d5787e8080f91d466fbe
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5dbcaa95009de205b9840857f30f4a4f9036035ce6ac456b766e97bd3e8e9ee0506413c300d08eb26a091853e95e986d14ed015253f309d49a1b82e2b7864a83
|
|
7
|
+
data.tar.gz: 0c8613b0eee94fa033d99189484196ee6be94f5510ea068ddad5f9ed19893fda037e682eaa2d5f79091587cf4a73a95a07d63f6d84a548e940ac16e30f3c7db7
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sirv Ltd
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# Sirv REST API Ruby SDK
|
|
2
|
+
|
|
3
|
+
Official Ruby SDK for the [Sirv REST API](https://apidocs.sirv.com/). Provides a simple, type-safe way to interact with Sirv's image hosting and processing platform.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Complete coverage of all 40+ Sirv REST API endpoints
|
|
8
|
+
- Automatic token management with configurable expiry
|
|
9
|
+
- Thread-safe client
|
|
10
|
+
- Retry logic with exponential backoff
|
|
11
|
+
- Comprehensive model classes
|
|
12
|
+
- Iterator patterns for paginated results
|
|
13
|
+
- Zero external dependencies (uses Ruby stdlib only)
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Add this line to your application's Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'sirv_rest_api'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
And then execute:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or install it yourself:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
gem install sirv_rest_api
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Requirements
|
|
36
|
+
|
|
37
|
+
- Ruby 2.7 or later
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
require 'sirv_rest_api'
|
|
43
|
+
|
|
44
|
+
# Create client
|
|
45
|
+
client = SirvRestApi::Client.new(
|
|
46
|
+
client_id: 'your-client-id',
|
|
47
|
+
client_secret: 'your-client-secret'
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Connect (authenticate)
|
|
51
|
+
token = client.connect
|
|
52
|
+
puts "Connected! Token expires in #{token.expires_in} seconds"
|
|
53
|
+
|
|
54
|
+
# Get account info
|
|
55
|
+
account = client.get_account_info
|
|
56
|
+
puts "Account: #{account.alias}"
|
|
57
|
+
puts "CDN URL: #{account.cdn_url}"
|
|
58
|
+
|
|
59
|
+
# List folder contents
|
|
60
|
+
folder = client.read_folder_contents('/')
|
|
61
|
+
folder.contents.each do |item|
|
|
62
|
+
type = item.directory? ? '[DIR]' : '[FILE]'
|
|
63
|
+
puts "#{type} #{item.filename}"
|
|
64
|
+
end
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
client = SirvRestApi::Client.new(
|
|
71
|
+
# Required
|
|
72
|
+
client_id: 'your-client-id',
|
|
73
|
+
client_secret: 'your-client-secret',
|
|
74
|
+
|
|
75
|
+
# Optional
|
|
76
|
+
base_url: 'https://api.sirv.com', # Default
|
|
77
|
+
auto_refresh_token: true, # Default: true
|
|
78
|
+
token_refresh_buffer: 60, # Seconds before expiry to refresh (default: 60)
|
|
79
|
+
timeout: 30, # Request timeout in seconds (default: 30)
|
|
80
|
+
max_retries: 3 # Max retries on 5xx errors (default: 3)
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Custom Token Expiry
|
|
85
|
+
|
|
86
|
+
You can customize how long the token is valid (5-604800 seconds):
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
# Request a token valid for 1 hour (3600 seconds)
|
|
90
|
+
token = client.connect(expires_in: 3600)
|
|
91
|
+
|
|
92
|
+
# Request a token valid for 7 days (604800 seconds)
|
|
93
|
+
token = client.connect(expires_in: 604800)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## API Reference
|
|
97
|
+
|
|
98
|
+
### Authentication
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
# Connect and get token
|
|
102
|
+
token = client.connect
|
|
103
|
+
token = client.connect(expires_in: 3600) # Custom expiry
|
|
104
|
+
|
|
105
|
+
# Check connection status
|
|
106
|
+
client.connected?
|
|
107
|
+
|
|
108
|
+
# Get current token
|
|
109
|
+
client.access_token
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Account Operations
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# Get account info
|
|
116
|
+
account = client.get_account_info
|
|
117
|
+
|
|
118
|
+
# Update account settings
|
|
119
|
+
client.update_account(minify: { enabled: true })
|
|
120
|
+
|
|
121
|
+
# Get rate limits
|
|
122
|
+
limits = client.get_account_limits
|
|
123
|
+
|
|
124
|
+
# Get storage info
|
|
125
|
+
storage = client.get_storage_info
|
|
126
|
+
|
|
127
|
+
# Get billing plan
|
|
128
|
+
plan = client.get_billing_plan
|
|
129
|
+
|
|
130
|
+
# Get account users
|
|
131
|
+
users = client.get_account_users
|
|
132
|
+
|
|
133
|
+
# Search events
|
|
134
|
+
events = client.search_events(level: 'error', from: '2024-01-01')
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### File Operations
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
# Get file info
|
|
141
|
+
info = client.get_file_info('/path/to/file.jpg')
|
|
142
|
+
|
|
143
|
+
# Read folder contents
|
|
144
|
+
folder = client.read_folder_contents('/my-folder')
|
|
145
|
+
|
|
146
|
+
# Iterate folder (handles pagination)
|
|
147
|
+
client.each_folder_item('/my-folder') do |file|
|
|
148
|
+
puts file.filename
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Search files
|
|
152
|
+
results = client.search_files(query: '*.jpg', size: 10)
|
|
153
|
+
|
|
154
|
+
# Iterate search results (handles pagination)
|
|
155
|
+
client.each_search_result(query: '*') do |file|
|
|
156
|
+
puts file.filename
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Upload file
|
|
160
|
+
client.upload_file('/path/to/dest.jpg', File.binread('./image.jpg'))
|
|
161
|
+
|
|
162
|
+
# Upload from local path
|
|
163
|
+
client.upload_file_from_path('/path/to/dest.jpg', './local-file.jpg')
|
|
164
|
+
|
|
165
|
+
# Download file
|
|
166
|
+
content = client.download_file('/path/to/file.jpg')
|
|
167
|
+
|
|
168
|
+
# Download file to local path
|
|
169
|
+
client.download_file_to('/path/to/file.jpg', './local-file.jpg')
|
|
170
|
+
|
|
171
|
+
# Create folder
|
|
172
|
+
client.create_folder('/new-folder')
|
|
173
|
+
|
|
174
|
+
# Delete file
|
|
175
|
+
client.delete_file('/path/to/file.jpg')
|
|
176
|
+
|
|
177
|
+
# Copy file
|
|
178
|
+
client.copy_file(from: '/source.jpg', to: '/dest.jpg')
|
|
179
|
+
|
|
180
|
+
# Rename/move file
|
|
181
|
+
client.rename_file(from: '/old.jpg', to: '/new.jpg')
|
|
182
|
+
|
|
183
|
+
# Fetch from URL
|
|
184
|
+
client.fetch_url(url: 'https://example.com/image.jpg', filename: '/fetched/image.jpg')
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Metadata Operations
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
# Get file metadata
|
|
191
|
+
meta = client.get_file_meta('/path/to/file.jpg')
|
|
192
|
+
|
|
193
|
+
# Set file metadata
|
|
194
|
+
client.set_file_meta('/path/to/file.jpg', {
|
|
195
|
+
title: 'My Image',
|
|
196
|
+
description: 'A beautiful image',
|
|
197
|
+
tags: ['nature', 'landscape']
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
# Get/set individual metadata fields
|
|
201
|
+
title = client.get_file_title('/path/to/file.jpg')
|
|
202
|
+
client.set_file_title('/path/to/file.jpg', 'New Title')
|
|
203
|
+
|
|
204
|
+
tags = client.get_file_tags('/path/to/file.jpg')
|
|
205
|
+
client.add_file_tags('/path/to/file.jpg', ['tag1', 'tag2'])
|
|
206
|
+
client.remove_file_tags('/path/to/file.jpg', ['tag1'])
|
|
207
|
+
|
|
208
|
+
# Product metadata
|
|
209
|
+
product = client.get_product_meta('/path/to/file.jpg')
|
|
210
|
+
client.set_product_meta('/path/to/file.jpg', {
|
|
211
|
+
name: 'Product Name',
|
|
212
|
+
sku: 'SKU-123',
|
|
213
|
+
brand: 'Brand Name'
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
# Approval flag
|
|
217
|
+
approved = client.get_approval_flag('/path/to/file.jpg')
|
|
218
|
+
client.set_approval_flag('/path/to/file.jpg', true)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### JWT Protected URLs
|
|
222
|
+
|
|
223
|
+
```ruby
|
|
224
|
+
jwt = client.generate_jwt(filename: '/protected/image.jpg', expires_in: 3600)
|
|
225
|
+
puts "Protected URL: #{jwt.url}"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Spins/360 Operations
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
# Convert spin to video
|
|
232
|
+
video_file = client.spin_to_video('/spin/product.spin', options: {
|
|
233
|
+
width: 800,
|
|
234
|
+
height: 600
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
# Convert video to spin
|
|
238
|
+
spin_file = client.video_to_spin('/video/product.mp4')
|
|
239
|
+
|
|
240
|
+
# Export spin to marketplaces
|
|
241
|
+
client.export_spin_to_amazon(filename: '/spin/product.spin', asin: 'B01234567')
|
|
242
|
+
client.export_spin_to_walmart(filename: '/spin/product.spin')
|
|
243
|
+
client.export_spin_to_home_depot(filename: '/spin/product.spin')
|
|
244
|
+
client.export_spin_to_lowes(filename: '/spin/product.spin')
|
|
245
|
+
client.export_spin_to_grainger(filename: '/spin/product.spin')
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Statistics
|
|
249
|
+
|
|
250
|
+
```ruby
|
|
251
|
+
# HTTP transfer stats
|
|
252
|
+
http_stats = client.get_http_stats(from: '2024-01-01', to: '2024-01-31')
|
|
253
|
+
|
|
254
|
+
# Spin views stats (max 5-day range)
|
|
255
|
+
spin_stats = client.get_spin_views_stats(from: '2024-01-01', to: '2024-01-05')
|
|
256
|
+
|
|
257
|
+
# Storage stats
|
|
258
|
+
storage_stats = client.get_storage_stats(from: '2024-01-01', to: '2024-01-31')
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Error Handling
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
begin
|
|
265
|
+
account = client.get_account_info
|
|
266
|
+
rescue SirvRestApi::AuthenticationError => e
|
|
267
|
+
puts "Authentication failed: #{e.message}"
|
|
268
|
+
rescue SirvRestApi::NotFoundError => e
|
|
269
|
+
puts "Not found: #{e.message}"
|
|
270
|
+
rescue SirvRestApi::RateLimitError => e
|
|
271
|
+
puts "Rate limit exceeded: #{e.message}"
|
|
272
|
+
rescue SirvRestApi::ApiError => e
|
|
273
|
+
puts "API error: #{e.message} (status #{e.status_code})"
|
|
274
|
+
end
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Thread Safety
|
|
278
|
+
|
|
279
|
+
The client is thread-safe and can be used from multiple threads:
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
threads = 10.times.map do |i|
|
|
283
|
+
Thread.new do
|
|
284
|
+
info = client.get_file_info("/file#{i}.jpg")
|
|
285
|
+
puts info.filename
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
threads.each(&:join)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Development
|
|
292
|
+
|
|
293
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
|
|
294
|
+
|
|
295
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
300
|
+
|
|
301
|
+
## Links
|
|
302
|
+
|
|
303
|
+
- [Sirv Website](https://sirv.com)
|
|
304
|
+
- [API Documentation](https://apidocs.sirv.com/)
|
|
305
|
+
- [Sirv Help Center](https://sirv.com/help/)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
|
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
|
7
|
+
t.libs << "test"
|
|
8
|
+
t.libs << "lib"
|
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
task default: :test
|
|
13
|
+
|
|
14
|
+
desc "Run tests with real credentials"
|
|
15
|
+
task :test_live do
|
|
16
|
+
ruby "test/live_test.rb"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc "Generate YARD documentation"
|
|
20
|
+
task :doc do
|
|
21
|
+
sh "yard doc lib/**/*.rb"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
desc "Build the gem"
|
|
25
|
+
task :build do
|
|
26
|
+
sh "gem build sirv_rest_api.gemspec"
|
|
27
|
+
end
|