buchida 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d609f12cc9ce58b4802a97f2b0bdb1e37150472571d7bb4f7165eab82a884eba
4
+ data.tar.gz: e6db0119d1dce466a631cbb23b99629a38038e5c72d8d58d49865bccd8ec6232
5
+ SHA512:
6
+ metadata.gz: 0bf53456137333f4e788a172820ad8995beba3d1a8b1233ed20107348d3a0b055410846d80756c7259764ffebcc1616b625d15e9fe973bec93af51d0a9cfe902
7
+ data.tar.gz: 9c06e7301bcb567579664b876a626f3e13f3e0eec85a981c2d4be49d19a81bffa1b7079d130a3f1b7a2346e4f7cda94e82041160b26bcb35d04686c72d33f4d7
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module Buchida
8
+ class Client
9
+ DEFAULT_BASE_URL = "https://api.buchida.com"
10
+ DEFAULT_TIMEOUT = 30
11
+
12
+ attr_reader :emails, :domains, :api_keys, :webhooks, :templates, :metrics
13
+
14
+ def initialize(api_key, base_url: DEFAULT_BASE_URL, timeout: DEFAULT_TIMEOUT)
15
+ raise ArgumentError, "API key is required" if api_key.nil? || api_key.empty?
16
+
17
+ @api_key = api_key
18
+ @base_url = base_url.chomp("/")
19
+ @timeout = timeout
20
+
21
+ @emails = Resources::Emails.new(self)
22
+ @domains = Resources::Domains.new(self)
23
+ @api_keys = Resources::ApiKeys.new(self)
24
+ @webhooks = Resources::Webhooks.new(self)
25
+ @templates = Resources::Templates.new(self)
26
+ @metrics = Resources::Metrics.new(self)
27
+ end
28
+
29
+ def request(method, path, body = nil)
30
+ uri = URI("#{@base_url}#{path}")
31
+
32
+ req = case method
33
+ when :get then Net::HTTP::Get.new(uri)
34
+ when :post then Net::HTTP::Post.new(uri)
35
+ when :delete then Net::HTTP::Delete.new(uri)
36
+ else raise ArgumentError, "Unsupported method: #{method}"
37
+ end
38
+
39
+ req["Authorization"] = "Bearer #{@api_key}"
40
+ req["Content-Type"] = "application/json"
41
+ req["User-Agent"] = "buchida-ruby/#{VERSION}"
42
+ req.body = JSON.generate(body) if body
43
+
44
+ http = Net::HTTP.new(uri.host, uri.port)
45
+ http.use_ssl = uri.scheme == "https"
46
+ http.open_timeout = @timeout
47
+ http.read_timeout = @timeout
48
+
49
+ response = http.request(req)
50
+
51
+ unless response.is_a?(Net::HTTPSuccess) || response.code == "204"
52
+ handle_error(response)
53
+ end
54
+
55
+ return nil if response.code == "204" || response.body.nil? || response.body.empty?
56
+
57
+ JSON.parse(response.body)
58
+ end
59
+
60
+ private
61
+
62
+ def handle_error(response)
63
+ body = begin
64
+ JSON.parse(response.body)
65
+ rescue
66
+ { "message" => response.message }
67
+ end
68
+
69
+ message = body["message"] || response.message
70
+ status = response.code.to_i
71
+
72
+ case status
73
+ when 401 then raise AuthenticationError, message
74
+ when 404 then raise NotFoundError, message
75
+ when 422 then raise ValidationError, message
76
+ when 429 then raise RateLimitError, message
77
+ else raise Error.new(message, status, body["code"])
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ class Error < StandardError
5
+ attr_reader :status_code, :code
6
+
7
+ def initialize(message, status_code, code = nil)
8
+ super(message)
9
+ @status_code = status_code
10
+ @code = code
11
+ end
12
+ end
13
+
14
+ class AuthenticationError < Error
15
+ def initialize(message = "Invalid API key")
16
+ super(message, 401, "authentication_error")
17
+ end
18
+ end
19
+
20
+ class RateLimitError < Error
21
+ def initialize(message = "Rate limit exceeded")
22
+ super(message, 429, "rate_limit_error")
23
+ end
24
+ end
25
+
26
+ class NotFoundError < Error
27
+ def initialize(message = "Resource not found")
28
+ super(message, 404, "not_found")
29
+ end
30
+ end
31
+
32
+ class ValidationError < Error
33
+ def initialize(message = "Validation failed")
34
+ super(message, 422, "validation_error")
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ module Resources
5
+ class ApiKeys
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def create(name:, permission:)
11
+ @client.request(:post, "/api-keys", { name: name, permission: permission })
12
+ end
13
+
14
+ def list
15
+ @client.request(:get, "/api-keys")
16
+ end
17
+
18
+ def delete(id)
19
+ @client.request(:delete, "/api-keys/#{id}")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ module Resources
5
+ class Domains
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def create(name:)
11
+ @client.request(:post, "/domains", { name: name })
12
+ end
13
+
14
+ def list
15
+ @client.request(:get, "/domains")
16
+ end
17
+
18
+ def get(id)
19
+ @client.request(:get, "/domains/#{id}")
20
+ end
21
+
22
+ def verify(id)
23
+ @client.request(:post, "/domains/#{id}/verify")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ module Resources
5
+ class Emails
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def send(from:, to:, subject:, html: nil, text: nil, reply_to: nil, cc: nil, bcc: nil, tags: nil, scheduled_at: nil)
11
+ body = { from: from, to: to, subject: subject }
12
+ body[:html] = html if html
13
+ body[:text] = text if text
14
+ body[:replyTo] = reply_to if reply_to
15
+ body[:cc] = cc if cc
16
+ body[:bcc] = bcc if bcc
17
+ body[:tags] = tags if tags
18
+ body[:scheduledAt] = scheduled_at if scheduled_at
19
+ @client.request(:post, "/emails", body)
20
+ end
21
+
22
+ def get(id)
23
+ @client.request(:get, "/emails/#{id}")
24
+ end
25
+
26
+ def list(cursor: nil, limit: nil, status: nil, from: nil, to: nil)
27
+ params = {}
28
+ params[:cursor] = cursor if cursor
29
+ params[:limit] = limit if limit
30
+ params[:status] = status if status
31
+ params[:from] = from if from
32
+ params[:to] = to if to
33
+ qs = URI.encode_www_form(params) unless params.empty?
34
+ path = qs ? "/emails?#{qs}" : "/emails"
35
+ @client.request(:get, path)
36
+ end
37
+
38
+ def cancel(id)
39
+ @client.request(:post, "/emails/#{id}/cancel")
40
+ end
41
+
42
+ def send_batch(emails)
43
+ @client.request(:post, "/emails/batch", emails)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ module Resources
5
+ class Metrics
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def get(from:, to:, granularity: nil)
11
+ params = { from: from, to: to }
12
+ params[:granularity] = granularity if granularity
13
+ qs = URI.encode_www_form(params)
14
+ @client.request(:get, "/metrics?#{qs}")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ module Resources
5
+ class Templates
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def list
11
+ @client.request(:get, "/templates")
12
+ end
13
+
14
+ def get(id)
15
+ @client.request(:get, "/templates/#{id}")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ module Resources
5
+ class Webhooks
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def create(url:, events:)
11
+ @client.request(:post, "/webhooks", { url: url, events: events })
12
+ end
13
+
14
+ def list
15
+ @client.request(:get, "/webhooks")
16
+ end
17
+
18
+ def delete(id)
19
+ @client.request(:delete, "/webhooks/#{id}")
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Buchida
4
+ VERSION = "0.1.0"
5
+ end
data/lib/buchida.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "buchida/version"
4
+ require_relative "buchida/errors"
5
+ require_relative "buchida/client"
6
+ require_relative "buchida/resources/emails"
7
+ require_relative "buchida/resources/domains"
8
+ require_relative "buchida/resources/api_keys"
9
+ require_relative "buchida/resources/webhooks"
10
+ require_relative "buchida/resources/templates"
11
+ require_relative "buchida/resources/metrics"
12
+
13
+ module Buchida
14
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: buchida
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - buchida
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-04-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: webmock
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ description: Ruby client for the buchida email API with CJK-first template support.
42
+ email: hello@buchida.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/buchida.rb
48
+ - lib/buchida/client.rb
49
+ - lib/buchida/errors.rb
50
+ - lib/buchida/resources/api_keys.rb
51
+ - lib/buchida/resources/domains.rb
52
+ - lib/buchida/resources/emails.rb
53
+ - lib/buchida/resources/metrics.rb
54
+ - lib/buchida/resources/templates.rb
55
+ - lib/buchida/resources/webhooks.rb
56
+ - lib/buchida/version.rb
57
+ homepage: https://github.com/Vyblor/buchida-ruby
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 3.2.0
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.5.3
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Official Ruby SDK for buchida email API
80
+ test_files: []