usps-imis-api 0.11.40 → 0.11.42

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: '09b163c4f02496fa2205d3ed3056f2e0e7bf7306b63f2176390a498503ca32d3'
4
- data.tar.gz: c5e9dd8def7221e9f63f71e277ebbdbd3d6b8f080d93af5a5494b50149b649cd
3
+ metadata.gz: db2bc7a4cecec659c0b9d6c86ec8a5819f066537f35b0db089ca5f7df243c597
4
+ data.tar.gz: 7945390fbd0d073799a01e25cbfd9ffcd6a590da818055a39a7c6368a881e787
5
5
  SHA512:
6
- metadata.gz: 2cf04565727807685ef016b823bdd798ac453ed9510d32b430c4b6e286b9f71d01ee6d2d08d15bcdfc3c55dc8168e42f224c9c2fddec2e9933c4e03ee34e03ed
7
- data.tar.gz: b0a7eeb21ce375a205b1783f839eba1c02aa2040091319845729d33680e49cb43a373a256e3ac002037222516ef111bf8d08903181458c0e8a5fcc1180b30772
6
+ metadata.gz: 20eca697722eb6ef3d502afa3b87f46655feee6739eabec86580a032d28f590f29b619abdca8d25f56edcc77a7584305fe9911c73c596b5b70dd847d00fb1b96
7
+ data.tar.gz: 92676045e015b98881b8d40e5d99b9720ddae3618d3686837e6ac9ac0a5414308ba146f4a9339e64038f85c696abbc2d07f148c3a62bed14d93c9f9e7096f0b7
data/Readme.md CHANGED
@@ -86,4 +86,4 @@ file to [rubygems.org](https://rubygems.org).
86
86
  A wrapper for the CLI from this API is
87
87
  [available for PHP](https://github.com/unitedstatespowersquadrons/imis-api-php).
88
88
 
89
- You can also view the [original PHP API](https://github.com/unitedstatespowersquadrons/imis-api).
89
+ You can also view the (***deprecated***) [original PHP API](https://github.com/unitedstatespowersquadrons/imis-api).
data/lib/usps/imis/api.rb CHANGED
@@ -62,7 +62,7 @@ module Usps
62
62
  def initialize(imis_id: nil, record_id: nil)
63
63
  self.imis_id = imis_id if imis_id
64
64
  self.record_id = record_id if record_id
65
- @logger ||= Imis.logger('Api')
65
+ @logger = Imis.logger('Api')
66
66
  Imis.config.validate!
67
67
  end
68
68
 
@@ -80,10 +80,11 @@ module Usps
80
80
  hex = '[0-9a-fA-F]'
81
81
  uuid_pattern = /^#{hex}{8}-#{hex}{4}-#{hex}{4}-#{hex}{4}-#{hex}{12}$/
82
82
  @imis_id =
83
- if id.to_s.match?(uuid_pattern)
84
- id
85
- elsif id.to_i.to_s == id.to_s.gsub(' ', '')
86
- id.to_i
83
+ if id.to_s.match?(uuid_pattern) then id
84
+ elsif id.to_i.to_s == id.to_s.gsub(' ', '') then id.to_i
85
+ elsif id.nil? then nil
86
+ else
87
+ raise ArgumentError, "Invalid id: #{id.inspect}"
87
88
  end
88
89
  end
89
90
 
@@ -118,13 +119,13 @@ module Usps
118
119
 
119
120
  logger.debug "Fetching iMIS ID for #{certificate}"
120
121
 
121
- begin
122
- result = query(Imis.configuration.imis_id_query_name, { certificate: })
123
- page = result.page.tap { logger.tagged('Response').debug it }
124
- self.imis_id = page.first['ID'].to_i
125
- rescue StandardError
126
- raise Errors::NotFoundError, 'Member not found'
127
- end
122
+ result = query(Imis.configuration.imis_id_query_name, { certificate: })
123
+ page = result.page.tap { logger.tagged('Response').debug it }
124
+ raise Errors::NotFoundError, 'Member not found' if page.empty?
125
+
126
+ self.imis_id = page.first['ID'].to_i
127
+ rescue Errors::ResponseError
128
+ raise Errors::NotFoundError, 'Member not found'
128
129
  end
129
130
 
130
131
  # Run requests as DSL, with specific iMIS ID only maintained for this scope
@@ -138,6 +139,8 @@ module Usps
138
139
  # @param id [Integer, String] iMIS ID to select for requests within the block
139
140
  # @param certificate [String] Certificate number to convert to iMIS ID and select for requests within the block
140
141
  # @param record_id [Integer] Record ID to select for requests within the block
142
+ # @yield Block context to run requests with a specific iMIS ID
143
+ # @yieldparam [Api]
141
144
  #
142
145
  # @example
143
146
  # with(12345) do
@@ -175,7 +178,7 @@ module Usps
175
178
  #
176
179
  # @return [Usps::Imis::Query] Query wrapper
177
180
  #
178
- def query(query_name, query_params = nil) = Query.new(self, query_name, **query_params)
181
+ def query(query_name, query_params = {}) = Query.new(self, query_name, **query_params)
179
182
 
180
183
  # Run requests as DSL, with specific +BusinessObject+ only maintained for this scope
181
184
  #
@@ -183,6 +186,8 @@ module Usps
183
186
  #
184
187
  # @param business_object_name [String, Symbol] Name of the business object
185
188
  # @param ordinal [Integer] Ordinal to build override ID param of the URL (e.g. used for Panels)
189
+ # @yield Block context to run requests on a specific +BusinessObject+
190
+ # @yieldparam [Api]
186
191
  #
187
192
  # @return [Usps::Imis::BusinessObject]
188
193
  #
@@ -250,12 +255,27 @@ module Usps
250
255
  { token: @token, token_expiration: @token_expiration }
251
256
  end
252
257
 
258
+ # Persistent HTTP connection for reuse across requests
259
+ #
260
+ def http_connection
261
+ return @http_connection if @http_connection&.started?
262
+
263
+ hostname = URI(Imis.configuration.hostname)
264
+ @http_connection = Net::HTTP.new(hostname.host, hostname.port).tap do |http|
265
+ http.use_ssl = true
266
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
267
+ http.open_timeout = 10
268
+ http.read_timeout = 30
269
+ http.write_timeout = 30
270
+ http.keep_alive_timeout = 30
271
+ http.start
272
+ end
273
+ end
274
+
253
275
  # Ruby 3.5 instance variable filter
254
276
  #
255
277
  def instance_variables_to_inspect = %i[@token_expiration @imis_id]
256
278
 
257
- private
258
-
259
279
  # Authenticate to the iMIS API, and store the access token and expiration time
260
280
  #
261
281
  def authenticate
@@ -270,7 +290,7 @@ module Usps
270
290
  username: Imis.configuration.username,
271
291
  password: Imis.configuration.password
272
292
  )
273
- result = submit(uri, request)
293
+ result = submit(request)
274
294
  json = JSON.parse(result.body)
275
295
  end
276
296
 
@@ -278,6 +298,8 @@ module Usps
278
298
  @token_expiration = Time.now + json['expires_in'] - 60
279
299
  end
280
300
 
301
+ private
302
+
281
303
  # URI for the authentication endpoint
282
304
  #
283
305
  def uri(...) = URI(File.join(Imis.configuration.hostname, AUTHENTICATION_PATH))
@@ -7,14 +7,28 @@ module Usps
7
7
  module Imis
8
8
  # Base class for API data response wrappers
9
9
  #
10
- class BaseData < Hash
10
+ class BaseData
11
+ # The raw API response hash
12
+ #
13
+ attr_reader :raw
14
+
15
+ # Create an instance from a hash
16
+ #
17
+ def self.[](hash) = new(hash)
18
+
11
19
  # Load raw API response JSON to access properties
12
20
  #
13
21
  # @param json [String] Raw API response JSON
14
22
  #
15
- def self.from_json(json) = self[JSON.parse(json)]
23
+ def self.from_json(json) = new(JSON.parse(json))
24
+
25
+ def initialize(raw = {})
26
+ @raw = raw
27
+ end
28
+
29
+ alias to_h raw
16
30
 
17
- alias raw to_h
31
+ def to_json(*) = raw.to_json(*)
18
32
 
19
33
  # Access the iMIS ID property
20
34
  #
@@ -48,6 +62,14 @@ module Usps
48
62
  )
49
63
  end
50
64
 
65
+ def ==(other)
66
+ case other
67
+ when BaseData then raw == other.raw
68
+ when Hash then raw == other
69
+ else super
70
+ end
71
+ end
72
+
51
73
  def inspect
52
74
  stringio = StringIO.new
53
75
  PP.pp(self, stringio)
@@ -21,6 +21,8 @@ module Usps
21
21
  # Build a blank object for the current iMIS ID
22
22
  #
23
23
  # @param hash [Hash] Hash version of props to set (block takes priority)
24
+ # @yield Block context to define additional properties with +add+
25
+ # @yieldparam [Properties]
24
26
  #
25
27
  def build(hash = {}, &) = header.merge(Properties.build(parent.api.record_id.to_s, @ordinal&.to_s, hash, &))
26
28
 
@@ -37,7 +37,7 @@ module Usps
37
37
  @api = api
38
38
  @business_object_name = business_object_name.to_s
39
39
  @ordinal = ordinal
40
- @logger ||= Imis.logger('BusinessObject')
40
+ @logger = Imis.logger('BusinessObject')
41
41
  end
42
42
 
43
43
  # Run a query on the entire business object
@@ -134,16 +134,22 @@ module Usps
134
134
  #
135
135
  # @return [true] Only on success response (i.e. blank string from the API)
136
136
  #
137
- def delete = submit(uri, authorize(http_delete)).body == '' # rubocop:disable Naming/PredicateMethod
137
+ def delete = submit(authorize(http_delete)).body == '' # rubocop:disable Naming/PredicateMethod
138
138
  alias destroy delete
139
139
 
140
140
  # Build a blank object for the current iMIS ID
141
141
  #
142
+ # @param hash [Hash] Hash version of props to set (block takes priority)
143
+ # @yield Block context to define additional properties with +add+
144
+ # @yieldparam [Properties]
145
+ #
142
146
  def blank_object(hash = {}, &) = BlankObject.new(self).build(hash, &)
143
147
 
144
148
  # Create a business object for the current member, starting with a blank object and building properties
145
149
  #
146
150
  # @param hash [Hash] Hash version of props to set (block takes priority)
151
+ # @yield Block context to define additional properties with +add+
152
+ # @yieldparam [Properties]
147
153
  #
148
154
  def post_from_blank(hash = {}, &) = post(blank_object(hash, &))
149
155
  alias create_from_blank post_from_blank
@@ -179,7 +185,7 @@ module Usps
179
185
 
180
186
  existing = get
181
187
 
182
- JSON.parse(JSON.dump(existing)).tap do |updated|
188
+ JSON.parse(JSON.dump(existing.raw)).tap do |updated|
183
189
  # Preserve the iMIS ID, as well as the Ordinal (if present)
184
190
  updated['Properties']['$values'], properties =
185
191
  existing.raw['Properties']['$values'].partition { %w[ID Ordinal].include?(it['Name']) }
@@ -204,7 +210,7 @@ module Usps
204
210
  def raw_object
205
211
  raise Errors::MissingIdError if api.imis_id.nil?
206
212
 
207
- response = submit(uri, authorize(http_get))
213
+ response = submit(authorize(http_get))
208
214
  klass = business_object_name == 'Party' ? PartyData : Data
209
215
  result = klass.from_json(response.body)
210
216
  logger.json result
@@ -217,7 +223,7 @@ module Usps
217
223
  raise Errors::MissingIdError if api.imis_id.nil?
218
224
 
219
225
  request.body = JSON.dump(body)
220
- response = submit(uri, authorize(request))
226
+ response = submit(authorize(request))
221
227
  klass = business_object_name == 'Party' ? PartyData : Data
222
228
  result = klass.from_json(response.body)
223
229
  logger.json result
@@ -17,7 +17,7 @@ module Usps
17
17
  local: File.join(Dir.pwd, 'imis.yml'),
18
18
  local_dot_config: File.join(Dir.pwd, '.config', 'imis.yml'),
19
19
  local_config: File.join(Dir.pwd, 'config', 'imis.yml'),
20
- user: "#{Dir.home}/.config/imis.yml",
20
+ user: File.join(Dir.home, '.config', 'imis.yml'),
21
21
  system: '/usr/local/imis/config.yml'
22
22
  }.freeze
23
23
 
@@ -50,7 +50,7 @@ module Usps
50
50
 
51
51
  configure!
52
52
  logging!
53
- @logger ||= Imis.logger('CommandLine')
53
+ @logger = Imis.logger('CommandLine')
54
54
  end
55
55
 
56
56
  # Run the configured action on the API
@@ -111,16 +111,15 @@ module Usps
111
111
 
112
112
  def simplify(data)
113
113
  return data.to_a if data.is_a?(Query)
114
- return data if options[:raw] || RAW_HASH_RESPONSE_OPTIONS.any? { options[it] }
114
+ return data.is_a?(BaseData) ? data.raw : data if force_raw_output?
115
115
 
116
116
  if data.is_a?(PartyData)
117
117
  logger.debug 'Returning simplified PartyData#properties'
118
118
  data.properties
119
- elsif data.is_a?(Hash)
120
- # Hash includes Usps::Imis::Data
119
+ elsif data.is_a?(Data)
121
120
  logger.debug 'Returning simplified Data#properties'
122
121
  data.properties(include_ids: options[:include_ids])
123
- elsif data.is_a?(Array) && data.all?(Hash)
122
+ elsif data.is_a?(Array) && data.all?(Data)
124
123
  logger.debug 'Returning simplified Array<Data#properties>'
125
124
  data.map { it.properties(include_ids: options[:include_ids]) }
126
125
  else
@@ -128,6 +127,8 @@ module Usps
128
127
  end
129
128
  end
130
129
 
130
+ def force_raw_output? = options[:raw] || RAW_HASH_RESPONSE_OPTIONS.any? { options[it] }
131
+
131
132
  # :nocov:
132
133
  def output(&)
133
134
  if ENV.fetch('SUPPRESS_OUTPUT', false)
@@ -158,6 +159,8 @@ module Usps
158
159
  global_log!(config)
159
160
 
160
161
  config_data&.each do |key, value|
162
+ next unless Config::SETTABLE.include?(key)
163
+
161
164
  config.public_send("#{key}=", value)
162
165
  end
163
166
  end
@@ -6,83 +6,46 @@ module Usps
6
6
  # Command line options parser
7
7
  #
8
8
  class OptionsParser
9
- OPTIONS = {
10
- # IDs
11
- certificate: ['Member certificate number', { type: :string }],
12
- id: ['Member iMIS ID', { type: :integer }],
13
- record_id: ['Specific Record ID', { type: :integer, short: :I }],
14
- uuid: ['Record UUID', { type: :string }],
15
-
16
- # Primary interactions
17
- on: ['Business Object name', { type: :string }],
18
- panel: ['Panel name', { type: :string }],
19
- query: ['IQA Query or Business Object name to query', { type: :string, short: :Q }],
20
- mapper: ['Interact with mapped fields', { short: :M }],
21
- map: ["Shorthand for #{'-Mf'.green} to access a single mapped field", { type: :string }],
22
- business_objects: ['List available Business Objects'],
23
-
24
- # Alternate verbs
25
- create: ["Send a #{'POST'.cyan} request", { short: :P }],
26
- delete: ["Send a #{'DELETE'.cyan} request", { short: :D }],
27
-
28
- # Data
29
- ordinal: ['Ordinal ID within a Panel', { type: :integer }],
30
- field: ['Specific field to return or update', { type: :string }],
31
- fields: ['Specific field(s) to return', { type: :strings, short: :F }],
32
- data: ["JSON string input -- #{'STDIN'.red} takes priority", { type: :string }],
33
-
34
- # Iteractions for supporting other language wrappers
35
- auth_token: ['Return an auth token for other language wrappers', { short: :T }],
36
- token: ['Provide an existing auth token', { type: :string }],
37
-
38
- # General config
39
- config: [
40
- 'Path to the JSON/YAML config file to use, or one of the following preset options: ' \
41
- "`#{'local'.yellow}`, " \
42
- "`#{'local_dot_config'.yellow}`, " \
43
- "`#{'local_config'.yellow}`, " \
44
- "`#{'user'.yellow}`, " \
45
- "`#{'system'.yellow}`. " \
46
- 'If no option is provided, the first matching preset option will be automatically used.',
47
- { type: :string, short: :C }
48
- ],
49
- show_config: ['Return the active config file path', { short: :X }],
50
- raw: ['Return raw JSON output, rather than simplified data', { short: :R }],
51
- include_ids: ["Include any #{'iMIS ID'.yellow} and #{'Ordinal'.yellow} properties in returned data"],
52
- jsonl: ['Format array output as JSONL', { short: :j }],
53
- quiet: ["Suppress logging to #{'STDERR'.red}"],
54
- log: ["Redirect logging to #{'STDOUT'.red}"],
55
- log_level: ['Set the logging level', { type: :string, default: 'info', short: :L }]
56
- }.freeze
57
-
9
+ SOLO_FLAGS = %i[show_config auth_token business_objects].freeze
58
10
  CONFLICTING_OPTION_GROUPS = [
59
11
  %i[certificate id uuid],
60
12
  %i[record_id uuid],
61
- %i[on panel query mapper map business_objects auth_token show_config],
13
+ %i[on panel query mapper map] + SOLO_FLAGS,
62
14
  %i[field fields map query],
63
15
  %i[raw include_ids],
64
16
  %i[quiet log_level],
65
17
  %i[quiet log],
66
18
 
67
19
  %i[create delete],
20
+ %i[create ordinal],
21
+ %i[data fields],
68
22
 
69
- %i[create mapper],
70
- %i[create query],
71
- %i[create map],
72
- %i[create field],
73
- %i[create fields],
74
-
75
- %i[delete mapper],
76
- %i[delete query],
77
- %i[delete map],
78
- %i[delete field],
79
- %i[delete fields],
80
- %i[delete data],
81
- %i[delete raw]
23
+ *(SOLO_FLAGS + %i[mapper query map field fields certificate]).map { [:create, it] },
24
+ *(SOLO_FLAGS + %i[mapper query map field fields certificate data raw]).map { [:delete, it] },
25
+ *(SOLO_FLAGS + %i[mapper query map on]).map { [:ordinal, it] },
26
+ *(SOLO_FLAGS + %i[certificate]).map { [:data, it] }
82
27
  ].freeze
83
28
 
84
29
  attr_reader :arguments, :options
85
30
 
31
+ def self.options
32
+ return @options if @options
33
+
34
+ raw_yaml_erb = File.read("#{File.dirname(__FILE__)}/options.yml.erb")
35
+ rendered_yaml = ERB.new(raw_yaml_erb).result.gsub("\x1b", '\u001b')
36
+ options = YAML.safe_load(rendered_yaml)
37
+
38
+ @options = options.transform_keys(&:to_sym).transform_values do |description, details|
39
+ next [description] if details.nil?
40
+
41
+ details = details.transform_keys(&:to_sym).each_with_object({}) do |(key, value), hash|
42
+ hash[key] = key == :default ? value : value.to_sym
43
+ end
44
+
45
+ [description, details]
46
+ end
47
+ end
48
+
86
49
  def self.banner_header(version)
87
50
  <<~BANNER
88
51
  #{version.bold.blue}
@@ -147,7 +110,7 @@ module Usps
147
110
  banner OptionsParser.banner_header(version)
148
111
  banner OptionsParser.banner_contents
149
112
 
150
- OPTIONS.each { |option, data| opt(option, *data) }
113
+ OptionsParser.options.each { |option, data| opt(option, *data) }
151
114
  CONFLICTING_OPTION_GROUPS.each { |group| conflicts(*group) }
152
115
 
153
116
  educate_on_error
@@ -160,7 +123,7 @@ module Usps
160
123
  # :nocov:
161
124
 
162
125
  def defaults?
163
- options_with_defaults = OPTIONS.select { |_, data| data[1]&.key?(:default) }
126
+ options_with_defaults = OptionsParser.options.select { |_, data| data[1]&.key?(:default) }
164
127
 
165
128
  options_with_defaults.all? { |option, data| data[1].nil? || options[option] == data[1][:default] } &&
166
129
  options.except(*options_with_defaults.keys).values.none?
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'optimist'
4
4
  require 'colorize'
5
+ require 'erb'
5
6
 
6
7
  module Usps
7
8
  module Imis
@@ -13,7 +13,10 @@ module Usps
13
13
  class Config
14
14
  IMIS_ROOT_URL_PROD = 'https://portal.americasboatingclub.org'
15
15
  IMIS_ROOT_URL_DEV = 'https://abcdev.imiscloud.com'
16
- REQUIRED_CONFIGS = %w[imis_id_query_name username password].freeze
16
+ DEFAULT_GLOBAL_LOG_PATH = '/var/log/imis/imis.log'
17
+ REQUIRED = %w[imis_id_query_name username password].freeze
18
+ OPTIONAL = %w[environment logger_file global_log_path].freeze
19
+ SETTABLE = (REQUIRED + OPTIONAL).freeze
17
20
 
18
21
  attr_accessor :imis_id_query_name, :username, :password
19
22
  attr_reader :environment, :logger, :logger_level, :logger_file
@@ -31,22 +34,36 @@ module Usps
31
34
  @logger_level = logger.class::SEV_LABEL[logger.level].downcase.to_sym
32
35
  end
33
36
 
37
+ # Define the API environment
38
+ #
39
+ # @param env [String] Environment to use
40
+ #
34
41
  def environment=(env)
35
42
  @environment = ActiveSupport::StringInquirer.new(env.to_s)
36
43
  end
37
44
 
45
+ # Override the main logger
46
+ #
47
+ # @param logger [Logger] Configured logging object
48
+ #
38
49
  def logger=(logger)
39
50
  @base_logger = logger.tap { it.formatter = LoggerFormatter.new }
40
51
  @base_logger.singleton_class.include(LoggerHelpers)
41
52
  @logger = ActiveSupport::TaggedLogging.new(@base_logger)
42
53
  end
43
54
 
55
+ # Define the main logger
56
+ #
57
+ # @param path [path, nil] Path to write log to, or +nil+ to log to +STDOUT+
58
+ #
44
59
  def logger_file=(path)
45
60
  @logger_file = path
46
61
  @base_logger = Logger.new(@logger_file.nil? ? $stdout : @logger_file, level: logger.level)
47
62
  @logger = ActiveSupport::TaggedLogging.new(@base_logger)
48
63
  end
49
64
 
65
+ # Current global mirror debug logger
66
+ #
50
67
  def global_logger
51
68
  return @global_logger if @global_logger
52
69
 
@@ -54,14 +71,21 @@ module Usps
54
71
  @global_logger
55
72
  end
56
73
 
74
+ # Current path for the global mirror debug logger
75
+ #
57
76
  def global_log_path
58
- defined?(@global_log_path) ? @global_log_path : self.global_log_path = '/var/log/imis/imis.log'
77
+ return @global_log_path if defined?(@global_log_path)
78
+
79
+ self.global_log_path = DEFAULT_GLOBAL_LOG_PATH
59
80
  end
60
81
 
82
+ # Define the global mirror debug logger
83
+ #
84
+ # @param path [path, nil] Path to write log to, or +nil+ to disable
85
+ #
61
86
  def global_log_path=(path)
62
87
  @global_log_path = path
63
88
  @global_logger = build_global_logger
64
- global_log_path
65
89
  end
66
90
 
67
91
  def silence!
@@ -88,7 +112,7 @@ module Usps
88
112
  def filtered_parameters = %i[password]
89
113
 
90
114
  def validate!
91
- missing_config = REQUIRED_CONFIGS.filter_map { it if public_send(it).nil? }
115
+ missing_config = REQUIRED.filter_map { it if public_send(it).nil? }
92
116
  return if missing_config.empty?
93
117
 
94
118
  raise Errors::ConfigError, "Missing required configuration: #{missing_config.join(', ')}"
@@ -95,7 +95,7 @@ module Usps
95
95
  response_body['error_description']
96
96
  else
97
97
  # Unknown error type: just use the raw response
98
- JSON.pretty_generate(response.body)
98
+ JSON.pretty_generate(response_body)
99
99
  end
100
100
  end
101
101
  end
@@ -30,7 +30,7 @@ module Usps
30
30
  def initialize(api = nil, imis_id: nil)
31
31
  @api = api || Api.new
32
32
  @api.imis_id = imis_id if imis_id
33
- @logger ||= Imis.logger('Mapper')
33
+ @logger = Imis.logger('Mapper')
34
34
  end
35
35
 
36
36
  # Get a member's data for a specific field by arbitrary field name
@@ -39,14 +39,14 @@ module Usps
39
39
  #
40
40
  # Only available for fields defined in +FIELD_MAPPING+
41
41
  #
42
- # @param field_key [Symbol] Internal name of the field
42
+ # @param field_key [String, Symbol] Internal name of the field
43
43
  #
44
44
  # @return Value of the field
45
45
  #
46
46
  def get_field(field_key)
47
47
  missing_mapping!(field_key) unless FIELD_MAPPING.key?(field_key.to_sym)
48
48
 
49
- business_object_name, field = FIELD_MAPPING[field_key]
49
+ business_object_name, field = FIELD_MAPPING[field_key.to_sym]
50
50
  api.on(business_object_name)[field]
51
51
  end
52
52
  alias fetch get_field
@@ -68,8 +68,8 @@ module Usps
68
68
  business_objects[business_object_name] << field
69
69
  end
70
70
 
71
- business_objects.flat_map do |business_object_name, fields|
72
- api.on(business_object_name).get_fields(*fields)
71
+ business_objects.flat_map do |business_object_name, object_fields|
72
+ api.on(business_object_name).get_fields(*object_fields)
73
73
  end
74
74
  end
75
75
  alias fetch_all get_fields
@@ -18,7 +18,7 @@ module Usps
18
18
  @api = api || Api.new
19
19
  @api.imis_id = imis_id if imis_id
20
20
  @api.record_id = record_id if record_id
21
- @logger ||= Imis.logger('Panel')
21
+ @logger = Imis.logger('Panel')
22
22
  end
23
23
 
24
24
  # Get a specific object from the Panel
@@ -10,6 +10,8 @@ module Usps
10
10
  # @param id [String] iMIS ID to include in the properties before running the block
11
11
  # @param ordinal [String] Ordinal to include in the properties before running the block
12
12
  # @param hash [Hash] Hash version of props to set (block takes priority)
13
+ # @yield Block context to define additional properties with +add+
14
+ # @yieldparam [Properties]
13
15
  #
14
16
  def self.build(id = nil, ordinal = nil, hash = {}, &) = new.build(id, ordinal, hash, &)
15
17
 
@@ -19,7 +21,7 @@ module Usps
19
21
  case value
20
22
  when String then value
21
23
  when Symbol then value.to_s
22
- when Time, DateTime then value.strftime('%Y-%m-%dT%H:%I:%S')
24
+ when Time, DateTime then value.strftime('%Y-%m-%dT%H:%M:%S')
23
25
  when Integer then { '$type' => 'System.Int32', '$value' => value }
24
26
  when true, false then { '$type' => 'System.Boolean', '$value' => value }
25
27
  else
@@ -33,6 +35,7 @@ module Usps
33
35
  # @param ordinal [String] Ordinal to include in the properties before running the block
34
36
  # @param hash [Hash] Hash version of props to set (block takes priority)
35
37
  # @yield Block context to define additional properties with +add+
38
+ # @yieldparam [Properties]
36
39
  #
37
40
  def build(id = nil, ordinal = nil, hash = {})
38
41
  @properties ||= []
@@ -59,7 +59,7 @@ module Usps
59
59
  @page_size = page_size
60
60
  @offset = offset
61
61
  @count = 0
62
- @logger ||= Imis.logger('Query', query_type)
62
+ @logger = Imis.logger('Query', query_type)
63
63
 
64
64
  logger.tagged('Name').debug query_name
65
65
  logger.tagged('Params').json query_params
@@ -113,7 +113,7 @@ module Usps
113
113
 
114
114
  # Fetch a raw query page
115
115
  #
116
- def fetch = JSON.parse(submit(uri, authorize(http_get)).body)
116
+ def fetch = JSON.parse(submit(authorize(http_get)).body)
117
117
 
118
118
  # Reset query paging progress
119
119
  #
@@ -7,23 +7,18 @@ module Usps
7
7
  module Requests
8
8
  private
9
9
 
10
- def logger = raise("#{self.class.name} must implement #logger")
10
+ def logger = raise(Errors::ApiError, "#{self.class.name} must implement #logger")
11
11
 
12
12
  def token = api.token
13
13
  def token_expiration = api.token_expiration
14
- def authenticate = api.send(:authenticate)
14
+ def authenticate = api.authenticate
15
15
 
16
16
  def http_get = Net::HTTP::Get.new(uri)
17
17
  def http_put = Net::HTTP::Put.new(uri)
18
18
  def http_post = Net::HTTP::Post.new(uri(id: ''))
19
19
  def http_delete = Net::HTTP::Delete.new(uri)
20
20
 
21
- def client(uri)
22
- Net::HTTP.new(uri.host, uri.port).tap do |http|
23
- http.use_ssl = true
24
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
25
- end
26
- end
21
+ def client = respond_to?(:http_connection) ? http_connection : api.http_connection
27
22
 
28
23
  # Authorize a request prior to submitting
29
24
  #
@@ -37,13 +32,13 @@ module Usps
37
32
  request.tap { it.add_field('Authorization', "Bearer #{token}") }
38
33
  end
39
34
 
40
- def submit(uri, request)
35
+ def submit(request)
41
36
  logger.info 'Submitting request to iMIS'
42
37
  logger.tagged('Request') do
43
38
  logger.debug "#{request.class.name.demodulize.upcase} #{uri}"
44
39
  logger.json sanitized_request_body(request)
45
40
 
46
- client(uri).request(request).tap do |result|
41
+ client.request(request).tap do |result|
47
42
  raise Errors::ResponseError.from(result) unless result.is_a?(Net::HTTPSuccess)
48
43
 
49
44
  logger.info 'Request succeeded'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Usps
4
4
  module Imis
5
- VERSION = '0.11.40'
5
+ VERSION = '0.11.42'
6
6
  end
7
7
  end
data/lib/usps/imis.rb CHANGED
@@ -12,7 +12,7 @@ require 'active_support/core_ext/object/to_query'
12
12
  require 'active_support/core_ext/enumerable'
13
13
  require 'active_support/string_inquirer'
14
14
  require 'logger'
15
- require 'active_support/isolated_execution_state' # Fix costant loading issue with TaggedLogging
15
+ require 'active_support/isolated_execution_state' # Fix constant loading issue with TaggedLogging
16
16
  require 'active_support/tagged_logging'
17
17
 
18
18
  require 'dotenv/load'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usps-imis-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.40
4
+ version: 0.11.42
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander