kompressr-sdk 0.1.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/API.md +120 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE +21 -0
- data/PARITY.md +32 -0
- data/README.md +149 -0
- data/examples/private_upload.rb +42 -0
- data/examples/rails_service.rb +34 -0
- data/lib/kompressr/client.rb +197 -0
- data/lib/kompressr/error.rb +49 -0
- data/lib/kompressr/platform_client.rb +112 -0
- data/lib/kompressr/transport.rb +528 -0
- data/lib/kompressr/validation.rb +278 -0
- data/lib/kompressr/version.rb +5 -0
- data/lib/kompressr.rb +8 -0
- metadata +179 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'time'
|
|
6
|
+
|
|
7
|
+
module Kompressr
|
|
8
|
+
module Validation
|
|
9
|
+
MAX_SAFE = 9_007_199_254_740_991
|
|
10
|
+
MAX_TIMEOUT = 2_147_483.647
|
|
11
|
+
DELETION = %w[active deleting deleted legacy_deleted].freeze
|
|
12
|
+
PROCESSING = %w[pending processing processed failed unprocessable unknown].freeze
|
|
13
|
+
SCOPES = %w[upload status list private_url delete].freeze
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
def invalid(message) = raise(Error.new(message, kind: 'validation', code: 'INVALID_ARGUMENT'), cause: nil)
|
|
17
|
+
def bad(message = 'The API returned an invalid response.')
|
|
18
|
+
raise Error.new(message, kind: 'invalid_response', code: 'INVALID_RESPONSE'), cause: nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def positive(value, name, maximum = MAX_SAFE)
|
|
22
|
+
invalid("#{name} must be an integer between 1 and #{maximum}.") unless value.instance_of?(Integer) && value.between?(1, maximum)
|
|
23
|
+
value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def seconds(value, name = 'timeout')
|
|
27
|
+
invalid("#{name} must be positive finite seconds, at most #{MAX_TIMEOUT}.") unless finite?(value) && value.positive? && value <= MAX_TIMEOUT
|
|
28
|
+
value.to_f
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def finite?(value) = (value.instance_of?(Integer) || value.instance_of?(Float)) && value.finite?
|
|
32
|
+
|
|
33
|
+
def text(value, name, maximum, empty: false, trim: true)
|
|
34
|
+
utf8 = value.instance_of?(String) ? value.b.force_encoding(Encoding::UTF_8) : nil
|
|
35
|
+
valid = utf8 && value.encoding.ascii_compatible? && utf8.valid_encoding?
|
|
36
|
+
normalized = valid ? (trim ? utf8.strip : utf8) : ''
|
|
37
|
+
invalid("#{name} must contain #{empty ? '0' : '1'}–#{maximum} valid UTF-8 bytes.") unless valid && (empty || !normalized.empty?) && normalized.bytesize <= maximum
|
|
38
|
+
utf8
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def uuid(value, name = 'ID')
|
|
42
|
+
invalid("#{name} must be a UUID.") unless value.instance_of?(String) && value.ascii_only? && /\A[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}\z/.match?(value)
|
|
43
|
+
value
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def enum(value, allowed, name)
|
|
47
|
+
invalid("Unsupported #{name}.") unless value.instance_of?(String) && allowed.include?(value)
|
|
48
|
+
value
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def customer_data(value, maximum = 4096)
|
|
52
|
+
invalid('Customer data supports at most five scalar fields.') unless value.instance_of?(Hash) && value.size <= 5
|
|
53
|
+
result = {}
|
|
54
|
+
value.each do |raw_key, item|
|
|
55
|
+
key = text(raw_key, 'Data key', 64).strip
|
|
56
|
+
invalid('Data keys must be unique after trimming.') if result.key?(key)
|
|
57
|
+
if item.instance_of?(String)
|
|
58
|
+
item = text(item, 'Data value', 512, empty: true, trim: false)
|
|
59
|
+
elsif !item.nil? && item != true && item != false
|
|
60
|
+
invalid('Data values must be finite scalars.') unless finite?(item)
|
|
61
|
+
end
|
|
62
|
+
result[key] = item
|
|
63
|
+
end
|
|
64
|
+
invalid("Encoded customer data exceeds #{maximum} bytes.") if JSON.generate(result).bytesize > maximum
|
|
65
|
+
result
|
|
66
|
+
rescue JSON::GeneratorError, EncodingError
|
|
67
|
+
invalid('Customer data must contain valid UTF-8.')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def origin(value)
|
|
71
|
+
invalid('Base URL must be an HTTP(S) origin without credentials, path, query or fragment.') unless value.instance_of?(String) && !/[\x00-\x20\x7f]/.match?(value)
|
|
72
|
+
uri = URI.parse(value)
|
|
73
|
+
valid = %w[http https].include?(uri.scheme) && uri.host && !uri.userinfo && !uri.query && !uri.fragment && ['', '/'].include?(uri.path)
|
|
74
|
+
valid &&= uri.port.between?(1, 65_535) && !uri.host.include?('%')
|
|
75
|
+
invalid('Base URL must be an HTTP(S) origin without credentials, path, query or fragment.') unless valid
|
|
76
|
+
suffix = uri.port == (uri.scheme == 'https' ? 443 : 80) ? '' : ":#{uri.port}"
|
|
77
|
+
"#{uri.scheme}://#{uri.host.downcase}#{suffix}".freeze
|
|
78
|
+
rescue URI::InvalidURIError, ArgumentError
|
|
79
|
+
invalid('Base URL must be an HTTP(S) origin without credentials, path, query or fragment.')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def filename(value)
|
|
83
|
+
value = text(value, 'Filename', 4096)
|
|
84
|
+
invalid('Filename must not contain control characters.') if /[\x00-\x1f\x7f]/.match?(value)
|
|
85
|
+
result = value.tr('\\', '/').split('/', -1).last
|
|
86
|
+
invalid('Supply a nonempty filename.') if result.nil? || result.strip.empty?
|
|
87
|
+
result
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def record(value)
|
|
91
|
+
bad unless value.instance_of?(Hash)
|
|
92
|
+
value
|
|
93
|
+
end
|
|
94
|
+
def valid_json_strings?(value)
|
|
95
|
+
case value
|
|
96
|
+
when String then value.valid_encoding?
|
|
97
|
+
when Array then value.all? { |item| valid_json_strings?(item) }
|
|
98
|
+
when Hash then value.all? { |key, item| valid_json_strings?(key) && valid_json_strings?(item) }
|
|
99
|
+
else true
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
def string(value)
|
|
103
|
+
bad unless value.instance_of?(String) && !value.strip.empty?
|
|
104
|
+
value
|
|
105
|
+
end
|
|
106
|
+
def integer(value)
|
|
107
|
+
bad unless finite?(value) && value == value.to_i && value.abs <= MAX_SAFE
|
|
108
|
+
value.to_i
|
|
109
|
+
end
|
|
110
|
+
def nonnegative(value)
|
|
111
|
+
n = integer(value)
|
|
112
|
+
bad if n.negative?
|
|
113
|
+
n
|
|
114
|
+
end
|
|
115
|
+
def id(value)
|
|
116
|
+
n = integer(value)
|
|
117
|
+
bad unless n.positive?
|
|
118
|
+
n
|
|
119
|
+
end
|
|
120
|
+
def boolean(value)
|
|
121
|
+
bad unless value == true || value == false
|
|
122
|
+
value
|
|
123
|
+
end
|
|
124
|
+
def member(value, allowed)
|
|
125
|
+
bad unless value.instance_of?(String) && allowed.include?(value)
|
|
126
|
+
value
|
|
127
|
+
end
|
|
128
|
+
def optional_strings(value, names)
|
|
129
|
+
names.each { |name| bad if value.key?(name) && !value[name].instance_of?(String) }
|
|
130
|
+
end
|
|
131
|
+
def select(value, names) = value.select { |name, _| names.include?(name) }
|
|
132
|
+
def metadata_response(value, maximum = 8192)
|
|
133
|
+
customer_data(value, maximum)
|
|
134
|
+
rescue Error
|
|
135
|
+
bad('Invalid customer metadata response.')
|
|
136
|
+
end
|
|
137
|
+
def urls(value)
|
|
138
|
+
%w[cdn_url cdn_url_avif private_url].each do |name|
|
|
139
|
+
next unless value.key?(name)
|
|
140
|
+
url = string(value[name])
|
|
141
|
+
uri = URI.parse(url)
|
|
142
|
+
bad('Invalid delivery URL.') unless %w[http https].include?(uri.scheme) && uri.host && !uri.userinfo && !/[\x00-\x20\x7f]/.match?(url) && uri.port.between?(1, 65_535)
|
|
143
|
+
end
|
|
144
|
+
rescue URI::InvalidURIError, ArgumentError
|
|
145
|
+
bad('Invalid delivery URL.')
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def upload(value, accepted: false)
|
|
149
|
+
v = record(value)
|
|
150
|
+
result = select(v, %w[status visibility deletion_status original_name original_size asset_type deletion_requested_at external_id created_at input_format output_format private_url_expires_at cdn_url cdn_url_avif private_url data options quality warning])
|
|
151
|
+
result['id'] = id(v[accepted ? 'asset_id' : 'id'])
|
|
152
|
+
member(v['status'], PROCESSING)
|
|
153
|
+
member(v['visibility'], %w[public private])
|
|
154
|
+
member(v['deletion_status'], DELETION)
|
|
155
|
+
result['original_size'] = nonnegative(v['original_size'])
|
|
156
|
+
string(v['original_name']) if accepted
|
|
157
|
+
string(v['asset_type'])
|
|
158
|
+
optional_strings(v, %w[original_name deletion_requested_at external_id created_at input_format output_format private_url_expires_at warning])
|
|
159
|
+
urls(v)
|
|
160
|
+
bad('Private asset response contains a public URL.') if v['visibility'] == 'private' && %w[cdn_url cdn_url_avif].any? { |name| v.key?(name) }
|
|
161
|
+
bad('Deleted asset response contains a delivery URL.') if v['deletion_status'] != 'active' && %w[cdn_url cdn_url_avif private_url].any? { |name| v.key?(name) }
|
|
162
|
+
result['data'] = metadata_response(v['data']) if v.key?('data')
|
|
163
|
+
bad if v.key?('options') && record(v['options']).values.any? { |item| !item.instance_of?(String) }
|
|
164
|
+
member(v['quality'], %w[480p 720p 1080p 4k]) if v.key?('quality')
|
|
165
|
+
unless accepted
|
|
166
|
+
result['kompressd_size'] = nonnegative(v['kompressd_size'])
|
|
167
|
+
result['can_generate_private_url'] = boolean(v['can_generate_private_url'])
|
|
168
|
+
bad unless finite?(v['savings_percent'])
|
|
169
|
+
result['savings_percent'] = v['savings_percent']
|
|
170
|
+
end
|
|
171
|
+
result
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def private_url(value)
|
|
175
|
+
v = record(value)
|
|
176
|
+
id(v['asset_id'])
|
|
177
|
+
member(v['variant'], %w[webp avif])
|
|
178
|
+
urls(v)
|
|
179
|
+
string(v['private_url'])
|
|
180
|
+
string(v['expires_at'])
|
|
181
|
+
bad unless integer(v['expires_in']).between?(60, 604_800)
|
|
182
|
+
select(v, %w[asset_id variant private_url expires_at expires_in])
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def asset_state(value)
|
|
186
|
+
v = record(value)
|
|
187
|
+
id(v['id']); id(v['kind']); nonnegative(v['storage_credited_mb'])
|
|
188
|
+
string(v['project_id']); integer(v['processing_status'])
|
|
189
|
+
member(v['deletion_status'], DELETION); member(v['source'], %w[upload origin])
|
|
190
|
+
optional_strings(v, %w[deletion_requested_at])
|
|
191
|
+
member(v['accounting_status'], %w[pending settled unavailable]) if v.key?('accounting_status')
|
|
192
|
+
result = select(v, %w[id project_id kind source processing_status deletion_status storage_credited_mb deletion_requested_at accounting_status])
|
|
193
|
+
if v.key?('last_failure')
|
|
194
|
+
failure = record(v['last_failure'])
|
|
195
|
+
%w[code message at].each { |key| string(failure[key]) }
|
|
196
|
+
result['last_failure'] = select(failure, %w[code message at])
|
|
197
|
+
end
|
|
198
|
+
result
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def page(value, key = 'data', &parse)
|
|
202
|
+
v = record(value)
|
|
203
|
+
bad unless v[key].instance_of?(Array)
|
|
204
|
+
result = { 'data' => v[key].map(&parse), 'page' => id(v['page']), 'limit' => id(v['limit']), 'total' => nonnegative(v['total']) }
|
|
205
|
+
bad if result['limit'] > 100 || result['data'].size > result['limit']
|
|
206
|
+
result
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def bulk(value, expected)
|
|
210
|
+
v = record(value)
|
|
211
|
+
counts = record(v['counts'])
|
|
212
|
+
bad unless v['results'].instance_of?(Array) && v['results'].size == expected.size
|
|
213
|
+
accepted = 0
|
|
214
|
+
rows = v['results'].each_with_index.map do |item, index|
|
|
215
|
+
row = record(item)
|
|
216
|
+
bad unless id(row['id']) == expected[index]
|
|
217
|
+
ok = boolean(row['accepted']); status = integer(row['status'])
|
|
218
|
+
output = select(row, %w[id status accepted code error])
|
|
219
|
+
optional_strings(row, %w[code error])
|
|
220
|
+
if ok
|
|
221
|
+
accepted += 1
|
|
222
|
+
state = asset_state(row['state'])
|
|
223
|
+
bad unless [200, 202].include?(status) && state['id'] == row['id'] && state['deletion_status'] != 'active'
|
|
224
|
+
output['state'] = state
|
|
225
|
+
else
|
|
226
|
+
bad unless status >= 400
|
|
227
|
+
string(row['error'])
|
|
228
|
+
end
|
|
229
|
+
output
|
|
230
|
+
end
|
|
231
|
+
expected_counts = { 'total' => expected.size, 'accepted' => accepted, 'failed' => expected.size - accepted }
|
|
232
|
+
expected_counts.each { |key, n| bad unless integer(counts[key]) == n }
|
|
233
|
+
{ 'results' => rows, 'counts' => expected_counts }
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def project_user(value)
|
|
237
|
+
v = record(value)
|
|
238
|
+
%w[id project_id customer_user_id].each { |name| string(v[name]) }
|
|
239
|
+
member(v['status'], %w[active suspended])
|
|
240
|
+
optional_strings(v, %w[display_name created_at last_seen_at last_upload_at last_key_used_at])
|
|
241
|
+
numbers = %w[asset_count storage_bytes active_key_count bandwidth_bytes_current_period requests_current_period]
|
|
242
|
+
numbers.each { |name| nonnegative(v[name]) if v.key?(name) }
|
|
243
|
+
result = select(v, %w[id project_id customer_user_id status display_name created_at last_seen_at last_upload_at last_key_used_at] + numbers)
|
|
244
|
+
result['metadata'] = metadata_response(v['metadata']) if v.key?('metadata')
|
|
245
|
+
result
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def upload_key(value)
|
|
249
|
+
v = record(value)
|
|
250
|
+
%w[id key_id project_id project_user_id name].each { |name| string(v[name]) }
|
|
251
|
+
bad unless v['scopes'].instance_of?(Array) && v['scopes'].all? { |s| SCOPES.include?(s) }
|
|
252
|
+
member(v['allowed_visibility'], %w[public private both])
|
|
253
|
+
if v.key?('allowed_asset_types')
|
|
254
|
+
bad unless v['allowed_asset_types'].instance_of?(Array)
|
|
255
|
+
v['allowed_asset_types'].each { |type| id(type) }
|
|
256
|
+
end
|
|
257
|
+
%w[expires_at revoked_at last_used_at].each { |key| bad if v.key?(key) && !v[key].nil? && !v[key].instance_of?(String) }
|
|
258
|
+
optional_strings(v, %w[created_at])
|
|
259
|
+
select(v, %w[id key_id project_id project_user_id name scopes allowed_visibility allowed_asset_types expires_at revoked_at last_used_at created_at])
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def success(value)
|
|
263
|
+
v = record(value)
|
|
264
|
+
bad unless v['success'] == true
|
|
265
|
+
v
|
|
266
|
+
end
|
|
267
|
+
def data(value)
|
|
268
|
+
v = success(value)
|
|
269
|
+
bad unless v.key?('data')
|
|
270
|
+
v['data']
|
|
271
|
+
end
|
|
272
|
+
def issued(value)
|
|
273
|
+
v = success(value)
|
|
274
|
+
IssuedKey.new(id: string(v['id']), key_id: string(v['key_id']), api_key: string(v['api_key']),
|
|
275
|
+
upload_key: v.key?('upload_key') ? upload_key(v['upload_key']) : nil)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
data/lib/kompressr.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'kompressr/version'
|
|
4
|
+
require_relative 'kompressr/error'
|
|
5
|
+
require_relative 'kompressr/validation'
|
|
6
|
+
require_relative 'kompressr/transport'
|
|
7
|
+
require_relative 'kompressr/platform_client'
|
|
8
|
+
require_relative 'kompressr/client'
|
metadata
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: kompressr-sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kompressr
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: json
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.7'
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '3'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '2.7'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '3'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: openssl
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '3.2'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '5'
|
|
42
|
+
type: :runtime
|
|
43
|
+
prerelease: false
|
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '3.2'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '5'
|
|
52
|
+
- !ruby/object:Gem::Dependency
|
|
53
|
+
name: uri
|
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0.13'
|
|
59
|
+
- - "<"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0.13'
|
|
69
|
+
- - "<"
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: '2'
|
|
72
|
+
- !ruby/object:Gem::Dependency
|
|
73
|
+
name: time
|
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: '0.3'
|
|
79
|
+
- - "<"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1'
|
|
82
|
+
type: :runtime
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0.3'
|
|
89
|
+
- - "<"
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: '1'
|
|
92
|
+
- !ruby/object:Gem::Dependency
|
|
93
|
+
name: ipaddr
|
|
94
|
+
requirement: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - ">="
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: 1.2.5
|
|
99
|
+
- - "<"
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '2'
|
|
102
|
+
type: :runtime
|
|
103
|
+
prerelease: false
|
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: 1.2.5
|
|
109
|
+
- - "<"
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '2'
|
|
112
|
+
- !ruby/object:Gem::Dependency
|
|
113
|
+
name: securerandom
|
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
|
115
|
+
requirements:
|
|
116
|
+
- - ">="
|
|
117
|
+
- !ruby/object:Gem::Version
|
|
118
|
+
version: '0.3'
|
|
119
|
+
- - "<"
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: '1'
|
|
122
|
+
type: :runtime
|
|
123
|
+
prerelease: false
|
|
124
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - ">="
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: '0.3'
|
|
129
|
+
- - "<"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '1'
|
|
132
|
+
description: Upload, wait for processing, sign private links and manage scoped identities
|
|
133
|
+
using a framework-independent Ruby client.
|
|
134
|
+
executables: []
|
|
135
|
+
extensions: []
|
|
136
|
+
extra_rdoc_files: []
|
|
137
|
+
files:
|
|
138
|
+
- API.md
|
|
139
|
+
- CHANGELOG.md
|
|
140
|
+
- LICENSE
|
|
141
|
+
- PARITY.md
|
|
142
|
+
- README.md
|
|
143
|
+
- examples/private_upload.rb
|
|
144
|
+
- examples/rails_service.rb
|
|
145
|
+
- lib/kompressr.rb
|
|
146
|
+
- lib/kompressr/client.rb
|
|
147
|
+
- lib/kompressr/error.rb
|
|
148
|
+
- lib/kompressr/platform_client.rb
|
|
149
|
+
- lib/kompressr/transport.rb
|
|
150
|
+
- lib/kompressr/validation.rb
|
|
151
|
+
- lib/kompressr/version.rb
|
|
152
|
+
homepage: https://kompressr.com
|
|
153
|
+
licenses:
|
|
154
|
+
- MIT
|
|
155
|
+
metadata:
|
|
156
|
+
source_code_uri: https://github.com/kompressrcdn/clients/tree/main/sdk-ruby
|
|
157
|
+
documentation_uri: https://github.com/kompressrcdn/clients/blob/main/sdk-ruby/README.md
|
|
158
|
+
changelog_uri: https://github.com/kompressrcdn/clients/blob/main/sdk-ruby/CHANGELOG.md
|
|
159
|
+
bug_tracker_uri: https://github.com/kompressrcdn/clients/issues
|
|
160
|
+
allowed_push_host: https://rubygems.org
|
|
161
|
+
rubygems_mfa_required: 'true'
|
|
162
|
+
rdoc_options: []
|
|
163
|
+
require_paths:
|
|
164
|
+
- lib
|
|
165
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - ">="
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '3.2'
|
|
170
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
|
+
requirements:
|
|
172
|
+
- - ">="
|
|
173
|
+
- !ruby/object:Gem::Version
|
|
174
|
+
version: '0'
|
|
175
|
+
requirements: []
|
|
176
|
+
rubygems_version: 4.0.16
|
|
177
|
+
specification_version: 4
|
|
178
|
+
summary: Official Ruby SDK for Kompressr file and platform APIs.
|
|
179
|
+
test_files: []
|