wrapi 0.4.5 → 0.4.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2879998432bd9b2be748b54c21024a68acf5cdba01ecc3040c9e9da45f02268
4
- data.tar.gz: 63b482ee658b94a605f92faa52502efe1fa24bee5a918db27c773726f4a1e326
3
+ metadata.gz: 4a4047745b71ea54dac6be7283fa0353f1e421770edf0f9940224d80bd291194
4
+ data.tar.gz: 6c8a945ec9bf4dcccfb1484b216c41e4b4582ce7ffcbfde6e47917061aee67ee
5
5
  SHA512:
6
- metadata.gz: 4913f5e123c1a2211e1c57b2b66e5712d1920ac667e38740d5047134fcc178aa82c1a509652da6f23ee16c54396025ed0959a4b95438d4026a2589b28de4d90e
7
- data.tar.gz: 0772f0cdb948a5100df2f08a0fdaf356823f1fdfa0bb658817d3a3626540c54ec29cf92a9d1d4f83b2f957b990a73dce8c20bff8a537fd6e6c226aff7f956706
6
+ metadata.gz: 7c4c12660ce8746049602aed4fbe4126dd47d4e57fa4dd3092fe831093e9f15b97293d6d1baa9dddf1f7b943ad8022db12d5f2b0f56d7c8a676cb009e6cb6141
7
+ data.tar.gz: 37e5c8beebe96f750b16d076107b77e55e84d3aeec42eefad3897a539f870e4a45d7f1d8a1ac7fdd0621351e81da03a115206ec0329dc81e9bb2c3697e8a96d9
data/CHANGELOG.md CHANGED
@@ -39,4 +39,10 @@
39
39
  - fix typo and implement clone for entities
40
40
 
41
41
  ## [0.4.5] - 2024-03-12
42
- - rafactorings code readability
42
+ - refactorings code readability
43
+
44
+ ## [0.4.6] - 2024-06-17
45
+ - fix issue with loading Entity from yaml
46
+
47
+ ## [0.4.7] - 2025-03-18
48
+ - fix obsolete escape
data/lib/wrapi/api.rb CHANGED
@@ -1,15 +1,43 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('configuration', __dir__)
2
4
  require File.expand_path('connection', __dir__)
3
5
  require File.expand_path('request', __dir__)
4
6
  require File.expand_path('authentication', __dir__)
5
7
 
6
8
  module WrAPI
7
- # @private
9
+ # The API class is responsible for managing the configuration and connections
10
+ # for the WrAPI library. It includes modules for handling connections, requests,
11
+ # and authentication.
12
+ #
13
+ # @attr_accessor [Hash] options Configuration options for the API instance.
14
+ #
15
+ # @example Creating a new API instance
16
+ # api = WrAPI::API.new(api_key: 'your_api_key')
17
+ #
18
+ # @example Accessing the configuration
19
+ # config = api.config
20
+ # puts config[:api_key]
21
+ #
22
+ # @see WrAPI::Connection
23
+ # @see WrAPI::Request
24
+ # @see WrAPI::Authentication
8
25
  class API
9
- # @private
10
26
  attr_accessor *WrAPI::Configuration::VALID_OPTIONS_KEYS
11
27
 
12
- # Creates a new API and copies settings from singleton
28
+ # Initializes a new API object with the given options.
29
+ #
30
+ # @param options [Hash] A hash of options to configure the API object.
31
+ # The options are merged with the default options from `WrAPI.options`.
32
+ #
33
+ # @option options [String] :api_key The API key for authentication.
34
+ # @option options [String] :api_secret The API secret for authentication.
35
+ # @option options [String] :endpoint The API endpoint URL.
36
+ # @option options [String] :user_agent The User-Agent header for HTTP requests.
37
+ # @option options [Integer] :timeout The timeout for HTTP requests.
38
+ # @option options [Integer] :open_timeout The open timeout for HTTP requests.
39
+ #
40
+ # @return [WrAPI::API] A new API object configured with the given options.
13
41
  def initialize(options = {})
14
42
  options = WrAPI.options.merge(options)
15
43
  WrAPI::Configuration::VALID_OPTIONS_KEYS.each do |key|
@@ -17,6 +45,11 @@ module WrAPI
17
45
  end
18
46
  end
19
47
 
48
+ # Returns a hash of configuration options and their values.
49
+ # Iterates over each valid configuration key defined in WrAPI::Configuration::VALID_OPTIONS_KEYS,
50
+ # and assigns the corresponding value by calling the method with the same name as the key.
51
+ #
52
+ # @return [Hash] A hash containing the configuration options and their values.
20
53
  def config
21
54
  conf = {}
22
55
  WrAPI::Configuration::VALID_OPTIONS_KEYS.each do |key|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WrAPI
