timely-app 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6e93ac9511c215489f329d2a464a85ee094ddadb88b41710298fd6e7aeca1d48
4
+ data.tar.gz: '0888c32a76cfabc24b32a74c5745f5fdc0252b2a9e28d395cadc6888eb52b1c9'
5
+ SHA512:
6
+ metadata.gz: 765f0d5cd8a1bdbdbb84b4d22cc60702d61547e4de445d13ac76d1b642cca88a82d9478e83566a75c1ba14bd021c8bc717fb4e5042b1c734480f3199da37b98f
7
+ data.tar.gz: 8003b4a414f1b39a828fdfa3434d50a6f803bdc9c0a181ed4a544e131c44131ff3bc9836508c522d776fd2c767105e87dc8ff520d968a1af5862efd00c32dd3a
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # 1.0.0
2
+
3
+ * Initial version
data/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 amkisko
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,76 @@
1
+ # timely-app
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/timely-app.svg)](https://badge.fury.io/rb/timely-app) [![Test Status](https://github.com/amkisko/timely-app/actions/workflows/test.yml/badge.svg)](https://github.com/amkisko/timely-app/actions/workflows/test.yml)
4
+
5
+ Ruby client for the [Timely API](https://dev.timelyapp.com).
6
+
7
+ ## Install
8
+
9
+ Using Bundler:
10
+ ```sh
11
+ bundle add timely-app
12
+ ```
13
+
14
+ Using RubyGems:
15
+ ```sh
16
+ gem install timely-app
17
+ ```
18
+
19
+ ## Getting started
20
+
21
+ Implement link to Timely OAuth authorization page:
22
+
23
+ ```ruby
24
+ <%= link_to "Sign in with Timely", TimelyApp::Client.new.get_oauth_authorize_url(client_id: ENV.fetch("TIMELY_CLIENT_ID"), redirect_uri: ENV.fetch("TIMELY_REDIRECT_URI")) %>
25
+ ```
26
+
27
+ Implement callback action to get access token:
28
+
29
+ ```ruby
30
+ def timely_auth_callback
31
+ skip_verify_authorized!
32
+
33
+ client = TimelyApp::Client.new
34
+ token = client.post_oauth_token(client_id: ENV.fetch("TIMELY_CLIENT_ID"), client_secret: ENV.fetch("TIMELY_CLIENT_SECRET"), code: params["code"], redirect_uri: ENV.fetch("TIMELY_REDIRECT_URI"), grant_type: "authorization_code")
35
+
36
+ if token["access_token"].present?
37
+ client.access_token = token["access_token"]
38
+ timely_user = client.get_current_user
39
+
40
+ user = User.find_or_create_by(email: timely_user["email"])
41
+ user.update!(timely_id: timely_user["id"], timely_access_token: token["access_token"], timely_refresh_token: token["refresh_token"])
42
+
43
+ sign_in(user)
44
+
45
+ redirect_to "/authorized"
46
+ else
47
+ redirect_to "/not-authorized"
48
+ end
49
+ rescue TimelyApp::Error => _e
50
+ redirect_to "/not-authorized"
51
+ end
52
+ ```
53
+
54
+ Use client:
55
+
56
+ ```ruby
57
+ timely = TimelyApp::Client.new(access_token: <USER_TOKEN_AFTER_OAUTH>, account_id: <ACCOUNT_ID>)
58
+
59
+ timely.get_projects.each do |project|
60
+ puts project.name
61
+ end
62
+ ```
63
+
64
+ ## How to test callbacks
65
+
66
+ You can use [localhost.run](https://localhost.run/) to test callbacks locally.
67
+
68
+ There are large list of available tools for tunneling: [awesome-tunneling](https://github.com/anderspitman/awesome-tunneling)
69
+
70
+ ## Contributing
71
+
72
+ Bug reports and pull requests are welcome on GitHub at https://github.com/amkisko/timely-app
73
+
74
+ ## License
75
+
76
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#accounts
4
+ module TimelyApp
5
+ class Client
6
+ def get_accounts
7
+ get('/1.1/accounts')
8
+ end
9
+
10
+ def get_account_activities(account_id, **params)
11
+ get("/1.1/#{account_id}/activities", params)
12
+ end
13
+
14
+ def get_account(id)
15
+ get("/1.1/accounts/#{id}")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#authentication
4
+ module TimelyApp
5
+ class Client
6
+ def get_oauth_authorize_url(client_id:, redirect_uri:)
7
+ host_uri_join(
8
+ "/1.1/oauth/authorize",
9
+ response_type: 'code',
10
+ redirect_uri: redirect_uri,
11
+ client_id: client_id
12
+ )
13
+ end
14
+
15
+ def post_oauth_token(client_id:, client_secret:, code:, redirect_uri:, grant_type: "authorization_code")
16
+ post("/1.1/oauth/token", body: {
17
+ redirect_uri: redirect_uri,
18
+ code: code,
19
+ client_id: client_id,
20
+ client_secret: client_secret,
21
+ grant_type: grant_type
22
+ }, params: {})
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#clients
4
+ module TimelyApp
5
+ class Client
6
+ def create_client(name:, **params)
7
+ post("/1.1/#{account_id}/clients", client: params.merge(name: name))
8
+ end
9
+
10
+ def get_clients(**params)
11
+ get('/1.1/accounts', params)
12
+ end
13
+
14
+ def get_client(id)
15
+ get("/1.1/#{account_id}/clients/#{id}")
16
+ end
17
+
18
+ def update_client(id, name:, **params)
19
+ put("/1.1/#{account_id}/clients/#{id}", client: params.merge(name: name))
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#events
4
+ module TimelyApp
5
+ class Client
6
+ def create_event(day:, hours:, minutes:, **params)
7
+ post("/1.1/#{account_id}/events", event: params.merge(day: day, hours: hours, minutes: minutes))
8
+ end
9
+
10
+ def create_project_event(project_id:, day:, hours:, minutes:, **params)
11
+ post("/1.1/#{account_id}/projects/#{project_id}/events", event: params.merge(day: day, hours: hours, minutes: minutes))
12
+ end
13
+
14
+ def create_user_event(user_id:, day:, hours:, minutes:, **params)
15
+ post("/1.1/#{account_id}/users/#{user_id}/events", event: params.merge(day: day, hours: hours, minutes: minutes))
16
+ end
17
+
18
+ def create_bulk_events(create)
19
+ post("/1.1/#{account_id}/bulk/events", create: create)
20
+ end
21
+
22
+ def delete_event(id)
23
+ delete("/1.1/#{account_id}/events/#{id}")
24
+ end
25
+
26
+ def delete_bulk_events(delete)
27
+ post("/1.1/#{account_id}/bulk/events", delete: delete)
28
+ end
29
+
30
+ def get_events(**params)
31
+ get("/1.1/#{account_id}/events", params)
32
+ end
33
+
34
+ def get_project_events(project_id:, **params)
35
+ get("/1.1/#{account_id}/projects/#{project_id}/events", params)
36
+ end
37
+
38
+ def get_user_events(user_id:, **params)
39
+ get("/1.1/#{account_id}/users/#{user_id}/events", params)
40
+ end
41
+
42
+ def update_user_event(id, user_id:, day:, hours:, minutes:, **params)
43
+ put("/1.1/#{account_id}/users/#{user_id}/events/#{id}", event: params.merge(day: day, hours: hours, minutes: minutes))
44
+ end
45
+
46
+ def update_project_event(id, project_id:, day:, hours:, minutes:, **params)
47
+ put("/1.1/#{account_id}/projects/#{project_id}/events/#{id}", event: params.merge(day: day, hours: hours, minutes: minutes))
48
+ end
49
+
50
+ def get_event(id)
51
+ get("/1.1/#{account_id}/events/#{id}")
52
+ end
53
+
54
+ def start_event_timer(id)
55
+ put("/1.1/#{account_id}/events/#{id}/start")
56
+ end
57
+
58
+ def stop_event_timer(id)
59
+ put("/1.1/#{account_id}/events/#{id}/stop")
60
+ end
61
+
62
+ def update_event(id, day:, hours:, minutes:, **params)
63
+ put("/1.1/#{account_id}/events/#{id}", event: params.merge(day: day, hours: hours, minutes: minutes))
64
+ end
65
+
66
+ def update_bulk_events(update)
67
+ post("/1.1/#{account_id}/bulk/events", update: update)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#forecasts
4
+ module TimelyApp
5
+ class Client
6
+ def create_forecast(project_id:, **params)
7
+ post("/1.1/#{account_id}/forecasts", forecast: params.merge(project_id: project_id))
8
+ end
9
+
10
+ def delete_forecast(id)
11
+ delete("/1.1/#{account_id}/forecasts/#{id}")
12
+ end
13
+
14
+ def get_forecasts(**params)
15
+ get("/1.1/#{account_id}/forecasts", params)
16
+ end
17
+
18
+ def update_forecast(id, project_id:, estimated_minutes:, **params)
19
+ put("/1.1/#{account_id}/forecasts/#{id}", forecast: params.merge(project_id: project_id, estimated_minutes: estimated_minutes))
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#labels
4
+ module TimelyApp
5
+ class Client
6
+ def create_label(name:, **params)
7
+ post("/1.1/#{account_id}/labels", label: params.merge(name: name))
8
+ end
9
+
10
+ def delete_label(id)
11
+ delete("/1.1/#{account_id}/labels/#{id}")
12
+ end
13
+
14
+ def get_child_labels(parent_id)
15
+ get("/1.1/#{account_id}/labels", parent_id: parent_id)
16
+ end
17
+
18
+ def get_labels(**params)
19
+ get("/1.1/#{account_id}/labels", params)
20
+ end
21
+
22
+ def get_label(id)
23
+ get("/1.1/#{account_id}/labels/#{id}")
24
+ end
25
+
26
+ def update_label(id, name:, **params)
27
+ put("/1.1/#{account_id}/labels/#{id}", label: params.merge(name: name))
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#permissions
4
+ module TimelyApp
5
+ class Client
6
+ def get_current_user_permissions
7
+ get("/1.1/#{account_id}/users/current/permissions")
8
+ end
9
+
10
+ def get_user_permissions(user_id:)
11
+ get("/1.1/#{account_id}/users/#{user_id}/permissions")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#projects
4
+ module TimelyApp
5
+ class Client
6
+ def create_project(name:, color:, client_id:, users:, **params)
7
+ post("/1.1/#{account_id}/projects", project: params.merge(name: name, color: color, client_id: client_id, users: users))
8
+ end
9
+
10
+ def delete_project(id)
11
+ delete("/1.1/#{account_id}/projects/#{id}")
12
+ end
13
+
14
+ def get_projects(**params)
15
+ get("/1.1/#{account_id}/projects", params)
16
+ end
17
+
18
+ def get_project(id)
19
+ get("/1.1/#{account_id}/projects/#{id}")
20
+ end
21
+
22
+ def update_project(id, name:, color:, client_id:, users:, **params)
23
+ put("/1.1/#{account_id}/projects/#{id}", project: params.merge(name: name, color: color, client_id: client_id, users: users))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#reports
4
+ module TimelyApp
5
+ class Client
6
+ def get_reports(**params)
7
+ post("/1.1/#{account_id}/reports", params)
8
+ end
9
+
10
+ def get_filter_reports(**params)
11
+ post("/1.1/#{account_id}/reports/filter", params)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#roles
4
+ module TimelyApp
5
+ class Client
6
+ def get_roles
7
+ get("/1.1/#{account_id}/roles")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#teams
4
+ module TimelyApp
5
+ class Client
6
+ def create_team(name:, users:, **params)
7
+ post("/1.1/#{account_id}/teams", team: params.merge(name: name, users: users))
8
+ end
9
+
10
+ def delete_team(id)
11
+ delete("/1.1/#{account_id}/teams/#{id}")
12
+ end
13
+
14
+ def get_teams(**params)
15
+ get("/1.1/#{account_id}/teams", params)
16
+ end
17
+
18
+ def get_team(id)
19
+ get("/1.1/#{account_id}/teams/#{id}")
20
+ end
21
+
22
+ def update_team(id, name:, users:, **params)
23
+ put("/1.1/#{account_id}/teams/#{id}", team: params.merge(name: name, users: users))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#user_capacities
4
+ module TimelyApp
5
+ class Client
6
+ def get_users_capacities(**params)
7
+ get("/1.1/#{account_id}/users/capacities", params)
8
+ end
9
+
10
+ def get_user_capacities(user_id:)
11
+ get("/1.1/#{account_id}/users/#{user_id}/capacities")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#users
4
+ module TimelyApp
5
+ class Client
6
+ def create_user(name:, email:, role_id:, **params)
7
+ post("/1.1/#{account_id}/users", user: params.merge(name: name, email: email, role_id: role_id))
8
+ end
9
+
10
+ def delete_user(id)
11
+ delete("/1.1/#{account_id}/users/#{id}")
12
+ end
13
+
14
+ def get_users(**params)
15
+ get("/1.1/#{account_id}/users", params)
16
+ end
17
+
18
+ def get_user(id)
19
+ get("/1.1/#{account_id}/users/#{id}")
20
+ end
21
+
22
+ def get_current_user
23
+ get("/1.1/#{account_id}/users/current")
24
+ end
25
+
26
+ def update_user(id, name:, email:, role_id:, **params)
27
+ put("/1.1/#{account_id}/users/#{id}", user: params.merge(name: name, email: email, role_id: role_id))
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://dev.timelyapp.com/#webhooks
4
+ module TimelyApp
5
+ class Client
6
+ def create_webhook(url:, **params)
7
+ post("/1.1/#{account_id}/webhooks", webhook: params.merge(url: url))
8
+ end
9
+
10
+ def delete_webhook(id)
11
+ delete("/1.1/#{account_id}/webhooks/#{id}")
12
+ end
13
+
14
+ def get_webhooks(**params)
15
+ get("/1.1/#{account_id}/webhooks", params)
16
+ end
17
+
18
+ def get_webhook(id)
19
+ get("/1.1/#{account_id}/webhooks/#{id}")
20
+ end
21
+
22
+ def update_webhook(id, url:, **params)
23
+ put("/1.1/#{account_id}/webhooks/#{id}", webhook: params.merge(url: url))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ require 'timely-app/version'
3
+ require 'timely-app/errors'
4
+ require 'timely-app/link_header'
5
+ require 'timely-app/params'
6
+ require 'timely-app/record'
7
+ require 'timely-app/response'
8
+ require 'net/http'
9
+ require 'json'
10
+
11
+ module TimelyApp
12
+ class Client
13
+ attr_accessor :account_id
14
+
15
+ def initialize(options = {})
16
+ @auth_header, @auth_value = 'Authorization', "Bearer #{options[:access_token]}"
17
+ @user_agent = options.fetch(:user_agent) { "timely-app/#{VERSION} ruby/#{RUBY_VERSION}" }
18
+
19
+ @host = 'api.timelyapp.com'
20
+
21
+ @http = Net::HTTP.new(@host, Net::HTTP.https_default_port)
22
+ @http.use_ssl = true
23
+
24
+ @account_id = options[:account_id]
25
+ end
26
+
27
+ def get(path, params = nil)
28
+ request(Net::HTTP::Get.new(Params.join(path, params)))
29
+ end
30
+
31
+ private
32
+
33
+ def host_uri_join(path, params)
34
+ URI::join("https://#{@host}", Params.join(path, params)).to_s
35
+ end
36
+
37
+ def post(path, attributes)
38
+ request(Net::HTTP::Post.new(path), attributes)
39
+ end
40
+
41
+ def put(path, attributes = nil)
42
+ request(Net::HTTP::Put.new(path), attributes)
43
+ end
44
+
45
+ def delete(path)
46
+ request(Net::HTTP::Delete.new(path))
47
+ end
48
+
49
+ def request(http_request, body_object = nil)
50
+ http_request['User-Agent'] = @user_agent
51
+ http_request[@auth_header] = @auth_value
52
+
53
+ if body_object
54
+ http_request['Content-Type'] = 'application/json'
55
+ http_request.body = JSON.generate(body_object)
56
+ end
57
+
58
+ response = @http.request(http_request)
59
+
60
+ if response.is_a?(Net::HTTPSuccess)
61
+ Response.parse(response)
62
+ else
63
+ raise Response.error(response)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,21 @@
1
+ module TimelyApp
2
+ class Error < StandardError
3
+ attr_reader :response, :errors
4
+
5
+ def initialize(message = nil, response:, errors: nil)
6
+ @response = response
7
+ @errors = errors
8
+
9
+ super(message)
10
+ end
11
+ end
12
+
13
+ ClientError = Class.new(Error)
14
+
15
+ ServerError = Class.new(Error)
16
+
17
+ UnauthorizedError = Class.new(ClientError)
18
+
19
+ NotFound = Class.new(ClientError)
20
+ ForbiddenError = Class.new(ClientError)
21
+ end
@@ -0,0 +1,18 @@
1
+ require 'timely-app/record'
2
+ require 'uri'
3
+
4
+ module TimelyApp
5
+ module LinkHeader
6
+ extend self
7
+
8
+ REGEXP = /<([^>]+)>; rel="(\w+)"/
9
+
10
+ def parse(string)
11
+ string.scan(REGEXP).each_with_object(Record.new) do |(uri, rel), record|
12
+ record[rel.to_sym] = URI.parse(uri).request_uri
13
+ end
14
+ end
15
+ end
16
+
17
+ private_constant :LinkHeader
18
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ require 'cgi'
3
+
4
+ module TimelyApp
5
+ module Params
6
+ extend self
7
+
8
+ def join(path, params = nil)
9
+ return path if params.nil? || params.empty?
10
+
11
+ path + '?' + encode(params)
12
+ end
13
+
14
+ def encode(params)
15
+ params.map { |k, v| "#{escape(k)}=#{array_escape(v)}" }.join('&')
16
+ end
17
+
18
+ private
19
+
20
+ def array_escape(object)
21
+ Array(object).map { |value| escape(value) }.join(',')
22
+ end
23
+
24
+ def escape(component)
25
+ CGI.escape(component.to_s)
26
+ end
27
+ end
28
+
29
+ private_constant :Params
30
+ end
@@ -0,0 +1,31 @@
1
+ module TimelyApp
2
+ class Record
3
+ def initialize(attributes = {})
4
+ @attributes = attributes
5
+ end
6
+
7
+ def [](name)
8
+ @attributes[name]
9
+ end
10
+
11
+ def []=(name, value)
12
+ @attributes[name] = value
13
+ end
14
+
15
+ def method_missing(name, *args, &block)
16
+ if @attributes.has_key?(name) && args.empty? && block.nil?
17
+ return @attributes[name]
18
+ else
19
+ super name, *args, &block
20
+ end
21
+ end
22
+
23
+ def respond_to_missing?(name, include_private = false)
24
+ @attributes.has_key?(name)
25
+ end
26
+
27
+ def to_h
28
+ @attributes
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ require 'net/http'
3
+ require 'json'
4
+
5
+ module TimelyApp
6
+ module Response
7
+ extend self
8
+
9
+ def parse(response)
10
+ if response.is_a?(Net::HTTPNoContent)
11
+ return :no_content
12
+ end
13
+
14
+ if response.content_type == 'application/json'
15
+ object = JSON.parse(response.body, symbolize_names: true, object_class: Record)
16
+
17
+ if response['Link']
18
+ object.singleton_class.module_eval { attr_accessor :link }
19
+ object.link = LinkHeader.parse(response['Link'])
20
+ end
21
+
22
+ return object
23
+ end
24
+
25
+ response.body
26
+ end
27
+
28
+ def error(response)
29
+ if response.content_type == "application/json"
30
+ body = JSON.parse(response.body)
31
+ error_class(response).new(body&.dig("errors", "message"), response: response, errors: body&.dig("errors"))
32
+ else
33
+ error_class(response).new(response: response)
34
+ end
35
+ end
36
+
37
+ def error_class(object)
38
+ case object
39
+ when Net::HTTPBadRequest then TimelyApp::ClientError
40
+ when Net::HTTPUnauthorized then TimelyApp::UnauthorizedError
41
+ when Net::HTTPForbidden then TimelyApp::ForbiddenError
42
+ when Net::HTTPNotFound then TimelyApp::NotFoundError
43
+ when Net::HTTPClientError then TimelyApp::ClientError
44
+ when Net::HTTPServerError then TimelyApp::ServerError
45
+ else
46
+ TimelyApp::Error
47
+ end
48
+ end
49
+ end
50
+
51
+ private_constant :Response
52
+ end
@@ -0,0 +1,3 @@
1
+ module TimelyApp
2
+ VERSION = '1.0.0'
3
+ end
data/lib/timely-app.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'timely-app/client'
2
+ require 'timely-app/client/accounts'
3
+ require 'timely-app/client/auth'
4
+ require 'timely-app/client/clients'
5
+ require 'timely-app/client/events'
6
+ require 'timely-app/client/forecasts'
7
+ require 'timely-app/client/labels'
8
+ require 'timely-app/client/permissions'
9
+ require 'timely-app/client/projects'
10
+ require 'timely-app/client/reports'
11
+ require 'timely-app/client/roles'
12
+ require 'timely-app/client/teams'
13
+ require 'timely-app/client/user_capacities'
14
+ require 'timely-app/client/users'
15
+ require 'timely-app/client/webhooks'
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'timely-app'
3
+ s.version = '1.0.0'
4
+ s.license = 'MIT'
5
+ s.platform = Gem::Platform::RUBY
6
+ s.authors = ['Andrei Makarov']
7
+ s.email = ['andrei@kiskolabs.com']
8
+ s.homepage = 'https://github.com/amkisko/timely-app'
9
+ s.description = 'Ruby client for the Timely API'
10
+ s.summary = 'See description'
11
+ s.files = Dir.glob('lib/**/*.rb') + %w(CHANGELOG.md LICENSE.md README.md timely-app.gemspec)
12
+ s.required_ruby_version = '>= 1.9.3'
13
+ s.require_path = 'lib'
14
+ s.metadata = {
15
+ 'homepage' => 'https://github.com/amkisko/timely-app',
16
+ 'source_code_uri' => 'https://github.com/amkisko/timely-app',
17
+ 'bug_tracker_uri' => 'https://github.com/amkisko/timely-app/issues',
18
+ 'changelog_uri' => 'https://github.com/amkisko/timely-app/blob/main/CHANGES.md'
19
+ }
20
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: timely-app
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrei Makarov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-02-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby client for the Timely API
14
+ email:
15
+ - andrei@kiskolabs.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - CHANGELOG.md
21
+ - LICENSE.md
22
+ - README.md
23
+ - lib/timely-app.rb
24
+ - lib/timely-app/client.rb
25
+ - lib/timely-app/client/accounts.rb
26
+ - lib/timely-app/client/auth.rb
27
+ - lib/timely-app/client/clients.rb
28
+ - lib/timely-app/client/events.rb
29
+ - lib/timely-app/client/forecasts.rb
30
+ - lib/timely-app/client/labels.rb
31
+ - lib/timely-app/client/permissions.rb
32
+ - lib/timely-app/client/projects.rb
33
+ - lib/timely-app/client/reports.rb
34
+ - lib/timely-app/client/roles.rb
35
+ - lib/timely-app/client/teams.rb
36
+ - lib/timely-app/client/user_capacities.rb
37
+ - lib/timely-app/client/users.rb
38
+ - lib/timely-app/client/webhooks.rb
39
+ - lib/timely-app/errors.rb
40
+ - lib/timely-app/link_header.rb
41
+ - lib/timely-app/params.rb
42
+ - lib/timely-app/record.rb
43
+ - lib/timely-app/response.rb
44
+ - lib/timely-app/version.rb
45
+ - timely-app.gemspec
46
+ homepage: https://github.com/amkisko/timely-app
47
+ licenses:
48
+ - MIT
49
+ metadata:
50
+ homepage: https://github.com/amkisko/timely-app
51
+ source_code_uri: https://github.com/amkisko/timely-app
52
+ bug_tracker_uri: https://github.com/amkisko/timely-app/issues
53
+ changelog_uri: https://github.com/amkisko/timely-app/blob/main/CHANGES.md
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.9.3
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubygems_version: 3.3.3
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: See description
73
+ test_files: []