fireimg 1.0.0 → 1.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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +21 -9
- data/lib/fireimg/client.rb +85 -0
- data/lib/fireimg/upload_result.rb +15 -0
- data/lib/fireimg/version.rb +1 -1
- data/lib/fireimg.rb +9 -0
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5926fd58382eaafd20085a2f21c6857f81b6be3cd832cb73d80cd81497d59ebc
|
|
4
|
+
data.tar.gz: c8ff329a137b3e4a5e2783367f7a082f2c37ef71c5ee4cc77e29dc21c9321652
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3473e296a6204d7c541eac38528ebb7088d77e9127d682237d343975acb895b21272ea780481dc7327515d62f135b99dde6a3b0a9db25ec2d83af3da97fb8fdb
|
|
7
|
+
data.tar.gz: 879d5d4c5cf51e878d1c140a2f291651a7391d8db7c9595879708371cbb2a87af861f525afc3c6cabb3391b845bbde91f15cf4d2adfe7097d4782cba2ee5701c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
- `Fireimg.upload` / `upload_many` presign then PUT, matching the FireImg CLI
|
|
6
|
+
- `presign` remains for apps that PUT from the client (NeedApp native/web)
|
|
7
|
+
|
|
3
8
|
## 1.0.0
|
|
4
9
|
|
|
5
10
|
- Presign uploads (folder keys, optional `sizes` to pre-generate variants)
|
data/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Source of truth is developed in the private FireImg repo and mirrored here.
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
10
|
```ruby
|
|
11
|
-
gem 'fireimg', '~> 1.
|
|
11
|
+
gem 'fireimg', '~> 1.1'
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
```bash
|
|
@@ -31,23 +31,35 @@ the block. `FIREIMG_API_BASE` and `FIREIMG_CDN_BASE` have the defaults above.
|
|
|
31
31
|
|
|
32
32
|
## Upload
|
|
33
33
|
|
|
34
|
+
`Fireimg.upload` does both steps the CLI does: request a presigned URL, then
|
|
35
|
+
PUT the bytes.
|
|
36
|
+
|
|
34
37
|
```ruby
|
|
35
|
-
result = Fireimg.
|
|
38
|
+
result = Fireimg.upload(
|
|
36
39
|
filename: 'feed_items/43/uuid.jpg',
|
|
37
40
|
content_type: 'image/jpeg',
|
|
41
|
+
path: '/tmp/photo.jpg', # or io: / body:
|
|
38
42
|
sizes: [
|
|
39
|
-
{ width: 800, quality: 'medium' },
|
|
40
|
-
{ width: 160, height: 160, fit: 'cover', pos: 'center' }
|
|
43
|
+
{ width: 800, quality: 'medium', fmt: 'webp' },
|
|
44
|
+
{ width: 160, height: 160, fit: 'cover', pos: 'center', fmt: 'webp' }
|
|
41
45
|
]
|
|
42
46
|
)
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
result.image_key # => "feed_items/43/uuid.jpg"
|
|
49
|
+
result.cdn_url # => "https://img.fireimg.com/{project}/images/feed_items/43/uuid.jpg"
|
|
45
50
|
```
|
|
46
51
|
|
|
47
|
-
`filename` may include folders.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
to pre-generate only
|
|
52
|
+
`filename` may include folders. Provide the bytes with `path:`, `io:`, or
|
|
53
|
+
`body:`. Optional `sizes` (up to 20) are generated asynchronously after the
|
|
54
|
+
`PUT` and **replace** the project's default image params for that upload. Omit
|
|
55
|
+
`sizes` to keep project defaults. Pass `sizes: []` to pre-generate only
|
|
56
|
+
FireImg's 80px dashboard thumbnail.
|
|
57
|
+
|
|
58
|
+
`Fireimg.upload_many(files:, sizes:)` batches the same way as the CLI
|
|
59
|
+
(up to 20 files per presign request).
|
|
60
|
+
|
|
61
|
+
If the client PUTs directly (NeedApp native/web), use `Fireimg.presign` and
|
|
62
|
+
PUT to `result.upload_url` with the same `Content-Type`.
|
|
51
63
|
|
|
52
64
|
## Moderate and delete
|
|
53
65
|
|
data/lib/fireimg/client.rb
CHANGED
|
@@ -46,6 +46,55 @@ module Fireimg
|
|
|
46
46
|
rows.first
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
# Presign + PUT, matching `fireimg upload` in the CLI.
|
|
50
|
+
# Provide the bytes with `path:`, `io:`, or `body:`.
|
|
51
|
+
def upload(filename:, content_type:, sizes: nil, **source)
|
|
52
|
+
rows = upload_many(
|
|
53
|
+
files: [source.merge(filename: filename, content_type: content_type)],
|
|
54
|
+
sizes: sizes
|
|
55
|
+
)
|
|
56
|
+
raise Error, 'FireImg upload returned no results' if rows.empty?
|
|
57
|
+
|
|
58
|
+
rows.first
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def upload_many(files:, sizes: nil)
|
|
62
|
+
list = Array(files)
|
|
63
|
+
raise Error, 'files cannot be empty' if list.empty?
|
|
64
|
+
|
|
65
|
+
prepared = []
|
|
66
|
+
seen = {}
|
|
67
|
+
list.each do |file|
|
|
68
|
+
payload = file_payload(file)
|
|
69
|
+
name = payload['filename']
|
|
70
|
+
raise Error, "duplicate filename #{name.inspect}" if seen.key?(name)
|
|
71
|
+
|
|
72
|
+
seen[name] = true
|
|
73
|
+
prepared << {
|
|
74
|
+
payload: payload,
|
|
75
|
+
content_type: payload['contentType'],
|
|
76
|
+
bytes: read_bytes(file)
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
rows = presign_many(files: prepared.map { |item| item[:payload] }, sizes: sizes)
|
|
81
|
+
by_name = prepared.to_h { |item| [item[:payload]['filename'], item] }
|
|
82
|
+
|
|
83
|
+
rows.map do |row|
|
|
84
|
+
item = by_name[row.filename]
|
|
85
|
+
raise Error, "presign returned unexpected filename #{row.filename.inspect}" if item.nil?
|
|
86
|
+
|
|
87
|
+
put(row.upload_url, item[:content_type], item[:bytes])
|
|
88
|
+
image_key = row.filename.to_s.sub(%r{\A/+}, '')
|
|
89
|
+
UploadResult.new(
|
|
90
|
+
filename: image_key,
|
|
91
|
+
image_key: image_key,
|
|
92
|
+
cdn_url: public_url(image_key),
|
|
93
|
+
s3_key: row.s3_key
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
49
98
|
def presign_many(files:, sizes: nil)
|
|
50
99
|
payload = {
|
|
51
100
|
'slug' => project,
|
|
@@ -88,6 +137,42 @@ module Fireimg
|
|
|
88
137
|
)
|
|
89
138
|
end
|
|
90
139
|
|
|
140
|
+
def read_bytes(file)
|
|
141
|
+
h = stringify_keys(file)
|
|
142
|
+
if (path = h['path']).to_s.strip != ''
|
|
143
|
+
File.binread(path)
|
|
144
|
+
elsif (io = h['io'])
|
|
145
|
+
io = io.to_io if io.respond_to?(:to_io) && !io.respond_to?(:read)
|
|
146
|
+
io.binmode if io.respond_to?(:binmode)
|
|
147
|
+
io.rewind if io.respond_to?(:rewind)
|
|
148
|
+
io.read
|
|
149
|
+
elsif !h['body'].nil?
|
|
150
|
+
bytes = h['body']
|
|
151
|
+
bytes.respond_to?(:b) ? bytes.b : bytes.to_s
|
|
152
|
+
else
|
|
153
|
+
raise Error, 'path, io, or body is required'
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def put(upload_url, content_type, body)
|
|
158
|
+
raise Error, 'upload URL is required' if upload_url.to_s.strip.empty?
|
|
159
|
+
|
|
160
|
+
uri = URI.parse(upload_url)
|
|
161
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
162
|
+
http.use_ssl = uri.scheme == 'https'
|
|
163
|
+
http.open_timeout = 5
|
|
164
|
+
http.read_timeout = 60
|
|
165
|
+
req = Net::HTTP::Put.new(uri.request_uri)
|
|
166
|
+
req['Content-Type'] = content_type
|
|
167
|
+
req.body = body
|
|
168
|
+
res = http.request(req)
|
|
169
|
+
return true if res.is_a?(Net::HTTPSuccess)
|
|
170
|
+
|
|
171
|
+
message = res.body.to_s.strip
|
|
172
|
+
message = res.message if message.empty?
|
|
173
|
+
raise Error, "FireImg PUT #{res.code}: #{message[0, 200]}"
|
|
174
|
+
end
|
|
175
|
+
|
|
91
176
|
def query_string(options)
|
|
92
177
|
params = []
|
|
93
178
|
w = options[:width]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fireimg
|
|
4
|
+
# Result of a completed upload (presign + PUT), matching the FireImg CLI.
|
|
5
|
+
UploadResult = Struct.new(:filename, :image_key, :cdn_url, :s3_key, keyword_init: true) do
|
|
6
|
+
def to_h
|
|
7
|
+
{
|
|
8
|
+
'filename' => filename,
|
|
9
|
+
'image_key' => image_key,
|
|
10
|
+
'cdn_url' => cdn_url,
|
|
11
|
+
's3_key' => s3_key
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/fireimg/version.rb
CHANGED
data/lib/fireimg.rb
CHANGED
|
@@ -5,6 +5,7 @@ require_relative 'fireimg/error'
|
|
|
5
5
|
require_relative 'fireimg/configuration'
|
|
6
6
|
require_relative 'fireimg/size'
|
|
7
7
|
require_relative 'fireimg/presign_result'
|
|
8
|
+
require_relative 'fireimg/upload_result'
|
|
8
9
|
require_relative 'fireimg/client'
|
|
9
10
|
|
|
10
11
|
module Fireimg
|
|
@@ -40,6 +41,14 @@ module Fireimg
|
|
|
40
41
|
client.url(image_key, **options)
|
|
41
42
|
end
|
|
42
43
|
|
|
44
|
+
def upload(...)
|
|
45
|
+
client.upload(...)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def upload_many(...)
|
|
49
|
+
client.upload_many(...)
|
|
50
|
+
end
|
|
51
|
+
|
|
43
52
|
def presign(...)
|
|
44
53
|
client.presign(...)
|
|
45
54
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fireimg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Firelit Studio
|
|
@@ -11,10 +11,10 @@ cert_chain: []
|
|
|
11
11
|
date: 2026-08-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
|
-
Server-side Ruby client for FireImg.
|
|
14
|
+
Server-side Ruby client for FireImg. Upload images (presign + PUT, including
|
|
15
15
|
folder keys and optional pre-generated sizes), run content moderation, and
|
|
16
|
-
build CDN URLs. Matches the FireImg API-key HTTP API
|
|
17
|
-
query parameters.
|
|
16
|
+
build CDN URLs. Matches the FireImg API-key HTTP API, the FireImg CLI upload
|
|
17
|
+
flow, and @fireimg/js URL query parameters.
|
|
18
18
|
email:
|
|
19
19
|
- hello@firelit.studio
|
|
20
20
|
executables: []
|
|
@@ -30,6 +30,7 @@ files:
|
|
|
30
30
|
- lib/fireimg/error.rb
|
|
31
31
|
- lib/fireimg/presign_result.rb
|
|
32
32
|
- lib/fireimg/size.rb
|
|
33
|
+
- lib/fireimg/upload_result.rb
|
|
33
34
|
- lib/fireimg/version.rb
|
|
34
35
|
homepage: https://github.com/FirelitStudio/fireimg-ruby
|
|
35
36
|
licenses:
|