2
4
  # Deals with authentication flow and stores it within global configuration
3
5
  # following attributes should be available:
@@ -7,9 +9,13 @@ module WrAPI
7
9
  # token_type
8
10
  # refresh_token
9
11
  # token_expires
10
-
11
12
  module Authentication
12
- # Authorize to the portal and return access_token
13
+ # Authenticates the API request by merging the provided options with the API access token parameters,
14
+ # sending a POST request to the specified path, and processing the response to extract the access token.
15
+ #
16
+ # @param path [String] the API endpoint path to which the authentication request is sent.
17
+ # @param options [Hash] additional parameters to be merged with the API access token parameters.
18
+ # @return [String] the processed access token extracted from the response body.
13
19
  def api_auth(path, options = {})
14
20
  params = api_access_token_params.merge(options)
15
21
  response = post(path, params)
@@ -17,7 +23,11 @@ module WrAPI
17
23
  api_process_token(response.body)
18
24
  end
19
25
 
20
- # Return an access token from authorization
26
+ # Refreshes the API token by making a POST request to the specified path with the given refresh token.
27
+ #
28
+ # @param path [String] the endpoint path to send the refresh request to.
29
+ # @param token [String] the refresh token to be used for obtaining a new access token.
30
+ # @return [String] the new access token obtained from the response.
21
31
  def api_refresh(path, token)
22
32
  params = { refreshToken: token }
23
33
 
@@ -26,8 +36,14 @@ module WrAPI
26
36
  api_process_token(response.body)
27
37
  end
28
38
 
29
- private
39
+ private
30
40
 
41
+ # Returns a hash containing the API access token parameters.
42
+ # Override this when passing different parameters
43
+ #
44
+ # @return [Hash] a hash with the following keys:
45
+ # - :username [String] the username for API authentication
46
+ # - :password [String] the password for API authentication
31
47
  def api_access_token_params
32
48
  {
33
49
  username: username,
@@ -35,14 +51,24 @@ module WrAPI
35
51
  }
36
52
  end
37
53
 
54
+ # Processes the API response to extract and set the authentication tokens.
55
+ # Raises an ArgumentError if the response is nil.
56
+ # Override this when passing different parameters
57
+ #
58
+ # @param response [Hash] The response from the API containing authentication tokens.
59
+ # @return [String] The access token extracted from the response.
60
+ # @raise [ArgumentError] If the response is nil.
61
+ # @raise [StandardError] If the access token is not found or is empty.
38
62
  def api_process_token(response)
39
- at = self.access_token = response['accessToken']
63
+ raise ArgumentError.new("Response cannot be nil") if response.nil?
64
+
65
+ token = self.access_token = response['accessToken']
40
66
  self.token_type = response['tokenType']
41
67
  self.refresh_token = response['refreshToken']
42
68
  self.token_expires = response['expiresIn']
43
- raise StandardError.new 'Could not find valid accessToken; response ' + response.to_s if at.nil? || at.empty?
69
+ raise StandardError.new("Could not find valid accessToken; response #{response}") if token.to_s.empty?
44
70
 
45
- at
71
+ token
46
72
  end
47
73
  end
48
74
  end
@@ -1,8 +1,40 @@
1
- #require_relative './pagination'
2
- #require_relative './version'
1
+ # frozen_string_literal: true
3
2
 
3
+ #
4
+ # This module defines constants and methods related to the configuration of the WrAPI.
5
+ # It provides a set of default configuration options and allows these options to be overridden.
6
+ #
7
+ # Constants:
8
+ # - VALID_OPTIONS_KEYS: An array of valid keys in the options hash when configuring a WrAPI::API.
9
+ # - DEFAULT_CONNECTION_OPTIONS: Default connection options (empty hash).
10
+ # - DEFAULT_FORMAT: Default response format (:json).
11
+ # - DEFAULT_PAGE_SIZE: Default page size for paged responses (500).
12
+ # - DEFAULT_USER_AGENT: Default user agent string.
13
+ # - DEFAULT_PAGINATION: Default pagination class.
14
+ #
15
+ # Attributes:
16
+ # - access_token: Access token for authentication.
17
+ # - token_type: Type of the token.
18
+ # - refresh_token: Token used to refresh the access token.
19
+ # - token_expires: Expiration time of the token.
20
+ # - client_id: Client ID for authentication.
21
+ # - client_secret: Client secret for authentication.
22
+ # - connection_options: Options for the connection.
23
+ # - username: Username for authentication.
24
+ # - password: Password for authentication.
25
+ # - endpoint: API endpoint.
26
+ # - logger: Logger instance.
27
+ # - format: Response format.
28
+ # - page_size: Page size for paged responses.
29
+ # - user_agent: User agent string.
30
+ # - pagination_class: Pagination class.
31
+ #
32
+ # Methods:
33
+ # - self.extended(base): Sets all configuration options to their default values when the module is extended.
34
+ # - configure: Allows configuration options to be set in a block.
35
+ # - options: Creates a hash of options and their values.
36
+ # - reset: Resets all configuration options to their default values.
4
37
  module WrAPI
