nokotime-ruby-client 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.
@@ -0,0 +1,28 @@
1
+ module Nokotime
2
+ module Authentication
3
+ AUTHENTICATION_TYPE = [
4
+ :noko_token
5
+ ].freeze
6
+
7
+ def valid_auth?(type)
8
+ AUTHENTICATION_TYPE.include? type
9
+ end
10
+
11
+ def authorize_request(request)
12
+ case auth_type
13
+ when :noko_token
14
+ request.headers["X-NokoToken"] = token
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def token
21
+ Nokotime.configuration.token
22
+ end
23
+
24
+ def auth_type
25
+ Nokotime.configuration.auth_type
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ module Nokotime
2
+ module Client
3
+ class Entries
4
+ ENDPOINT = "/v2/entries".freeze
5
+
6
+ attr_reader :params
7
+
8
+ def initialize(params = {})
9
+ @params = params
10
+ end
11
+
12
+ def all
13
+ multiple_pages.get(ENDPOINT, params: entry_params)
14
+ end
15
+
16
+ def show(id)
17
+ single_page.get("#{ENDPOINT}/#{id}")
18
+ end
19
+
20
+ private
21
+
22
+ def multiple_pages
23
+ @multiple_pages ||= Request::MultiplePages.new
24
+ end
25
+
26
+ def single_page
27
+ @single_page ||= Request::SinglePage.new
28
+ end
29
+
30
+ def entry_params
31
+ return params if validation.success?
32
+
33
+ raise Errors::InvalidParams, validation.messages
34
+ end
35
+
36
+ def validation
37
+ @validation ||= Validator::EntrySchema.validate(params)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ module Nokotime
2
+ module Client
3
+ class ProjectGroups
4
+ ENDPOINT = "/v2/project_groups".freeze
5
+
6
+ attr_reader :params
7
+
8
+ def initialize(params = {})
9
+ @params = params
10
+ end
11
+
12
+ def all
13
+ multiple_pages.get(ENDPOINT, params: project_group_params)
14
+ end
15
+
16
+ private
17
+
18
+ def multiple_pages
19
+ @multiple_pages ||= Request::MultiplePages.new
20
+ end
21
+
22
+ def project_group_params
23
+ return params if validation.success?
24
+
25
+ raise Errors::InvalidParams, validation.messages
26
+ end
27
+
28
+ def validation
29
+ @validation ||= Validator::ProjectGroupSchema.validate(params)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,41 @@
1
+ module Nokotime
2
+ module Client
3
+ class Projects
4
+ ENDPOINT = "/v2/projects".freeze
5
+
6
+ attr_reader :params
7
+
8
+ def initialize(params = {})
9
+ @params = params
10
+ end
11
+
12
+ def all
13
+ multiple_pages.get(ENDPOINT, params: project_params)
14
+ end
15
+
16
+ def show(id)
17
+ single_page.get("#{ENDPOINT}/#{id}")
18
+ end
19
+
20
+ private
21
+
22
+ def multiple_pages
23
+ @multiple_pages ||= Request::MultiplePages.new
24
+ end
25
+
26
+ def single_page
27
+ @single_page ||= Request::SinglePage.new
28
+ end
29
+
30
+ def project_params
31
+ return params if validation.success?
32
+
33
+ raise Errors::InvalidParams, validation.messages
34
+ end
35
+
36
+ def validation
37
+ @validation ||= Validator::ProjectSchema.validate(params)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ module Nokotime
2
+ module Client
3
+ class Tags
4
+ ENDPOINT = "/v2/tags".freeze
5
+
6
+ attr_reader :params
7
+
8
+ def initialize(params = {})
9
+ @params = params
10
+ end
11
+
12
+ def all
13
+ multiple_pages.get(ENDPOINT, params: tag_params)
14
+ end
15
+
16
+ private
17
+
18
+ def multiple_pages
19
+ @multiple_pages ||= Request::MultiplePages.new
20
+ end
21
+
22
+ def tag_params
23
+ return params if validation.success?
24
+
25
+ raise Errors::InvalidParams, validation.messages
26
+ end
27
+
28
+ def validation
29
+ @validation ||= Validator::TagSchema.validate(params)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,41 @@
1
+ module Nokotime
2
+ module Client
3
+ class Users
4
+ ENDPOINT = "/v2/users".freeze
5
+
6
+ attr_reader :params
7
+
8
+ def initialize(params = {})
9
+ @params = params
10
+ end
11
+
12
+ def all
13
+ multiple_pages.get(ENDPOINT, params: user_params)
14
+ end
15
+
16
+ def show(id)
17
+ single_page.get("#{ENDPOINT}/#{id}")
18
+ end
19
+
20
+ private
21
+
22
+ def multiple_pages
23
+ @multiple_pages ||= Request::MultiplePages.new
24
+ end
25
+
26
+ def single_page
27
+ @single_page ||= Request::SinglePage.new
28
+ end
29
+
30
+ def user_params
31
+ return params if validation.success?
32
+
33
+ raise Errors::InvalidParams, validation.messages
34
+ end
35
+
36
+ def validation
37
+ @validation ||= Validator::UserSchema.validate(params)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ module Nokotime
2
+ class Configuration
3
+ include Nokotime::Authentication
4
+
5
+ attr_writer :auth_type
6
+ attr_writer :max_concurrency
7
+ attr_writer :token
8
+ attr_accessor :url
9
+
10
+ DEFAULT_URL = "https://api.nokotime.com".freeze
11
+
12
+ def initialize
13
+ @auth_type = nil
14
+ @max_concurrency = nil
15
+ @token = nil
16
+ @url = DEFAULT_URL
17
+ end
18
+
19
+ def auth_type
20
+ unless valid_auth?(@auth_type)
21
+ raise(
22
+ Errors::Configuration,
23
+ "#{@auth_type} isn't valid type authentication."
24
+ )
25
+ end
26
+
27
+ @auth_type || raise(
28
+ Errors::Configuration, "Authentication type missing."
29
+ )
30
+ end
31
+
32
+ def max_concurrency
33
+ @max_concurrency || raise(
34
+ Errors::Configuration, "Max concurrency missing."
35
+ )
36
+ end
37
+
38
+ def token
39
+ @token || raise(
40
+ Errors::Configuration, "Token missing."
41
+ )
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,87 @@
1
+ module Nokotime
2
+ class Connection
3
+ include Nokotime::Authentication
4
+
5
+ # rubocop:disable Metrics/MethodLength
6
+ def get(path, params: {}, request_options: {})
7
+ response = connection.get do |request|
8
+ authorize_request(request)
9
+ set_request_options(request, request_options)
10
+ request.url path, params
11
+ end
12
+
13
+ response
14
+ rescue Faraday::ConnectionFailed => e
15
+ raise Errors::ConnectionFailed.new(e), e.message
16
+ rescue Faraday::ResourceNotFound => e
17
+ raise Errors::ResourceNotFound.new(e), e.message
18
+ rescue Faraday::ClientError => e
19
+ raise Errors::ClientError.new(e), e.message
20
+ end
21
+ # rubocop:enable Metrics/MethodLength
22
+
23
+ # rubocop:disable Metrics/AbcSize
24
+ # rubocop:disable Metrics/MethodLength
25
+ def get_in_parallel(
26
+ path,
27
+ from_page_number,
28
+ to_page_number,
29
+ params: {},
30
+ request_options: {}
31
+ )
32
+ responses = []
33
+
34
+ connection.in_parallel(manager) do
35
+ (from_page_number..to_page_number).each do |page|
36
+ merged_params = {page: page}.merge(params)
37
+
38
+ responses << get(
39
+ path, params: merged_params, request_options: request_options
40
+ )
41
+ end
42
+ end
43
+
44
+ responses
45
+ rescue Faraday::ConnectionFailed => e
46
+ raise Errors::ConnectionFailed.new(e), e.message
47
+ rescue Faraday::ResourceNotFound => e
48
+ raise Errors::ResourceNotFound.new(e), e.message
49
+ rescue Faraday::ClientError => e
50
+ raise Errors::ClientError.new(e), e.message
51
+ end
52
+ # rubocop:enable Metrics/MethodLength
53
+ # rubocop:enable Metrics/AbcSize
54
+
55
+ private
56
+
57
+ def connection
58
+ @connection ||= Faraday.new(default_options) do |connection|
59
+ connection.request :json
60
+ connection.response :json, content_type: /\bjson$/
61
+ connection.response :raise_error
62
+ connection.adapter :typhoeus
63
+ end
64
+ end
65
+
66
+ def default_options
67
+ {
68
+ url: Nokotime.configuration.url,
69
+ headers: {
70
+ user_agent: "MyNokoBot/1.0",
71
+ accept: "application/json"
72
+ }
73
+ }
74
+ end
75
+
76
+ def set_request_options(request, options)
77
+ request.options.timeout = options[:timeout]
78
+ request.options.open_timeout = options[:open_timeout]
79
+ end
80
+
81
+ def manager
82
+ @manager ||= Typhoeus::Hydra.new(
83
+ max_concurrency: Nokotime.configuration.max_concurrency
84
+ )
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,5 @@
1
+ module Nokotime
2
+ module Errors
3
+ class Configuration < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Nokotime
2
+ module Errors
3
+ class ConnectionFailed < StandardError; end
4
+ class ResourceNotFound < StandardError; end
5
+ class ClientError < StandardError; end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Nokotime
2
+ module Errors
3
+ class InvalidParams < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,67 @@
1
+ module Nokotime
2
+ class Paginator
3
+ attr_reader :raw_links
4
+
5
+ def initialize(raw_links)
6
+ @raw_links = raw_links
7
+ end
8
+
9
+ def next
10
+ find("next")&.dig(:url)
11
+ end
12
+
13
+ def prev
14
+ find("prev")&.dig(:url)
15
+ end
16
+
17
+ def first
18
+ find("first")&.dig(:url)
19
+ end
20
+
21
+ def last
22
+ find("last")&.dig(:url)
23
+ end
24
+
25
+ def total_pages
26
+ find("last")&.dig(:number_page)
27
+ end
28
+
29
+ private
30
+
31
+ def find(rel)
32
+ pages.find { |page| page[:rel] == rel }
33
+ end
34
+
35
+ def pages
36
+ return {} if raw_links.empty?
37
+
38
+ @pages ||=
39
+ raw_links.split(",").map do |link|
40
+ url, rel, number_page = split_and_clean_link(link)
41
+
42
+ {
43
+ url: "#{url.path}?#{url.query}",
44
+ rel: rel,
45
+ number_page: number_page
46
+ }
47
+ end
48
+ end
49
+
50
+ # Example of link response headers:
51
+ # "<https://api.nokotime.com/v2/users?page=2>; rel=\"last\""
52
+ #
53
+ # The first element is an URI. "Rel" means the relative position
54
+ # of the current page, in this case is last page.
55
+
56
+ def split_and_clean_link(link)
57
+ raw_url, rel = link.split(";").map(&:strip)
58
+
59
+ raw_url = raw_url.gsub(/<|>/, "")
60
+ rel = rel.gsub(/(rel=)?"/, "")
61
+ url = URI.parse(raw_url)
62
+ page = CGI.parse(url.query)["page"].first
63
+
64
+ [url, rel, page]
65
+ end
66
+ end
67
+ end