jbr 1.0.3 → 1.0.5
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 +4 -0
- data/README.md +83 -7
- data/lib/graphql/client.rb +34 -0
- data/lib/graphql/error.rb +5 -0
- data/lib/graphql/unauthorized.rb +5 -0
- data/lib/jbr/configuration.rb +5 -0
- data/lib/jbr/mock/account.rb +5 -0
- data/lib/jbr/mock/invoice.rb +15 -0
- data/lib/jbr/mock/job.rb +14 -0
- data/lib/jbr/mock/oauth.rb +19 -0
- data/lib/jbr/mock/quote.rb +10 -0
- data/lib/jbr/mock/request.rb +10 -0
- data/lib/jbr/mock/url.rb +7 -0
- data/lib/jbr/mock.rb +5 -0
- data/lib/jbr/mocking.rb +21 -0
- data/lib/jbr/oauth.rb +0 -6
- data/lib/jbr/url.rb +13 -0
- data/lib/jbr/version.rb +1 -1
- data/lib/jbr.rb +17 -0
- metadata +15 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1acfc5eb08362100da536df933e8fdbde9edb2c3857970258731087766ebc9b1
|
|
4
|
+
data.tar.gz: 101d507d0b42e8c5f4f775db7e23ebbe4842ce5df46ced706dc7e4b261c41cac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b39be9586f32d4e4729999690569fbd806c96aa095ee899e5fcb3232308ee82376bf9e45bf1627dcc7822416698258b923e4c694fa4fe2b1c35be0e6e1087bde
|
|
7
|
+
data.tar.gz: c8904ce193f0694f17793560f3d1f29c7cdab60b3f19be34b04e96cb1097d5deee6bcfa83762e49371c2d3e6f41c38671461cc2c017f76e19a63a43005e797bb
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -2,10 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## Available methods
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### Credentials
|
|
6
|
+
|
|
7
|
+
Generate the URL for Jobber users to authorize the app:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
url = Jbr.oauth_url_for redirect_uri:, state:
|
|
11
|
+
url # => 'https://api.getjobber.com/api/oauth/authorize?state=...&redirect_uri=...'
|
|
12
|
+
|
|
13
|
+
Create credentials with a code and a redirect URI:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
oauth = Jbr.create_oauth code:, redirect_uri:
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Initialize with existing credentials:
|
|
6
20
|
|
|
7
21
|
```ruby
|
|
8
|
-
oauth = Jbr
|
|
22
|
+
oauth = Jbr.oauth_for access_token:, refresh_token, expires_at:, account_id:
|
|
9
23
|
```
|
|
10
24
|
|
|
11
25
|
Access OAuth attributes:
|
|
@@ -17,6 +31,14 @@ oauth.expires_at # => 2026-05-22 14:32:53
|
|
|
17
31
|
oauth.account_id # => 'Z2lkOi8vSm9iYmV'
|
|
18
32
|
````
|
|
19
33
|
|
|
34
|
+
Revoke credentials:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
oauth.delete
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Requests
|
|
41
|
+
|
|
20
42
|
Create a Jobber request, finding or creating a Client with a matching phone number:
|
|
21
43
|
|
|
22
44
|
```ruby
|
|
@@ -26,7 +48,9 @@ request.id # => 'Z2lkOi8vSm9iYmVyL'
|
|
|
26
48
|
request.client_id # => 'MwMTU0Mg'
|
|
27
49
|
```
|
|
28
50
|
|
|
29
|
-
|
|
51
|
+
### Quotes
|
|
52
|
+
|
|
53
|
+
Fetch a quote from Jobber:
|
|
30
54
|
|
|
31
55
|
```ruby
|
|
32
56
|
quote = oauth.quotes.find 'Z2lkOi8vS'
|
|
@@ -34,7 +58,9 @@ quote.id # => 'Z2lkOi8vS'
|
|
|
34
58
|
quote.request_id # => 'Z2lkOi8vSm9iYmVyL'
|
|
35
59
|
```
|
|
36
60
|
|
|
37
|
-
|
|
61
|
+
### Jobs
|
|
62
|
+
|
|
63
|
+
Fetch a job from Jobber:
|
|
38
64
|
|
|
39
65
|
```ruby
|
|
40
66
|
job = oauth.jobs.find 'Njc5MTk5'
|
|
@@ -44,7 +70,9 @@ job.scheduled_at # => 2026-05-14 23:02:52
|
|
|
44
70
|
job.completed_at # => 2026-05-18 11:36:13
|
|
45
71
|
```
|
|
46
72
|
|
|
47
|
-
|
|
73
|
+
### Invoices
|
|
74
|
+
|
|
75
|
+
Fetch a non-draft invoice from Jobber:
|
|
48
76
|
|
|
49
77
|
```ruby
|
|
50
78
|
invoice = oauth.invoices.find 'MjU3ODA0'
|
|
@@ -55,10 +83,58 @@ invoice.issued_at # => 2026-05-22 12:12:53
|
|
|
55
83
|
invoice.completed_at # => 2026-05-22 14:32:53
|
|
56
84
|
```
|
|
57
85
|
|
|
86
|
+
## Available mocks
|
|
87
|
+
|
|
88
|
+
Use these methods to mock request to Jobber when testing an app:
|
|
58
89
|
|
|
59
|
-
|
|
90
|
+
### Credentials
|
|
91
|
+
|
|
92
|
+
Mock successfully creating and revoking credentials:
|
|
60
93
|
|
|
61
94
|
```ruby
|
|
62
|
-
|
|
95
|
+
Jbr.mock
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Mock an error when creating credentials:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
Jbr.mock.oauth_error = 'Flow rejected'
|
|
63
102
|
```
|
|
64
103
|
|
|
104
|
+
Mock a custom redirect URL:
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
Jbr.mock.oauth_url_for = 'https://example.com'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Requests
|
|
111
|
+
|
|
112
|
+
Mock successfully creating a request:
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
Jbr.mock.request = { id: 'request-01', client_id: 'client-01' }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Quotes
|
|
119
|
+
|
|
120
|
+
Mock successfully fetching a quote:
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
Jbr.mock.quote = { id: 'quote-01', request_id: 'request-01' }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Jobs
|
|
127
|
+
|
|
128
|
+
Mock successfully fetching a job:
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
Jbr.mock.job = { id: 'job-01', quote_id: 'quote-01', scheduled_at: Date.tomorrow.noon }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Invoices
|
|
135
|
+
|
|
136
|
+
Mock successfully fetching an invoice:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
Jbr.mock.invoice = { id: 'invoice-01', job_id: 'job-01', total: 19.99, issued_at: Date.yesterday.noon }
|
|
140
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'net/http'
|
|
3
|
+
|
|
4
|
+
# A minimal GraphQL client used to talk to third-party APIs.
|
|
5
|
+
module GraphQL
|
|
6
|
+
# An HTTP wrapper that posts queries to a GraphQL endpoint and returns the `data` payload.
|
|
7
|
+
class Client
|
|
8
|
+
# @param endpoint [String] the GraphQL endpoint URL.
|
|
9
|
+
# @param token [String] the bearer access token used to authorize the request.
|
|
10
|
+
# @param headers [Hash] any extra headers required by the API (e.g. a version pin).
|
|
11
|
+
def initialize(endpoint:, token:, headers: {})
|
|
12
|
+
@endpoint = URI endpoint
|
|
13
|
+
@token = token
|
|
14
|
+
@headers = headers
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param query [String] the GraphQL query string.
|
|
18
|
+
# @param variables [Hash] the variables to interpolate into the query.
|
|
19
|
+
# @return [Hash] the `data` portion of the GraphQL response.
|
|
20
|
+
def query(query, variables: {})
|
|
21
|
+
response = Net::HTTP.post @endpoint, { query:, variables: }.to_json, request_headers
|
|
22
|
+
raise Unauthorized, response.body if response.code == '401'
|
|
23
|
+
raise Error, response.body unless response.is_a? Net::HTTPSuccess
|
|
24
|
+
body = JSON.parse(response.body)
|
|
25
|
+
raise Error, body['errors'].pluck('message').join('; ') if body['errors'].present?
|
|
26
|
+
body.fetch('data')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
def request_headers
|
|
31
|
+
{ 'Authorization' => "Bearer #{@token}", 'Content-Type' => 'application/json' }.merge @headers
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Jbr
|
|
2
|
+
class Mock::Invoice < Invoice
|
|
3
|
+
def find(_)
|
|
4
|
+
@id = Jbr.mock.invoice[:id]
|
|
5
|
+
@job_id = Jbr.mock.invoice[:job_id]
|
|
6
|
+
@total = Jbr.mock.invoice[:total]
|
|
7
|
+
|
|
8
|
+
self
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def issued_at = Jbr.mock.invoice[:issued_at]
|
|
12
|
+
|
|
13
|
+
def completed_at = Jbr.mock.invoice[:completed_at]
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/jbr/mock/job.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Jbr
|
|
2
|
+
class Mock::OAuth < OAuth
|
|
3
|
+
def invoices = Mock::Invoice.new(oauth: self)
|
|
4
|
+
def jobs = Mock::Job.new(oauth: self)
|
|
5
|
+
def quotes = Mock::Quote.new(oauth: self)
|
|
6
|
+
def requests = Mock::Request.new(oauth: self)
|
|
7
|
+
def account = Mock::Account.new oauth: self
|
|
8
|
+
|
|
9
|
+
def delete; end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def self.post(_)
|
|
14
|
+
raise Error, error: Jbr.mock.oauth_error if Jbr.mock.oauth_error
|
|
15
|
+
|
|
16
|
+
{ access_token: 'mock-token', refresh_token: 'mock-token', expires_at: (Time.current + 3600) }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/jbr/mock/url.rb
ADDED
data/lib/jbr/mock.rb
ADDED
data/lib/jbr/mocking.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Jbr
|
|
2
|
+
module Mocking
|
|
3
|
+
def mock
|
|
4
|
+
@mock ||= Jbr::Mock.new
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def create_oauth(params = {})
|
|
8
|
+
(@mock ? Mock::OAuth : OAuth).create **params
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def oauth_url_for(params = {})
|
|
12
|
+
(@mock ? Mock::URL : URL).for **params
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def oauth_for(params = {})
|
|
16
|
+
(@mock ? Mock::OAuth : OAuth).new params
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
extend Mocking
|
|
21
|
+
end
|
data/lib/jbr/oauth.rb
CHANGED
|
@@ -74,11 +74,5 @@ module Jbr
|
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def headers = { 'X-JOBBER-GRAPHQL-VERSION' => '2026-04-22' }
|
|
77
|
-
|
|
78
|
-
def self.url_for(params = {})
|
|
79
|
-
uri = URI 'https://api.getjobber.com/api/oauth/authorize'
|
|
80
|
-
uri.query ||= params.merge(response_type: 'code', client_id: client_id).to_query
|
|
81
|
-
uri.to_s
|
|
82
|
-
end
|
|
83
77
|
end
|
|
84
78
|
end
|
data/lib/jbr/url.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Jbr
|
|
2
|
+
class URL
|
|
3
|
+
def self.for(params = {})
|
|
4
|
+
uri = URI 'https://api.getjobber.com/api/oauth/authorize'
|
|
5
|
+
uri.query ||= params.merge(response_type: 'code', client_id: client_id).to_query
|
|
6
|
+
uri.to_s
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def self.client_id = ENV['JOBBER_CLIENT_ID']
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/jbr/version.rb
CHANGED
data/lib/jbr.rb
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
require 'json'
|
|
4
4
|
require 'net/http'
|
|
5
5
|
|
|
6
|
+
require 'graphql/error'
|
|
7
|
+
require 'graphql/unauthorized'
|
|
8
|
+
require 'graphql/client'
|
|
9
|
+
|
|
10
|
+
require 'jbr/mock'
|
|
11
|
+
|
|
12
|
+
require 'jbr/url'
|
|
6
13
|
require 'jbr/error'
|
|
7
14
|
require 'jbr/resource'
|
|
8
15
|
require 'jbr/request'
|
|
@@ -13,3 +20,13 @@ require 'jbr/client'
|
|
|
13
20
|
require 'jbr/invoice'
|
|
14
21
|
require 'jbr/job'
|
|
15
22
|
require 'jbr/quote'
|
|
23
|
+
|
|
24
|
+
require 'jbr/mock/oauth'
|
|
25
|
+
require 'jbr/mock/quote'
|
|
26
|
+
require 'jbr/mock/job'
|
|
27
|
+
require 'jbr/mock/invoice'
|
|
28
|
+
require 'jbr/mock/request'
|
|
29
|
+
require 'jbr/mock/account'
|
|
30
|
+
require 'jbr/mock/url'
|
|
31
|
+
|
|
32
|
+
require 'jbr/mocking'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jbr
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claudio Baccigalupo
|
|
@@ -19,16 +19,30 @@ files:
|
|
|
19
19
|
- CHANGELOG.md
|
|
20
20
|
- LICENSE.txt
|
|
21
21
|
- README.md
|
|
22
|
+
- lib/graphql/client.rb
|
|
23
|
+
- lib/graphql/error.rb
|
|
24
|
+
- lib/graphql/unauthorized.rb
|
|
22
25
|
- lib/jbr.rb
|
|
23
26
|
- lib/jbr/account.rb
|
|
24
27
|
- lib/jbr/client.rb
|
|
28
|
+
- lib/jbr/configuration.rb
|
|
25
29
|
- lib/jbr/error.rb
|
|
26
30
|
- lib/jbr/invoice.rb
|
|
27
31
|
- lib/jbr/job.rb
|
|
32
|
+
- lib/jbr/mock.rb
|
|
33
|
+
- lib/jbr/mock/account.rb
|
|
34
|
+
- lib/jbr/mock/invoice.rb
|
|
35
|
+
- lib/jbr/mock/job.rb
|
|
36
|
+
- lib/jbr/mock/oauth.rb
|
|
37
|
+
- lib/jbr/mock/quote.rb
|
|
38
|
+
- lib/jbr/mock/request.rb
|
|
39
|
+
- lib/jbr/mock/url.rb
|
|
40
|
+
- lib/jbr/mocking.rb
|
|
28
41
|
- lib/jbr/oauth.rb
|
|
29
42
|
- lib/jbr/quote.rb
|
|
30
43
|
- lib/jbr/request.rb
|
|
31
44
|
- lib/jbr/resource.rb
|
|
45
|
+
- lib/jbr/url.rb
|
|
32
46
|
- lib/jbr/version.rb
|
|
33
47
|
homepage: https://github.com/HouseAccountEng/jbr
|
|
34
48
|
licenses:
|