wrapi 0.4.6 → 0.4.8

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: 5b7bed56656363a708f42ca25752e0d7235e9172e479a929e2f0c42674f42197
4
- data.tar.gz: 0d0ea9163649d1da64a89c37c548dbb657a98f74fd0da8e3eb871c6994afe8f7
3
+ metadata.gz: f311f0c8d5a16deead39d219d0d266202798df6cfb4d0b23cabfabd62d1cd9ec
4
+ data.tar.gz: c9a7bba391164cad77f2e976ec24f7b9016e0840857a416886c81987c26015b3
5
5
  SHA512:
6
- metadata.gz: 81cc81edf7e4e9cf2d6b0c837e599332dd717d0914b87aba76ce56da736cdd588a43b863dcf9196e7eec8c86fbfb1df5e5d6586292a5f58c619487f8b7952bff
7
- data.tar.gz: d1e12b22efcaf3ba181dd62407f9acf4e15e2f45f7c03848d8c076763fdd94ad9904f3b3751bd5491a00a820e0bec8ffd53bef60e910e4f541b4df9a04ed1be3
6
+ metadata.gz: 934bfa4e242147dcad243f8bfd6ce3c3389bea2e55d85f9444aa8c082c20b103da16fd23ff9afcad655832de37c8271ead765433e7b092669247e844a5603ba7
7
+ data.tar.gz: 1395f62ad20197b83a1a4f6159de38614131e3d3064229a47b77a3776c0ff251786b27b0c5978d7823ce40c2089e695b1938ca0e50bb7efff4ba4197a47e6100
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ## [Unreleased]
1
+ ## Changelog
2
2
 
3
3
  ## [0.1.0] - 2024-02-2
4
4
  - Initial release extracted from CloudAlly gem
@@ -43,3 +43,9 @@
43
43
 
44
44
  ## [0.4.6] - 2024-06-17
45
45
  - fix issue with loading Entity from yaml
46
+
47
+ ## [0.4.7] - 2025-03-18
48
+ - fix obsolete escape
49
+
50
+ ## [0.4.8] - 2025-03-20
51
+ - scramble passwords in www encoded content
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,50 @@ 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(/([&?]password=)[^&]*/, '\1[REMOVED]')
109
+ log.filter(/("[Aa]ccess_?[Tt]oken":")(.+?)(".*)/, '\1[REMOVED]\3')
110
+ # filter sensitive header content such as client secrets and authorization headers
111
+ log.filter(/(client[-_]secret[:=].)([^&]+)/, '\1[REMOVED]')
112
+ log.filter(/(Authorization:.)([^&]+)/, '\1[REMOVED]')
59
113
  end
60
114
  end
61
115
  end
data/lib/wrapi/entity.rb CHANGED
@@ -1,18 +1,29 @@
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
- # factory method to create entity or array of entities
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
8
16
  def self.create(attr)
9
17
  if attr.is_a? Array
10
18
  Entity.entify(attr)
11
- else
12
- Entity.new(attr) if attr
19
+ elsif attr
20
+ Entity.new(attr)
13
21
  end
14
22
  end
15
23
 
24
+ # Initializes a new Entity
25
+ #
26
+ # @param attr [Hash] the attributes to initialize the entity with
16
27
  def initialize(attr)
17
28
  case attr
18
29
  when Hash
@@ -21,30 +32,47 @@ module WrAPI
21
32
  @attributes = attr.clone
22
33
  end
23
34
  end
24
-
35
+
36
+ # Returns the attributes of the entity
37
+ #
38
+ # @return [Hash] the attributes of the entity
25
39
  def attributes
26
40
  @attributes || {}
27
41
  end
28
42
 
29
- def attributes= val
43
+ # Sets the attributes of the entity
44
+ #
45
+ # @param val [Hash] the new attributes of the entity
46
+ def attributes=(val)
30
47
  @attributes = val || {}
31
48
  end
32
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
33
55
  def method_missing(method_sym, *arguments, &block)
34
56
  # assignment
57
+ method = method_sym.to_s
35
58
  assignment = method_sym[/.*(?==\z)/m]
36
59
  if assignment
37
60
  raise ArgumentError, "wrong number of arguments (given #{arguments.length}, expected 1)", caller(1) unless arguments.length == 1
38
61
 
39
62
  @attributes[assignment] = arguments[0]
40
- elsif @attributes.include? method_sym.to_s
41
- accessor(method_sym.to_s)
63
+ elsif @attributes.include? method
64
+ accessor(method)
42
65
  else
43
66
  # delegate to hash
44
67
  @attributes.send(method_sym, *arguments, &block)
45
68
  end
46
69
  end
47
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
48
76
  def respond_to?(method_sym, include_private = false)
49
77
  @attributes ||= {}
50
78
  if @attributes.include? method_sym.to_s
@@ -54,41 +82,61 @@ module WrAPI
54
82
  end
55
83
  end
56
84
 
57
- 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 = {})
58
90
  @attributes.to_json
59
91
  end
60
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
61
97
  def accessor(method)
62
- case @attributes[method]
98
+ attribute = @attributes[method]
99
+ case attribute
63
100
  when Hash
