checkhim 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: aabadc5305ed16d50ea750471f2cd2b5f6f525bc05e4333fa67ad93dfcd1e3c0
4
+ data.tar.gz: 9deb483176c12193da402711d7a410edd950fa21bec73c8add784cbdb50aeffe
5
+ SHA512:
6
+ metadata.gz: d652ce69668b2d3466aa4094d029d141ae142bcca59e0c77b2949a9bca31b28ebf6e259ab1e611ffa5f26bdda7d76ed0e839eecf6c065b44aa9b6ab940314bc3
7
+ data.tar.gz: f71982b701a023a370f8a016939a5bd356ea066eccb013717181fa1f64a010afd353a7d76fd461f260dc756854ba59ddf272fe51066b2d3b0faccdcd3b4ff627
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
+
6
+ ## [Unreleased]
7
+ - Add retry helper for transient failures
8
+ - Add logging hooks / instrumentation
9
+ - Add RuboCop CI job
10
+
11
+ ## [0.1.0] - 2025-09-16
12
+ ### Added
13
+ - Initial public release of the CheckHim Ruby SDK
14
+ - `CheckHim::Client#verify`
15
+ - Structured error classes mapped to API error codes
16
+ - `CheckHim::VerificationResult` model
17
+ - Basic RSpec test coverage (success + error mapping)
18
+ - GitHub Actions CI (Ruby 2.7 – 3.3)
19
+ - Documentation: README, contribution guidelines (in README)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CheckHim
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,120 @@
1
+ # CheckHim Ruby SDK
2
+
3
+ Official Ruby client for the [CheckHim](https://checkhim.tech) Number Verification API.
4
+
5
+ ## Key Features
6
+ - Simple, expressive API
7
+ - Robust, typed error mapping
8
+ - Lightweight (no heavy HTTP dependencies)
9
+ - Built-in timeouts and sensible defaults
10
+ - Thread-safe client (no global mutable state)
11
+
12
+ ## Installation
13
+
14
+ Add to your Gemfile:
15
+
16
+ ```ruby
17
+ gem 'checkhim'
18
+ ```
19
+
20
+ Or install directly:
21
+
22
+ ```bash
23
+ gem install checkhim
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```ruby
29
+ require 'checkhim'
30
+
31
+ client = CheckHim::Client.new('ch_test_your_api_key')
32
+
33
+ begin
34
+ result = client.verify('+5511984339000')
35
+ puts "Valid: #{result.valid?} Carrier: #{result.carrier}"
36
+ rescue CheckHim::Error => e
37
+ warn "Error: #{e.message} (#{e.code})"
38
+ end
39
+ ```
40
+
41
+ ### Successful Response
42
+ ```json
43
+ {
44
+ "carrier": "Oi",
45
+ "valid": true
46
+ }
47
+ ```
48
+
49
+ ### Error Response Format
50
+ ```json
51
+ {
52
+ "error": "verification failed: Network is forbidden (code: 6)",
53
+ "code": "REJECTED_NETWORK"
54
+ }
55
+ ```
56
+
57
+ ## Error Classes
58
+ All errors inherit from `CheckHim::Error`.
59
+
60
+ | Code | Class | Meaning |
61
+ | ---- | ----- | ------- |
62
+ | REJECTED_NETWORK | CheckHim::RejectedNetwork | Network forbidden |
63
+ | REJECTED_PREFIX_MISSING | CheckHim::RejectedPrefixMissing | Missing country/area prefix |
64
+ | REJECTED_FORMAT | CheckHim::RejectedFormat | Invalid formatting |
65
+ | REJECTED_SUBSCRIBER_ABSENT | CheckHim::RejectedSubscriberAbsent | Subscriber unreachable/absent |
66
+ | REJECTED_UNKNOWN_SUBSCRIBER | CheckHim::RejectedUnknownSubscriber | Unknown subscriber |
67
+ | REJECTED_UNDELIVERABLE | CheckHim::RejectedUndeliverable | Undeliverable route |
68
+ | UNDELIVERABLE_NOT_DELIVERED | CheckHim::UndeliverableNotDelivered | Inactive or not delivered |
69
+ | TEMPORARY_FAILURE | CheckHim::TemporaryFailure | Transient failure; retry later |
70
+ | SERVICE_UNAVAILABLE | CheckHim::ServiceUnavailable | Upstream service unavailable |
71
+
72
+ Other unexpected 4xx/5xx responses raise `CheckHim::APIError`.
73
+ Network issues raise `CheckHim::NetworkError`.
74
+
75
+ ### Handling Errors
76
+ ```ruby
77
+ begin
78
+ client.verify('+244921000111')
79
+ rescue CheckHim::RejectedNetwork => e
80
+ # handle specific code
81
+ rescue CheckHim::TemporaryFailure
82
+ sleep 2; retry
83
+ rescue CheckHim::Error => e
84
+ warn "General failure: #{e.message} (#{e.code})"
85
+ end
86
+ ```
87
+
88
+ ## Configuration Options
89
+ ```ruby
90
+ client = CheckHim::Client.new(
91
+ 'ch_live_key',
92
+ open_timeout: 3,
93
+ read_timeout: 8,
94
+ endpoint: 'https://api.checkhim.tech/api/v1'
95
+ )
96
+ ```
97
+
98
+ ## Versioning
99
+ This library follows semantic versioning: MAJOR.MINOR.PATCH.
100
+
101
+ ## Development
102
+ ```bash
103
+ git clone https://github.com/checkhim/ruby-sdk.git
104
+ cd ruby-sdk
105
+ bundle install
106
+ rake spec
107
+ ```
108
+
109
+ ## Contributing
110
+ 1. Fork the repository
111
+ 2. Create a feature branch (`git checkout -b feature/improve-thing`)
112
+ 3. Add tests for your change
113
+ 4. Ensure `rake spec` passes and add documentation
114
+ 5. Submit a pull request
115
+
116
+ ## Security
117
+ Do not open public issues for sensitive security topics. Email: opensource@checkhim.tech
118
+
119
+ ## License
120
+ Released under the MIT License. See `LICENSE` for details.
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'json'
5
+
6
+ module CheckHim
7
+ # Client for interacting with the CheckHim Verification API.
8
+ class Client
9
+ DEFAULT_ENDPOINT = 'https://api.checkhim.tech/api/v1'.freeze
10
+ VERIFY_PATH = '/verify'.freeze
11
+ DEFAULT_OPEN_TIMEOUT = 5
12
+ DEFAULT_READ_TIMEOUT = 10
13
+
14
+ attr_reader :api_key, :endpoint, :open_timeout, :read_timeout, :user_agent
15
+
16
+ def initialize(api_key, endpoint: DEFAULT_ENDPOINT, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT, user_agent: nil)
17
+ raise ArgumentError, 'api_key must be provided' if api_key.nil? || api_key.strip.empty?
18
+
19
+ @api_key = api_key
20
+ @endpoint = endpoint.chomp('/')
21
+ @open_timeout = open_timeout
22
+ @read_timeout = read_timeout
23
+ @user_agent = user_agent || default_user_agent
24
+ end
25
+
26
+ # Verifies a phone number. Returns a VerificationResult on success.
27
+ # Raises CheckHim::Error subclasses on failure.
28
+ def verify(number)
29
+ payload = { number: number, type: 'frontend' }
30
+ uri = URI.parse(@endpoint + VERIFY_PATH)
31
+ http = Net::HTTP.new(uri.host, uri.port)
32
+ http.use_ssl = uri.scheme == 'https'
33
+ http.open_timeout = @open_timeout
34
+ http.read_timeout = @read_timeout
35
+
36
+ request = Net::HTTP::Post.new(uri.request_uri)
37
+ request['Authorization'] = "Bearer #{@api_key}"
38
+ request['Content-Type'] = 'application/json'
39
+ request['Accept'] = 'application/json'
40
+ request['User-Agent'] = @user_agent
41
+ request.body = JSON.generate(payload)
42
+
43
+ response = http.request(request)
44
+ handle_response(response)
45
+ rescue Timeout::Error, Errno::ECONNREFUSED, SocketError => e
46
+ raise NetworkError.new("Network error: #{e.message}")
47
+ end
48
+
49
+ private
50
+
51
+ def handle_response(response)
52
+ body_text = response.body.to_s
53
+ json = parse_json(body_text)
54
+
55
+ if response.code.to_i >= 400
56
+ raise_api_error(json, response)
57
+ end
58
+
59
+ unless json.is_a?(Hash) && json.key?('carrier') && json.key?('valid')
60
+ raise APIError.new('Malformed API response', http_status: response.code.to_i, details: body_text)
61
+ end
62
+
63
+ VerificationResult.new(carrier: json['carrier'], valid: json['valid'])
64
+ end
65
+
66
+ def parse_json(body)
67
+ JSON.parse(body)
68
+ rescue JSON::ParserError
69
+ {}
70
+ end
71
+
72
+ def raise_api_error(json, response)
73
+ message = json['error'] || 'API request failed'
74
+ code = json['code']
75
+ klass = ERROR_CODE_CLASS_MAP[code] || APIError
76
+ raise klass.new(message, code: code, http_status: response.code.to_i, details: json)
77
+ end
78
+
79
+ def default_user_agent
80
+ "checkhim-ruby/#{CheckHim::VERSION} Ruby/#{RUBY_VERSION} (#{RUBY_PLATFORM})"
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckHim
4
+ # Base error for all CheckHim related failures.
5
+ class Error < StandardError
6
+ attr_reader :code, :http_status, :details
7
+
8
+ def initialize(message = nil, code: nil, http_status: nil, details: nil)
9
+ super(message)
10
+ @code = code
11
+ @http_status = http_status
12
+ @details = details
13
+ end
14
+ end
15
+
16
+ class NetworkError < Error; end
17
+ class APIError < Error; end
18
+
19
+ # Specific API domain errors (these map the remote 'code' field)
20
+ class RejectedNetwork < APIError; end
21
+ class RejectedPrefixMissing < APIError; end
22
+ class RejectedFormat < APIError; end
23
+ class RejectedSubscriberAbsent < APIError; end
24
+ class RejectedUnknownSubscriber < APIError; end
25
+ class RejectedUndeliverable < APIError; end
26
+ class UndeliverableNotDelivered < APIError; end
27
+ class TemporaryFailure < APIError; end
28
+ class ServiceUnavailable < APIError; end
29
+
30
+ ERROR_CODE_CLASS_MAP = {
31
+ 'REJECTED_NETWORK' => RejectedNetwork,
32
+ 'REJECTED_PREFIX_MISSING' => RejectedPrefixMissing,
33
+ 'REJECTED_FORMAT' => RejectedFormat,
34
+ 'REJECTED_SUBSCRIBER_ABSENT' => RejectedSubscriberAbsent,
35
+ 'REJECTED_UNKNOWN_SUBSCRIBER' => RejectedUnknownSubscriber,
36
+ 'REJECTED_UNDELIVERABLE' => RejectedUndeliverable,
37
+ 'UNDELIVERABLE_NOT_DELIVERED' => UndeliverableNotDelivered,
38
+ 'TEMPORARY_FAILURE' => TemporaryFailure,
39
+ 'SERVICE_UNAVAILABLE' => ServiceUnavailable
40
+ }.freeze
41
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckHim
4
+ # Represents a verification result returned by the API.
5
+ class VerificationResult
6
+ attr_reader :carrier, :valid
7
+
8
+ def initialize(carrier:, valid:)
9
+ @carrier = carrier
10
+ @valid = !!valid
11
+ end
12
+
13
+ def valid?
14
+ @valid
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckHim
4
+ VERSION = '0.1.0'
5
+ end
data/lib/checkhim.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'checkhim/version'
4
+ require_relative 'checkhim/errors'
5
+ require_relative 'checkhim/verification_result'
6
+ require_relative 'checkhim/client'
7
+
8
+ module CheckHim
9
+ # Namespace module for the CheckHim Ruby SDK.
10
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: checkhim
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - CheckHim Engineering
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-09-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: webmock
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.19'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.19'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.50'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '2.0'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '1.50'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '13.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '13.0'
89
+ description: Official, well-tested Ruby client for the CheckHim API enabling phone
90
+ number verification with robust error handling.
91
+ email:
92
+ - engineering@checkhim.tech
93
+ executables: []
94
+ extensions: []
95
+ extra_rdoc_files: []
96
+ files:
97
+ - CHANGELOG.md
98
+ - LICENSE
99
+ - README.md
100
+ - lib/checkhim.rb
101
+ - lib/checkhim/client.rb
102
+ - lib/checkhim/errors.rb
103
+ - lib/checkhim/verification_result.rb
104
+ - lib/checkhim/version.rb
105
+ homepage: https://checkhim.tech
106
+ licenses:
107
+ - MIT
108
+ metadata:
109
+ homepage_uri: https://checkhim.tech
110
+ source_code_uri: https://github.com/checkhim/ruby-sdk
111
+ changelog_uri: https://github.com/checkhim/ruby-sdk/CHANGELOG.md
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '2.7'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.4.20
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Ruby client for the CheckHim number verification API.
131
+ test_files: []