5
-
6
38
  # Defines constants and methods related to configuration
7
39
  # If configuration is overridden, please add following methods
8
40
  # @see [self.extended(base)] to initialize the Configuration
@@ -30,7 +62,7 @@ module WrAPI
30
62
  ].freeze
31
63
 
32
64
  # By default, don't set any connection options
33
- DEFAULT_CONNECTION_OPTIONS = {}
65
+ DEFAULT_CONNECTION_OPTIONS = {}.freeze
34
66
 
35
67
  # The response format appended to the path and sent in the 'Accept' header if none is set
36
68
  #
@@ -43,11 +75,12 @@ module WrAPI
43
75
  DEFAULT_PAGE_SIZE = 500
44
76
 
45
77
  # The user agent that will be sent to the API endpoint if none is set
46
- DEFAULT_USER_AGENT = "Ruby API wrapper #{WrAPI::VERSION}".freeze
47
-
78
+ DEFAULT_USER_AGENT = "Ruby API wrapper #{WrAPI::VERSION}"
79
+
80
+ # DEFAULT_PAGINATION is a constant that sets the default pagination strategy for WrAPI requests.
81
+ # It uses the DefaultPager class from the WrAPI::RequestPagination module.
48
82
  DEFAULT_PAGINATION = WrAPI::RequestPagination::DefaultPager
49
83
 
50
- # @private
51
84
  attr_accessor *VALID_OPTIONS_KEYS
52
85
 
53
86
  # When this module is extended, set all configuration options to their default values
@@ -1,16 +1,38 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
 
3
5
  module WrAPI
4
- # Create connection including authorization parameters with default Accept format and User-Agent
6
+ # @private
7
+ # The Connection module provides methods to establish and configure a Faraday connection.
8
+ # It includes private methods to set up options, authorization, headers, and logging for the connection.
5
9
  # By default
6
10
  # - Bearer authorization is access_token is not nil override with @setup_authorization
7
11
  # - Headers setup for client-id and client-secret when client_id and client_secret are not nil @setup_headers
8
- # @private
12
+ #
13
+ # Methods:
14
+ # - connection: Establishes a Faraday connection with the configured options, authorization, headers, and logging.
15
+ # - setup_options: Sets up the options for the Faraday connection, including headers and URL.
16
+ # - setup_authorization: Configures the authorization header for the Faraday connection.
17
+ # - setup_headers: Configures additional headers for the Faraday connection.
18
+ # - setup_logger_filtering: Sets up logging and filtering for sensitive information in the Faraday connection.
9
19
  module Connection
10
20
  private
11
21
 
22
+ # Establishes a Faraday connection with the specified options and configurations.
23
+ #
24
+ # @raise [ArgumentError] if the endpoint option is not defined.
25
+ # @return [Faraday::Connection] a configured Faraday connection.
26
+ #
27
+ # The connection is configured with the following:
28
+ # - Raises errors for HTTP responses.
29
+ # - Uses the default Faraday adapter.
30
+ # - Sets up authorization and headers.
31
+ # - Parses JSON responses.
32
+ # - Uses URL-encoded requests.
33
+ # - Optionally sets up logger filtering if a logger is provided.
12
34
  def connection
13
- raise ArgumentError, "Option for endpoint is not defined" unless endpoint
35
+ raise ArgumentError, 'Option for endpoint is not defined' unless endpoint
14
36
 
15
37
  options = setup_options
16
38
  Faraday::Connection.new(options) do |connection|
@@ -25,8 +47,16 @@ module WrAPI
25
47
  end
26
48
  end
27
49
 