64
- @attributes[method] = self.class.new(@attributes[method])
101
+ @attributes[method] = self.class.new(attribute)
65
102
  when Array
66
103
  # make deep copy
67
- @attributes[method] = Entity.entify(@attributes[method])
104
+ @attributes[method] = Entity.entify(attribute)
68
105
  else
69
- @attributes[method]
106
+ attribute
70
107
  end
71
108
  end
72
-
109
+
110
+ # Clones the entity
111
+ #
112
+ # @return [Entity] the cloned entity
73
113
  def clone
74
- c = super
75
- c.attributes = @attributes.clone
76
- c
114
+ cln = super
115
+ cln.attributes = @attributes.clone
116
+ cln
77
117
  end
78
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
79
123
  def ==(other)
80
124
  (self.class == other.class) && (self.attributes.eql? other.attributes)
81
125
  end
82
126
  alias eql? ==
83
127
 
84
- def self.entify(a)
85
- if ( a.count > 0 ) && ( a.first.is_a? Hash )
86
- 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|
87
135
  #item.is_a?(Hash) ? self.class.new(item) : item
88
136
  Entity.create(item)
89
137
  end
90
138
  else
91
- a
139
+ attribute
92
140
  end
93
141
  end
94
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,34 +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
- handle_data(response.body,pager) do |d|
33
- if block_given?
34
- yield(d)
35
- else
36
- 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)
37
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
46
+ end
47
+ pager.next_page!(response.body)
38
48
  end
39
- pager.next_page!(response.body)
49
+ result unless block_given?
50
+ else
51
+ raise ArgumentError, "Pages requests should be json formatted (given format '#{format}')"
40
52
  end
41
- result unless block_given?
42
53
  end
43
54
 
44
55
  # Perform an HTTP POST request
45
- # @return response is returned in json if format is :json
46
- 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)
47
62
  response = request(:post, path, options) do |request|
48
63
  yield(request) if block_given?
49
64
  end
@@ -51,8 +66,12 @@ module WrAPI
51
66
  end
52
67
 
53
68
  # Perform an HTTP PUT request
54
- # @return response is returned in json if format is :json
55
- 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)
56
75
  response = request(:put, path, options) do |request|
57
76
  yield(request) if block_given?
58
77
  end
@@ -60,44 +79,66 @@ module WrAPI
60
79
  end
61
80
 
62
81
  # Perform an HTTP DELETE request
63
- # @return response is returened
64
- 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)
65
88
  response = request(:delete, path, options) do |request|
66
89
  yield(request) if block_given?
67
90
  end
68
91
  entity_response(response, raw)
69
92
  end
70
93
 
94
+ # Checks if the response format is JSON
95
+ #
96
+ # @return [Boolean] true if the format is JSON, false otherwise
71
97
  def is_json?
72
- format && 'json'.eql?(format.to_s)
98
+ 'json'.eql?(format&.to_s)
73
99
  end
74
100
 
75
- private
101
+ private
76
102
 
103
+ # Creates a pager for paginated requests
104
+ #
105
+ # @return [Object] the pager instance
77
106
  def create_pager
78
107
  pagination_class ? pagination_class.new(page_size) : WrAPI::RequestPagination::DefaultPager
79
108
  end
80
109
 
81
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
82
117
  def request(method, path, options)
83
118
  response = connection.send(method) do |request|
84
- yield(request) if block_given?
119
+ if block_given?
120
+ yield(request)
121
+ end
85
122
  request.headers[CONTENT_TYPE_HDR] = "application/#{format}" unless request.headers[CONTENT_TYPE_HDR]
86
- uri = URI::Parser.new
87
- _path = uri.parse(path)
88
- _path.path = uri.escape(_path.path)
123
+
124
+ _path = escape_path(path)
89
125
  case method
90
126
  when :get, :delete
91
127
  request.url(_path.to_s, options)
92
128
  when :post, :put
93
129
  request.path = _path.to_s
94
- set_body(request,options)
130
+ set_body(request, options)
95
131
  end
96
132
  end
97
133
  response
98
134
  end
99
135
 
100
- 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)
101
142
  if is_json? && !raw
102
143
  Entity.create(pagination_class.data(response.body))
103
144
  else
@@ -105,27 +146,52 @@ module WrAPI
105
146
  end
106
147
  end
107
148
 
108
- # set post body depending json content-type
109
- 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)
110
154
  if is_json? && !options.empty?
111
155
  request.body = options.to_json
112
156
  else
113
157
  request.body = URI.encode_www_form(options) unless options.empty?
114
158
  end
115
159
  end
116
- def handle_data(body,pager)
160
+
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)
117
167
  if d = pager.class.data(body)
118
168
  d = Entity.create(d)
119
169
  yield(d) if block_given?
120
170
  end
121
171
  end
122
- # add data to array and check if data itself is an array
123
- def add_data(result,data)
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)
124
179
  if data.is_a? Array
125
180
  result += data
126
181
  else
127
182
  result << data
128
183
  end
129
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
130
196
  end
131
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.6'
4
+ VERSION = '0.4.8'
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.6
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janco Tanis
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-07-17 00:00:00.000000000 Z
10
+ date: 2025-03-20 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: []