buchida 0.1.2 → 0.2.1
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/lib/buchida/client.rb +34 -3
- data/lib/buchida/resources/api_keys.rb +2 -2
- data/lib/buchida/resources/domains.rb +4 -4
- data/lib/buchida/resources/emails.rb +16 -9
- data/lib/buchida/resources/metrics.rb +3 -2
- data/lib/buchida/resources/templates.rb +8 -3
- data/lib/buchida/resources/webhooks.rb +2 -2
- data/lib/buchida/response.rb +120 -0
- data/lib/buchida/version.rb +1 -1
- data/lib/buchida.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7dbd112ad5d392d35ec62955149963bbec35a8765644c4305939fb42d985b4de
|
|
4
|
+
data.tar.gz: bee7497ebefacd406ff96a6501e09df13e4b8009b5d814bdcbd79b4edec81aea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 104960ce3956b0c51b243139a74c14fd045eef4d7f391d4b1bf41f0ccbdc290852507391cdd65d278b85b13ce89cea92d35260b6f5a8f6ffb7b80598ca917720
|
|
7
|
+
data.tar.gz: 814f8c84b3398dd20ba19d852523c946afd8099676db8cade70d9f3fe3c8724ef958fbcce35cd6bc1695c9f388ffd62a54a2dd9a7ed48b0d32da51ca68279553
|
data/lib/buchida/client.rb
CHANGED
|
@@ -6,7 +6,7 @@ require "json"
|
|
|
6
6
|
|
|
7
7
|
module Buchida
|
|
8
8
|
class Client
|
|
9
|
-
DEFAULT_BASE_URL = "https://api.buchida.com"
|
|
9
|
+
DEFAULT_BASE_URL = "https://api.buchida.com/v1"
|
|
10
10
|
DEFAULT_TIMEOUT = 30
|
|
11
11
|
|
|
12
12
|
attr_reader :emails, :domains, :api_keys, :webhooks, :templates, :metrics
|
|
@@ -57,8 +57,32 @@ module Buchida
|
|
|
57
57
|
JSON.parse(response.body)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# Request returning a single object: unwraps `{ "data" => {...} }` (204 => nil).
|
|
61
|
+
def request_object(method, path, body = nil)
|
|
62
|
+
unwrap_object(request(method, path, body))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Request returning a list: unwraps `{ "data" => [...], "cursor" =>, "hasMore" => }`.
|
|
66
|
+
def request_list(method, path, body = nil)
|
|
67
|
+
resp = request(method, path, body)
|
|
68
|
+
if resp.is_a?(Hash)
|
|
69
|
+
ListResult.new(resp["data"] || [], cursor: resp["cursor"], has_more: resp["hasMore"] || resp["has_more"] || false)
|
|
70
|
+
elsif resp.is_a?(Array)
|
|
71
|
+
ListResult.new(resp)
|
|
72
|
+
else
|
|
73
|
+
resp
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
60
77
|
private
|
|
61
78
|
|
|
79
|
+
def unwrap_object(resp)
|
|
80
|
+
return resp unless resp.is_a?(Hash)
|
|
81
|
+
|
|
82
|
+
inner = resp.key?("data") ? resp["data"] : resp
|
|
83
|
+
inner.is_a?(Hash) ? Result[inner] : inner
|
|
84
|
+
end
|
|
85
|
+
|
|
62
86
|
def handle_error(response)
|
|
63
87
|
body = begin
|
|
64
88
|
JSON.parse(response.body)
|
|
@@ -66,7 +90,14 @@ module Buchida
|
|
|
66
90
|
{ "message" => response.message }
|
|
67
91
|
end
|
|
68
92
|
|
|
69
|
-
|
|
93
|
+
err = body["error"]
|
|
94
|
+
if err.is_a?(Hash)
|
|
95
|
+
message = err["message"] || response.message
|
|
96
|
+
error_code = err["code"]
|
|
97
|
+
else
|
|
98
|
+
message = body["message"] || response.message
|
|
99
|
+
error_code = body["code"]
|
|
100
|
+
end
|
|
70
101
|
status = response.code.to_i
|
|
71
102
|
|
|
72
103
|
case status
|
|
@@ -74,7 +105,7 @@ module Buchida
|
|
|
74
105
|
when 404 then raise NotFoundError, message
|
|
75
106
|
when 422 then raise ValidationError, message
|
|
76
107
|
when 429 then raise RateLimitError, message
|
|
77
|
-
else raise Error.new(message, status,
|
|
108
|
+
else raise Error.new(message, status, error_code)
|
|
78
109
|
end
|
|
79
110
|
end
|
|
80
111
|
end
|
|
@@ -8,11 +8,11 @@ module Buchida
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def create(name:, permission:)
|
|
11
|
-
@client.
|
|
11
|
+
@client.request_object(:post, "/api-keys", { name: name, permission: permission })
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def list
|
|
15
|
-
@client.
|
|
15
|
+
@client.request_list(:get, "/api-keys")
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def delete(id)
|
|
@@ -8,19 +8,19 @@ module Buchida
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def create(name:)
|
|
11
|
-
@client.
|
|
11
|
+
@client.request_object(:post, "/domains", { name: name })
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def list
|
|
15
|
-
@client.
|
|
15
|
+
@client.request_list(:get, "/domains")
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def get(id)
|
|
19
|
-
@client.
|
|
19
|
+
@client.request_object(:get, "/domains/#{id}")
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def verify(id)
|
|
23
|
-
@client.
|
|
23
|
+
@client.request_object(:post, "/domains/#{id}/verify")
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
end
|
|
@@ -7,40 +7,47 @@ module Buchida
|
|
|
7
7
|
@client = client
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def send(from:, to:, subject:, html: nil, text: nil, reply_to: nil, cc: nil, bcc: nil, tags: nil, scheduled_at: nil)
|
|
10
|
+
def send(from:, to:, subject:, html: nil, text: nil, reply_to: nil, cc: nil, bcc: nil, tags: nil, scheduled_at: nil, from_name: nil)
|
|
11
11
|
body = { from: from, to: to, subject: subject }
|
|
12
|
+
body[:from_name] = from_name if from_name
|
|
12
13
|
body[:html] = html if html
|
|
13
14
|
body[:text] = text if text
|
|
14
|
-
body[:
|
|
15
|
+
body[:reply_to] = reply_to if reply_to
|
|
15
16
|
body[:cc] = cc if cc
|
|
16
17
|
body[:bcc] = bcc if bcc
|
|
17
18
|
body[:tags] = tags if tags
|
|
18
|
-
body[:
|
|
19
|
-
@client.
|
|
19
|
+
body[:scheduled_at] = scheduled_at if scheduled_at
|
|
20
|
+
@client.request_object(:post, "/emails", body)
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def get(id)
|
|
23
|
-
@client.
|
|
24
|
+
@client.request_object(:get, "/emails/#{id}")
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
# +from+ / +to+ filter by sender / recipient ADDRESS (not dates).
|
|
28
|
+
# +from_date+ / +to_date+ (ISO 8601) filter by creation date;
|
|
29
|
+
# +direction+ is "inbound" or "outbound".
|
|
30
|
+
def list(cursor: nil, limit: nil, status: nil, from: nil, to: nil, from_date: nil, to_date: nil, direction: nil)
|
|
27
31
|
params = {}
|
|
28
32
|
params[:cursor] = cursor if cursor
|
|
29
33
|
params[:limit] = limit if limit
|
|
30
34
|
params[:status] = status if status
|
|
31
35
|
params[:from] = from if from
|
|
32
36
|
params[:to] = to if to
|
|
37
|
+
params[:from_date] = from_date if from_date
|
|
38
|
+
params[:to_date] = to_date if to_date
|
|
39
|
+
params[:direction] = direction if direction
|
|
33
40
|
qs = URI.encode_www_form(params) unless params.empty?
|
|
34
41
|
path = qs ? "/emails?#{qs}" : "/emails"
|
|
35
|
-
@client.
|
|
42
|
+
@client.request_list(:get, path)
|
|
36
43
|
end
|
|
37
44
|
|
|
38
45
|
def cancel(id)
|
|
39
|
-
@client.
|
|
46
|
+
@client.request_object(:post, "/emails/#{id}/cancel")
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
def send_batch(emails)
|
|
43
|
-
@client.
|
|
50
|
+
@client.request_list(:post, "/emails/batch", emails)
|
|
44
51
|
end
|
|
45
52
|
end
|
|
46
53
|
end
|
|
@@ -8,10 +8,11 @@ module Buchida
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def get(from:, to:, granularity: nil)
|
|
11
|
-
|
|
11
|
+
# The API filters on from_date/to_date; plain from/to were silently ignored.
|
|
12
|
+
params = { from_date: from, to_date: to }
|
|
12
13
|
params[:granularity] = granularity if granularity
|
|
13
14
|
qs = URI.encode_www_form(params)
|
|
14
|
-
@client.
|
|
15
|
+
@client.request_object(:get, "/metrics?#{qs}")
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
@@ -7,12 +7,17 @@ module Buchida
|
|
|
7
7
|
@client = client
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
# +status+ is "draft" or "published"; +search+ matches name/subject.
|
|
11
|
+
def list(status: nil, search: nil)
|
|
12
|
+
params = {}
|
|
13
|
+
params[:status] = status if status
|
|
14
|
+
params[:search] = search if search
|
|
15
|
+
path = params.empty? ? "/templates" : "/templates?#{URI.encode_www_form(params)}"
|
|
16
|
+
@client.request_list(:get, path)
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
def get(id)
|
|
15
|
-
@client.
|
|
20
|
+
@client.request_object(:get, "/templates/#{id}")
|
|
16
21
|
end
|
|
17
22
|
end
|
|
18
23
|
end
|
|
@@ -8,11 +8,11 @@ module Buchida
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def create(url:, events:)
|
|
11
|
-
@client.
|
|
11
|
+
@client.request_object(:post, "/webhooks", { url: url, events: events })
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def list
|
|
15
|
-
@client.
|
|
15
|
+
@client.request_list(:get, "/webhooks")
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def delete(id)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Buchida
|
|
4
|
+
# Deprecation helper for the pre-0.2 raw-envelope access (`res["data"]`).
|
|
5
|
+
module Legacy
|
|
6
|
+
@warned = false
|
|
7
|
+
|
|
8
|
+
def self.warn_once(what)
|
|
9
|
+
return if @warned
|
|
10
|
+
|
|
11
|
+
@warned = true
|
|
12
|
+
Kernel.warn("[buchida] DEPRECATION: #{what} is deprecated. Since buchida 0.2 the SDK " \
|
|
13
|
+
"returns the unwrapped payload; use the result directly.")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.data_key?(key)
|
|
17
|
+
key == "data" || key == :data
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# An unwrapped single-object response (a Hash with String keys, as before).
|
|
22
|
+
# `result["data"]` / `result[:data]` still return the same object, with a one-time
|
|
23
|
+
# deprecation warning, so code written against the raw `{ "data" => {...} }` envelope keeps working.
|
|
24
|
+
# No self-reference is stored, so `to_json` / `JSON.generate` are unaffected.
|
|
25
|
+
class Result < Hash
|
|
26
|
+
REAL_KEY = Hash.instance_method(:key?)
|
|
27
|
+
|
|
28
|
+
def [](key)
|
|
29
|
+
if Legacy.data_key?(key) && !REAL_KEY.bind(self).call("data")
|
|
30
|
+
Legacy.warn_once("result[\"data\"]")
|
|
31
|
+
return self
|
|
32
|
+
end
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def key?(key)
|
|
37
|
+
Legacy.data_key?(key) || super
|
|
38
|
+
end
|
|
39
|
+
alias_method :has_key?, :key?
|
|
40
|
+
alias_method :include?, :key?
|
|
41
|
+
alias_method :member?, :key?
|
|
42
|
+
|
|
43
|
+
def fetch(key, *args, &block)
|
|
44
|
+
if Legacy.data_key?(key) && !REAL_KEY.bind(self).call("data")
|
|
45
|
+
Legacy.warn_once("result.fetch(\"data\")")
|
|
46
|
+
return self
|
|
47
|
+
end
|
|
48
|
+
super
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def dig(key, *rest)
|
|
52
|
+
value = self[key]
|
|
53
|
+
rest.empty? || value.nil? ? value : value.dig(*rest)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# An unwrapped list response: an Array of items plus `cursor` and `has_more`.
|
|
58
|
+
# The old envelope keys (`res["data"]`, `res["cursor"]`, `res["hasMore"]`) still work, with a
|
|
59
|
+
# one-time deprecation warning.
|
|
60
|
+
class ListResult < Array
|
|
61
|
+
attr_reader :cursor, :has_more
|
|
62
|
+
|
|
63
|
+
def initialize(items = [], cursor: nil, has_more: false)
|
|
64
|
+
super(items)
|
|
65
|
+
@cursor = cursor
|
|
66
|
+
@has_more = has_more
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def data
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def has_more?
|
|
74
|
+
@has_more ? true : false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
LEGACY_KEYS = %w[data cursor hasMore has_more].freeze
|
|
78
|
+
|
|
79
|
+
def self.legacy_key?(key)
|
|
80
|
+
(key.is_a?(String) || key.is_a?(Symbol)) && LEGACY_KEYS.include?(key.to_s)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def key?(key)
|
|
84
|
+
ListResult.legacy_key?(key)
|
|
85
|
+
end
|
|
86
|
+
alias_method :has_key?, :key?
|
|
87
|
+
|
|
88
|
+
def include?(item)
|
|
89
|
+
ListResult.legacy_key?(item) || super
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def fetch(key, *args, &block)
|
|
93
|
+
return self[key] if ListResult.legacy_key?(key)
|
|
94
|
+
|
|
95
|
+
super
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def dig(key, *rest)
|
|
99
|
+
if ListResult.legacy_key?(key)
|
|
100
|
+
value = self[key]
|
|
101
|
+
return rest.empty? || value.nil? ? value : value.dig(*rest)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
super
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def [](*args)
|
|
108
|
+
key = args.first
|
|
109
|
+
if args.length == 1 && (key.is_a?(String) || key.is_a?(Symbol))
|
|
110
|
+
case key.to_s
|
|
111
|
+
when "data" then (Legacy.warn_once("list[\"data\"]"); return self)
|
|
112
|
+
when "cursor" then (Legacy.warn_once("list[\"cursor\"]"); return @cursor)
|
|
113
|
+
when "hasMore", "has_more" then (Legacy.warn_once("list[\"hasMore\"]"); return @has_more)
|
|
114
|
+
end
|
|
115
|
+
return nil
|
|
116
|
+
end
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
data/lib/buchida/version.rb
CHANGED
data/lib/buchida.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: buchida
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- buchida
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -54,6 +54,7 @@ files:
|
|
|
54
54
|
- lib/buchida/resources/metrics.rb
|
|
55
55
|
- lib/buchida/resources/templates.rb
|
|
56
56
|
- lib/buchida/resources/webhooks.rb
|
|
57
|
+
- lib/buchida/response.rb
|
|
57
58
|
- lib/buchida/version.rb
|
|
58
59
|
homepage: https://github.com/Vyblor/buchida-ruby
|
|
59
60
|
licenses:
|