28
- # callback method to setup api authorization
29
- def setup_options()
50
+ # Sets up the options for the connection. acts as a callback method to
51
+ # setup api authorization
52
+ #
53
+ # @return [Hash] A hash containing the headers and URL for the connection,
54
+ # merged with any additional connection options.
55
+ # @option options [Hash] :headers The headers for the connection, including:
56
+ # - 'Accept' [String]: The content type to accept, based on the format.
57
+ # - 'User-Agent' [String]: The user agent string.
58
+ # @option options [String] :url The endpoint URL for the connection.
59
+ def setup_options
30
60
  {
31
61
  headers: {
32
62
  'Accept': "application/#{format}; charset=utf-8",
@@ -36,26 +66,49 @@ module WrAPI
36
66
  }.merge(connection_options || {})
37
67
  end
38
68
 
39
- # callback method to setup api authorization
69
+ # Sets up the authorization header for the given connection.
70
+ # override to setup your own header for api authorization
71
+ #
72
+ # @param connection [Object] The connection object to which the authorization header will be added.
73
+ # @return [void]
74
+ # @note The authorization header will only be set if the access_token is present.
40
75
  def setup_authorization(connection)
41
76
  connection.headers['Authorization'] = "Bearer #{access_token}" if access_token
42
77
  end
43
78
 
44
- # callback method to setup api headers
79
+ # Sets up the headers for the given connection. Override to set own headers.
80
+ #
81
+ # @param connection [Object] The connection object to set headers on.
82
+ # @option connection.headers [String] 'client-id' The client ID, if available.
83
+ # @option connection.headers [String] 'client-secret' The client secret, if available.
84
+ #
85
+ # @return [void]
45
86
  def setup_headers(connection)
46
87
  connection.headers['client-id'] = client_id if client_id
47
88
  connection.headers['client-secret'] = client_secret if client_secret
48
89
  end
49
90
 
50
- # callback method to setup logger
91
+ # Sets up logger filtering for the given connection.
92
+ #
93
+ # This method configures the logger to filter sensitive information from the
94
+ # connection's response. It filters out passwords, access tokens, client secrets,
95
+ # and authorization headers from the logs.
96
+ #
97
+ # @param connection [Faraday::Connection] The connection object to configure the logger for.
98
+ # @param logger [Logger] The logger instance to use for logging the connection's responses.
99
+ #
100
+ # @example
101
+ # setup_logger_filtering(connection, logger)
102
+ #
103
+ # @note This method assumes that the connection object is a Faraday connection.
51
104
  def setup_logger_filtering(connection, logger)
52
- connection.response :logger, logger, { headers: true, bodies: true } do |l|
53
- # filter json content
54
- l.filter(/("password":")(.+?)(".*)/, '\1[REMOVED]\3')
55
- l.filter(/("[Aa]ccess_?[Tt]oken":")(.+?)(".*)/, '\1[REMOVED]\3')
56
- # filter header content
57
- l.filter(/(client[-_]secret[:=].)([^&]+)/, '\1[REMOVED]')
58
- l.filter(/(Authorization:.)([^&]+)/, '\1[REMOVED]')
105
+ connection.response :logger, logger, { headers: true, bodies: true } do |log|
106
+ # Filter sensitive information from JSON content, such as passwords and access tokens.
107
+ log.filter(/("password":")(.+?)(".*)/, '\1[REMOVED]\3')
108
+ log.filter(/("[Aa]ccess_?[Tt]oken":")(.+?)(".*)/, '\1[REMOVED]\3')
109
+ # filter sensitive header content such as client secrets and authorization headers
110
+ log.filter(/(client[-_]secret[:=].)([^&]+)/, '\1[REMOVED]')
111
+ log.filter(/(Authorization:.)([^&]+)/, '\1[REMOVED]')
59
112
  end
60
113
  end
61
114
  end
data/lib/wrapi/entity.rb CHANGED
@@ -1,45 +1,80 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
5
+ # This module defines the WrAPI namespace which is used to encapsulate all the classes and modules
6
+ # related to the WrAPI library. The WrAPI library provides functionality for interacting with APIs.
3
7
  module WrAPI
4
8
  # Defines HTTP request methods
5
9
  module Request
10
+ # Entity class to represent and manipulate API data
6
11
  class Entity
7
- attr_reader :attributes
8
-
9
- # factory method to create entity or array of entities
10
- def self.create(attributes)
11
- if attributes.is_a? Array
12
- Entity.entify(attributes)
13
- else
14
- Entity.new(attributes) if attributes
12
+ # Factory method to create an entity or array of entities
13
+ #
14
+ # @param attr [Hash, Array<Hash>] the attributes to create the entity/entities from
15
+ # @return [Entity, Array<Entity>] the created entity or array of entities
16
+ def self.create(attr)
17
+ if attr.is_a? Array
18
+ Entity.entify(attr)
19
+ elsif attr
20
+ Entity.new(attr)
15
21
  end
16
22
  end
17
23
 
18
- def initialize(attributes)
19
- case attributes
24
+ # Initializes a new Entity
25
+ #
26
+ # @param attr [Hash] the attributes to initialize the entity with
27
+ def initialize(attr)
28
+ case attr
20
29
  when Hash
21
- @attributes = attributes.clone.transform_keys(&:to_s)
30
+ @attributes = attr.clone.transform_keys(&:to_s)
22
31
  else
23
- @attributes = attributes.clone
32
+ @attributes = attr.clone
24
33
  end
25
34
  end
26
35
 
36
+ # Returns the attributes of the entity
37
+ #
38
+ # @return [Hash] the attributes of the entity
39
+ def attributes
40
+ @attributes || {}
41
+ end
42
+
43
+ # Sets the attributes of the entity
44
+ #
45
+ # @param val [Hash] the new attributes of the entity
46
+ def attributes=(val)
47
+ @attributes = val || {}
48
+ end
49
+
50
+ # Handles dynamic method calls for attribute access and assignment
51
+ #
52
+ # @param method_sym [Symbol] the method name
53
+ # @param arguments [Array] the arguments passed to the method
54
+ # @param block [Proc] an optional block
27
55
  def method_missing(method_sym, *arguments, &block)
28
56
  # assignment
57
+ method = method_sym.to_s
29
58
  assignment = method_sym[/.*(?==\z)/m]
30
59
  if assignment
31
60
  raise ArgumentError, "wrong number of arguments (given #{arguments.length}, expected 1)", caller(1) unless arguments.length == 1
32
61
 
33
62
  @attributes[assignment] = arguments[0]
34
- elsif @attributes.include? method_sym.to_s
35
- accessor(method_sym.to_s)
63
+ elsif @attributes.include? method
64
+ accessor(method)
36
65
  else
37
66
  # delegate to hash
38
67
  @attributes.send(method_sym, *arguments, &block)
39
68
  end
40
69
  end
41
70
 
71
+ # Checks if the entity responds to a method
72
+ #
73
+ # @param method_sym [Symbol] the method name
74
+ # @param include_private [Boolean] whether to include private methods
75
+ # @return [Boolean] true if the entity responds to the method, false otherwise
42
76
  def respond_to?(method_sym, include_private = false)
77
+ @attributes ||= {}
43
78
  if @attributes.include? method_sym.to_s
44
79
  true
45
80
  else
@@ -47,36 +82,61 @@ module WrAPI
47
82
  end
48
83
  end
49
84
 
50
- def to_json(options = {})
85
+ # Converts the entity to a JSON string
86
+ #
87
+ # @param options [Hash] options for JSON generation
88
+ # @return [String] the JSON representation of the entity
89
+ def to_json(_options = {})
51
90
  @attributes.to_json
52
91
  end
53
92
 
93
+ # Accesses an attribute, converting it to an Entity if it is a Hash or Array
94
+ #
95
+ # @param method [String] the attribute name
96
+ # @return [Object] the attribute value
54
97
  def accessor(method)
55
- case @attributes[method]
56
- when Hash
57
- @attributes[method] = self.class.new(@attributes[method])
58
- when Array
59
- # make deep copy
60
- @attributes[method] = Entity.entify(@attributes[method])
61
- else
62
- @attributes[method]
63
- end
98
+ attribute = @attributes[method]
99
+ case attribute
100
+ when Hash
101
+ @attributes[method] = self.class.new(attribute)
102
+ when Array
103
+ # make deep copy
104
+ @attributes[method] = Entity.entify(attribute)
105
+ else
106
+ attribute
107
+ end
64
108
  end
65
-
109
+
110
+ # Clones the entity
111
+ #
112
+ # @return [Entity] the cloned entity
66
113
  def clone
67
- c = super
68
- c.attributes = @attributes.clone
69
- c
114
+ cln = super
115
+ cln.attributes = @attributes.clone
116
+ cln
117
+ end
118
+
119
+ # Checks if two entities are equal
120
+ #
121
+ # @param other [Entity] the other entity to compare with
122
+ # @return [Boolean] true if the entities are equal, false otherwise
123
+ def ==(other)
124
+ (self.class == other.class) && (self.attributes.eql? other.attributes)
70
125
  end
126
+ alias eql? ==
71
127
 
72
- def self.entify(a)
73
- if ( a.count > 0 ) && ( a.first.is_a? Hash )
74
- a.dup.map do |item|
128
+ # Converts an array of hashes to an array of entities
129
+ #
130
+ # @param attribute [Array<Hash>] the array of hashes
131
+ # @return [Array<Entity>] the array of entities
132
+ def self.entify(attribute)
133
+ if attribute.any? && (attribute.first.is_a? Hash)
134
+ attribute.dup.map do |item|
75
135
  #item.is_a?(Hash) ? self.class.new(item) : item
76
136
  Entity.create(item)
77
137
  end
78
138
  else
79
- a
139
+ attribute
80
140
  end
81
141
  end
82
142
  end
@@ -1,39 +1,50 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'json'
3
5
 
4
6
  module WrAPI
5
- # Defines HTTP request methods
6
- # required attributes format
7
+ # Defines HTTP request methods and required attributes format for pagination.
7
8
  module RequestPagination
8
-
9
- # Defaut pages asumes all data retrieved in a single go.
9
+ # DefaultPager handles pagination by assuming all data is retrieved in a single go.
10
10
  class DefaultPager
11
-
12
- # initialize with page size
13
- def initialize(page_size=nil)
11
+ # Initializes the pager with an optional page size.
12
+ #
13
+ # @param _page_size [Integer, nil] the size of the page (not used in this implementation)
14
+ def initialize(_page_size = nil)
14
15
  @page = 0
15
16
  end
16
17
 
17
- # go to next page
18
- # @return true if nore pages
19
- def next_page!(data=nil)
18
+ # Advances to the next page.
19
+ #
20
+ # @param _data [Object, nil] the data from the current page (not used in this implementation)
21
+ # @return [Boolean] true if there are more pages, false otherwise
22
+ def next_page!(_data = nil)
20
23
  @page += 1
21
24
  more_pages?
22
25
  end
23
26
 
24
- # assume single page
27
+ # Checks if there are more pages.
28
+ #
29
+ # @return [Boolean] true if there are more pages, false otherwise
25
30
  def more_pages?
26
31
  @page < 1
27
32
  end
28
33
 
34
+ # Returns options for the current page to add to get request.
35
+ #
36
+ # @return [Hash] an empty hash as options
29
37
  def page_options
30
38
  {}
31
39
  end
32
40
 
33
- def self.data(body)
41
+ # Processes the data from the response body.
42
+ #
43
+ # @param body [Object] the response body
44
+ # @return [Object] the processed data (in this case, the body itself)
45
+ def self.data(body)
34
46
  body
35
47
  end
36
48
  end
37
-
38
49
  end
39
50
  end
data/lib/wrapi/request.rb CHANGED
@@ -1,14 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'json'
3
5
 
4
6
  module WrAPI
5
7
  # Defines HTTP request methods
6
- # required attributes format
7
8
  module Request
8
9
  CONTENT_TYPE_HDR = 'Content-Type'.freeze
9
- # Perform an HTTP GET request and return entity incase format is :json
10
- # @return if format is :json and !raw an [Entity] is returned, otherwhise the response body
11
- def get(path, options = {}, raw=false)
10
+
11
+ # Perform an HTTP GET request and return entity in case format is :json
12
+ #
13
+ # @param path [String] the request path
14
+ # @param options [Hash] the request options
15
+ # @param raw [Boolean] whether to return raw response
16
+ # @return [Entity, String] the response entity or raw response body
17
+ def get(path, options = {}, raw = false)
12
18
  response = request(:get, path, options) do |request|
13
19
  # inject headers...
14
20
  yield(request) if block_given?
@@ -16,35 +22,43 @@ module WrAPI
16
22
  entity_response(response, raw)
17
23
  end
18
24
 
19
- # Perform an HTTP GET request for paged date sets response
20
- # @return nil if block given, otherwise complete concatenated json result set
25
+ # Perform an HTTP GET request for paged data sets response
26
+ #
27
+ # @param path [String] the request path
28
+ # @param options [Hash] the request options
29
+ # @param request_labda [Proc] an optional lambda to modify the request
30
+ # @return [Array<Entity>, nil] the concatenated result set or nil if block given
21
31
  def get_paged(path, options = {}, request_labda = nil)
22
- raise ArgumentError,
23
- "Pages requests should be json formatted (given format '#{format}')" unless is_json?
24
-
25
- result = []
26
- pager = create_pager
27
- while pager.more_pages?
28
- response = request(:get, path, options.merge(pager.page_options)) do |req|
29
- # inject headers...
30
- request_labda.call(req) if request_labda
31
- end
32
- if d = pager.class.data(response.body)
33
- d = Entity.create(d)
34
- if block_given?
35
- yield(d)
36
- else
37
- result = add_data(result,d)
32
+ if is_json?
33
+ result = []
34
+ pager = create_pager
35
+ while pager.more_pages?
36
+ response = request(:get, path, options.merge(pager.page_options)) do |req|
37
+ # inject headers...
38
+ request_labda&.call(req)
39
+ end
40
+ handle_data(response.body, pager) do |d|
41
+ if block_given?
42
+ yield(d)
43
+ else
44
+ result = add_data(result, d)
45
+ end
38
46
  end
47
+ pager.next_page!(response.body)
39
48
  end
40
- pager.next_page!(response.body)
49
+ result unless block_given?
50
+ else
51
+ raise ArgumentError, "Pages requests should be json formatted (given format '#{format}')"
41
52
  end
42
- result unless block_given?
43
53
  end
44
54
 
45
55
  # Perform an HTTP POST request
46
- # @return response is returned in json if format is :json
47
- def post(path, options = {}, raw=true)
56
+ #
57
+ # @param path [String] the request path
58
+ # @param options [Hash] the request options
59
+ # @param raw [Boolean] whether to return raw response
60
+ # @return [Entity, String] the response entity or raw response body
61
+ def post(path, options = {}, raw = true)
48
62
  response = request(:post, path, options) do |request|
49
63
  yield(request) if block_given?
50
64
  end
@@ -52,8 +66,12 @@ module WrAPI
52
66
  end
53
67
 
54
68
  # Perform an HTTP PUT request
55
- # @return response is returned in json if format is :json
56
- def put(path, options = {}, raw=true)
69
+ #
70
+ # @param path [String] the request path
71
+ # @param options [Hash] the request options
72
+ # @param raw [Boolean] whether to return raw response
73
+ # @return [Entity, String] the response entity or raw response body
74
+ def put(path, options = {}, raw = true)
57
75
  response = request(:put, path, options) do |request|
58
76
  yield(request) if block_given?
59
77
  end
@@ -61,44 +79,66 @@ module WrAPI
61
79
  end
62
80
 
63
81
  # Perform an HTTP DELETE request
64
- # @return response is returened
65
- def delete(path, options = {}, raw=false)
82
+ #
83
+ # @param path [String] the request path
84
+ # @param options [Hash] the request options
85
+ # @param raw [Boolean] whether to return raw response
86
+ # @return [Entity, String] the response entity or raw response body
87
+ def delete(path, options = {}, raw = false)
66
88
  response = request(:delete, path, options) do |request|
67
89
  yield(request) if block_given?
68
90
  end
69
91
  entity_response(response, raw)
70
92
  end
71
93
 
94
+ # Checks if the response format is JSON
95
+ #
96
+ # @return [Boolean] true if the format is JSON, false otherwise
72
97
  def is_json?
73
98
  format && 'json'.eql?(format.to_s)
74
99
  end
75
100
 
76
- private
101
+ private
77
102
 
103
+ # Creates a pager for paginated requests
104
+ #
105
+ # @return [Object] the pager instance
78
106
  def create_pager
79
107
  pagination_class ? pagination_class.new(page_size) : WrAPI::RequestPagination::DefaultPager
80
108
  end
81
109
 
82
110
  # Perform an HTTP request
111
+ #
112
+ # @param method [Symbol] the HTTP method
113
+ # @param path [String] the request path
114
+ # @param options [Hash] the request options
115
+ # @yieldparam request [Object] the request object
116
+ # @return [Object] the response object
83
117
  def request(method, path, options)
84
118
  response = connection.send(method) do |request|
85
- yield(request) if block_given?
119
+ if block_given?
120
+ yield(request)
121
+ end
86
122
  request.headers[CONTENT_TYPE_HDR] = "application/#{format}" unless request.headers[CONTENT_TYPE_HDR]
87
- uri = URI::Parser.new
88
- _path = uri.parse(path)
89
- _path.path = uri.escape(_path.path)
123
+
124
+ _path = escape_path(path)
90
125
  case method
91
126
  when :get, :delete
92
127
  request.url(_path.to_s, options)
93
128
  when :post, :put
94
129
  request.path = _path.to_s
95
- set_body(request,options)
130
+ set_body(request, options)
96
131
  end
97
132
  end
98
133
  response
99
134
  end
100
135
 
101
- def entity_response(response, raw=false)
136
+ # Processes the response and returns an entity if format is JSON
137
+ #
138
+ # @param response [Object] the response object
139
+ # @param raw [Boolean] whether to return raw response
140
+ # @return [Entity, Object] the response entity or raw response
141
+ def entity_response(response, raw = false)
102
142
  if is_json? && !raw
103
143
  Entity.create(pagination_class.data(response.body))
104
144
  else
@@ -106,8 +146,11 @@ module WrAPI
106
146
  end
107
147
  end
108
148
 
109
- # set post body depending json content-type
110
- def set_body(request,options)
149
+ # Sets the request body depending on the content type
150
+ #
151
+ # @param request [Object] the request object
152
+ # @param options [Hash] the request options
153
+ def set_body(request, options)
111
154
  if is_json? && !options.empty?
112
155
  request.body = options.to_json
113
156
  else
@@ -115,13 +158,40 @@ module WrAPI
115
158
  end
116
159
  end
117
160
 
118
- # add data to array and check if data itself is an array
119
- def add_data(result,data)
161
+ # Handles the data in the response body
162
+ #
163
+ # @param body [String] the response body
164
+ # @param pager [Object] the pager instance
165
+ # @yieldparam data [Object] the data in the response body
166
+ def handle_data(body, pager)
167
+ if d = pager.class.data(body)
168
+ d = Entity.create(d)
169
+ yield(d) if block_given?
170
+ end
171
+ end
172
+
173
+ # Adds data to the result array and checks if data itself is an array
174
+ #
175
+ # @param result [Array] the result array
176
+ # @param data [Object] the data to add
177
+ # @return [Array] the updated result array
178
+ def add_data(result, data)
120
179
  if data.is_a? Array
121
180
  result += data
122
181
  else
123
182
  result << data
124
183
  end
125
184
  end
185
+
186
+ # Escapes the request path
187
+ #
188
+ # @param path [String] the request path
189
+ # @return [URI::Generic] the escaped path
190
+ def escape_path(path)
191
+ uri = URI::Parser.new
192
+ _path = uri.parse(path)
193
+ _path.path = URI::RFC2396_PARSER.escape(_path.path)
194
+ _path
195
+ end
126
196
  end
127
197
  end
@@ -1,14 +1,24 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module WrAPI
4
+ # Module to delegate methods to the Client
3
5
  module RespondTo
4
-
5
- # Delegate to Client
6
+ # Delegate method calls to the Client
7
+ #
8
+ # @param method [Symbol] the method name
9
+ # @param args [Array] the arguments passed to the method
10
+ # @param block [Proc] an optional block
6
11
  def self.method_missing(method, *args, &block)
7
12
  return super unless client.respond_to?(method)
13
+
8
14
  client.send(method, *args, &block)
9
15
  end
10
16
 
11
- # Delegate to Client
17
+ # Checks if the Client responds to a method
18
+ #
19
+ # @param method [Symbol] the method name
20
+ # @param include_all [Boolean] whether to include private methods
21
+ # @return [Boolean] true if the Client responds to the method, false otherwise
12
22
  def self.respond_to?(method, include_all = false)
13
23
  client.respond_to?(method, include_all) || super
14
24
  end
data/lib/wrapi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WrAPI
4
- VERSION = '0.4.5'
4
+ VERSION = '0.4.7'
5
5
  end
data/lib/wrapi.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('wrapi/version', __dir__)
2
4
  require File.expand_path('wrapi/pagination', __dir__)
3
5
  require File.expand_path('wrapi/configuration', __dir__)
@@ -8,6 +10,13 @@ require File.expand_path('wrapi/request', __dir__)
8
10
  require File.expand_path('wrapi/respond_to', __dir__)
9
11
  require File.expand_path('wrapi/authentication', __dir__)
10
12
 
13
+ # WrAPI module provides a structure for creating API wrappers.
14
+ # It extends RespondTo and Configuration modules to include their functionalities.
15
+ #
16
+ # Methods:
17
+ # - self.client(_options = {}): Abstract method that should be overridden in the including class.
18
+ # Raises NotImplementedError if not implemented.
19
+ # - self.reset: Resets the configuration to defaults and sets the user agent string.
11
20
  module WrAPI
12
21
  extend RespondTo
13
22
  extend Configuration
@@ -15,13 +24,13 @@ module WrAPI
15
24
  # Abstract method should be overridden
16
25
  #
17
26
  # @return client
18
- def self.client(options = {})
27
+ def self.client(_options = {})
19
28
  raise NotImplementedError, 'Abstract method self.client must implemented when including ResponTo'
20
29
  end
21
30
 
22
31
  # set/override defaults
23
32
  def self.reset
24
33
  super
25
- self.user_agent = "Ruby API wrapper #{WrAPI::VERSION}".freeze
34
+ self.user_agent = "Ruby API wrapper #{WrAPI::VERSION}"
26
35
  end
27
36
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wrapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janco Tanis
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-03-18 00:00:00.000000000 Z
10
+ date: 2025-03-18 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: faraday
@@ -80,7 +79,6 @@ dependencies:
80
79
  - - ">="
81
80
  - !ruby/object:Gem::Version
82
81
  version: '0'
83
- description:
84
82
  email: gems@jancology.com
85
83
  executables: []
86
84
  extensions: []
@@ -109,7 +107,6 @@ licenses:
109
107
  metadata:
110
108
  homepage_uri: https://rubygems.org/gems/wrapi
111
109
  source_code_uri: https://github.com/jancotanis/wrapi
112
- post_install_message:
113
110
  rdoc_options: []
114
111
  require_paths:
115
112
  - lib
@@ -124,8 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
121
  - !ruby/object:Gem::Version
125
122
  version: '0'
126
123
  requirements: []
127
- rubygems_version: 3.2.3
128
- signing_key:
124
+ rubygems_version: 3.6.2
129
125
  specification_version: 4
130
126
  summary: A Ruby api wrapper code extracted from real world api clients
131
127
  test_files: []