usps-imis-api 0.11.41 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac3e7c47ae3555e7cb4d83bf24585b5b4ffac669c0f60dab014996566a4ad366
4
- data.tar.gz: 547b0943b75e78b4ba4b968e3a780194cfe783eaef2301a4f5cacdee6e298c0e
3
+ metadata.gz: 5f986785bbba830f42a6aaa6a64f339cebeee7d860468817a7c7c49cf012eed9
4
+ data.tar.gz: 32a73e123d38e7785f0f26b8515f5f370af3b6c0788d3665f1d69c54244dfac3
5
5
  SHA512:
6
- metadata.gz: 5f7009001491dd4177d883335bdd63a2049bf157bbac66295d22c789dd1755b9672d096a760a000883f6397e4ee9c74d48cebae0c1868895e46c7b63577aaae6
7
- data.tar.gz: 8509266846dab5d93389ee7486afb8f987202d1cfbda01b2e59894e2e5fe6caddf7e820b2c822335c7123535fac1b0d3ada220d9deaf20bb3ab56a3284fccd37
6
+ metadata.gz: a559de92104378e97072b90d01c68c9723c5635b95a409dca45b4f144c46b337d8a084a46495c616494d568ae1b7719225b4e93a79dbd385657f6255154b300a
7
+ data.tar.gz: 3fc29fa1f0a916103647eb2d1220bcf07ac03b5476b1aa6423593c7eca13ffee880bc9eda123eb5677ce15785d9e838428dabd1d0da69963bf98586e004a1cf4
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
@@ -139,6 +139,8 @@ module Usps
139
139
  # @param id [Integer, String] iMIS ID to select for requests within the block
140
140
  # @param certificate [String] Certificate number to convert to iMIS ID and select for requests within the block
141
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]
142
144
  #
143
145
  # @example
144
146
  # with(12345) do
@@ -184,6 +186,8 @@ module Usps
184
186
  #
185
187
  # @param business_object_name [String, Symbol] Name of the business object
186
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]
187
191
  #
188
192
  # @return [Usps::Imis::BusinessObject]
189
193
  #
@@ -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
 
@@ -139,11 +139,17 @@ module Usps
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
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ module CommandLine
6
+ # Command line interface output formatters
7
+ #
8
+ # @private
9
+ #
10
+ module Formatters
11
+ # CLI options that indicate the response is a raw Hash rather than a Data object,
12
+ # and should not be simplified
13
+ #
14
+ RAW_HASH_RESPONSE_OPTIONS = %i[business_objects auth_token].freeze
15
+
16
+ private
17
+
18
+ def simplify(data)
19
+ return data.to_a if data.is_a?(Query)
20
+ return data.is_a?(BaseData) ? data.raw : data if force_raw_output?
21
+
22
+ if data.is_a?(PartyData)
23
+ logger.debug 'Returning simplified PartyData#properties'
24
+ data.properties
25
+ elsif data.is_a?(Data)
26
+ logger.debug 'Returning simplified Data#properties'
27
+ data.properties(include_ids: options[:include_ids])
28
+ elsif data.is_a?(Array) && data.all?(Data)
29
+ logger.debug 'Returning simplified Array<Data#properties>'
30
+ data.map { it.properties(include_ids: options[:include_ids]) }
31
+ else
32
+ data
33
+ end
34
+ end
35
+
36
+ def force_raw_output? = options[:raw] || RAW_HASH_RESPONSE_OPTIONS.any? { options[it] }
37
+
38
+ # :nocov:
39
+ def output(&)
40
+ if ENV.fetch('SUPPRESS_OUTPUT', false)
41
+ logger.debug 'Output suppressed'
42
+ return
43
+ end
44
+
45
+ return unless block_given?
46
+
47
+ value = yield
48
+
49
+ if value.is_a?(Array) && @options[:jsonl] then jsonl(value)
50
+ elsif value.is_a?(Array) && @options[:csv] then csv(value)
51
+ else raw(value)
52
+ end
53
+ end
54
+
55
+ def raw(value) = puts(JSON.dump(value))
56
+
57
+ def jsonl(value) = puts(value.map { JSON.dump(it) })
58
+
59
+ def csv(value)
60
+ puts(CSV.generate(headers: value.first.keys, write_headers: true) do |csv|
61
+ value.each { csv << it.values }
62
+ end)
63
+ end
64
+ # :nocov:
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'performers'
4
+ require_relative 'formatters'
4
5
 
5
6
  module Usps
6
7
  module Imis
@@ -9,6 +10,7 @@ module Usps
9
10
  #
10
11
  class Interface
11
12
  include Performers
13
+ include Formatters
12
14
 
13
15
  # Prioritized list of config file paths to automatically check if not provided
14
16
  #
@@ -17,15 +19,10 @@ module Usps
17
19
  local: File.join(Dir.pwd, 'imis.yml'),
18
20
  local_dot_config: File.join(Dir.pwd, '.config', 'imis.yml'),
19
21
  local_config: File.join(Dir.pwd, 'config', 'imis.yml'),
20
- user: "#{Dir.home}/.config/imis.yml",
22
+ user: File.join(Dir.home, '.config', 'imis.yml'),
21
23
  system: '/usr/local/imis/config.yml'
22
24
  }.freeze
23
25
 
24
- # CLI options that indicate the response is a raw Hash rather than a Data object,
25
- # and should not be simplified
26
- #
27
- RAW_HASH_RESPONSE_OPTIONS = %i[business_objects auth_token].freeze
28
-
29
26
  # Options passed in from the command line
30
27
  #
31
28
  attr_reader :options
@@ -109,45 +106,6 @@ module Usps
109
106
  logger.debug "Record ID: #{api.record_id}" if api.record_id
110
107
  end
111
108
 
112
- def simplify(data)
113
- return data.to_a if data.is_a?(Query)
114
- return data.is_a?(BaseData) ? data.raw : data if force_raw_output?
115
-
116
- if data.is_a?(PartyData)
117
- logger.debug 'Returning simplified PartyData#properties'
118
- data.properties
119
- elsif data.is_a?(Data)
120
- logger.debug 'Returning simplified Data#properties'
121
- data.properties(include_ids: options[:include_ids])
122
- elsif data.is_a?(Array) && data.all?(Data)
123
- logger.debug 'Returning simplified Array<Data#properties>'
124
- data.map { it.properties(include_ids: options[:include_ids]) }
125
- else
126
- data
127
- end
128
- end
129
-
130
- def force_raw_output? = options[:raw] || RAW_HASH_RESPONSE_OPTIONS.any? { options[it] }
131
-
132
- # :nocov:
133
- def output(&)
134
- if ENV.fetch('SUPPRESS_OUTPUT', false)
135
- logger.debug 'Output suppressed'
136
- return
137
- end
138
-
139
- return unless block_given?
140
-
141
- value = yield
142
-
143
- if value.is_a?(Array) && @options[:jsonl]
144
- puts(value.map { JSON.dump(it) })
145
- else
146
- puts JSON.dump(value)
147
- end
148
- end
149
- # :nocov:
150
-
151
109
  # Supports YAML or JSON config data
152
110
  #
153
111
  def configure!
@@ -7,22 +7,25 @@ module Usps
7
7
  #
8
8
  class OptionsParser
9
9
  SOLO_FLAGS = %i[show_config auth_token business_objects].freeze
10
+ QUERY_FLAGS = %i[query page page_size offset].freeze
10
11
  CONFLICTING_OPTION_GROUPS = [
11
12
  %i[certificate id uuid],
12
13
  %i[record_id uuid],
13
14
  %i[on panel query mapper map] + SOLO_FLAGS,
14
15
  %i[field fields map query],
15
16
  %i[raw include_ids],
17
+ %i[raw jsonl csv],
16
18
  %i[quiet log_level],
17
19
  %i[quiet log],
20
+ %i[page offset],
18
21
 
19
22
  %i[create delete],
20
23
  %i[create ordinal],
21
24
  %i[data fields],
22
25
 
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 + QUERY_FLAGS + %i[mapper map field fields certificate]).map { [:create, it] },
27
+ *(SOLO_FLAGS + QUERY_FLAGS + %i[mapper map field fields certificate data raw]).map { [:delete, it] },
28
+ *(SOLO_FLAGS + QUERY_FLAGS + %i[mapper map on]).map { [:ordinal, it] },
26
29
  *(SOLO_FLAGS + %i[certificate]).map { [:data, it] }
27
30
  ].freeze
28
31
 
@@ -88,17 +91,7 @@ module Usps
88
91
  #
89
92
  Optimist.educate if ARGV.empty? && defaults?
90
93
 
91
- # :nocov:
92
- @options[:data] = read_stdin if stdin?
93
- # :nocov:
94
-
95
- @options[:data] = JSON.parse(@options[:data]) if @options[:data]
96
-
97
- # Support shorthand for setting `certificate` param on queries
98
- return unless @options[:query] && @options[:certificate]
99
-
100
- @options[:data] ||= {}
101
- @options[:data]['certificate'] = @options.delete(:certificate)
94
+ pre_process_options!
102
95
  end
103
96
 
104
97
  private
@@ -128,6 +121,24 @@ module Usps
128
121
  options_with_defaults.all? { |option, data| data[1].nil? || options[option] == data[1][:default] } &&
129
122
  options.except(*options_with_defaults.keys).values.none?
130
123
  end
124
+
125
+ def pre_process_options!
126
+ # :nocov:
127
+ @options[:data] = read_stdin if stdin?
128
+ # :nocov:
129
+
130
+ @options[:data] = JSON.parse(@options[:data]) if @options[:data]
131
+
132
+ raise Errors::CommandLineError, 'Maximum page size is 500' if @options[:page_size] > 500
133
+
134
+ @options[:offset] = (@options[:page] - 1) * @options[:page_size] if @options[:page]
135
+
136
+ # Support shorthand for setting `certificate` param on queries
137
+ return unless @options[:query] && @options[:certificate]
138
+
139
+ @options[:data] ||= {}
140
+ @options[:data]['certificate'] = @options.delete(:certificate)
141
+ end
131
142
  end
132
143
  end
133
144
  end
@@ -15,11 +15,11 @@ module Usps
15
15
  in mapper:, **extra then perform_mapper(mapper, **extra)
16
16
  in on:, **extra then perform_on(on, **extra)
17
17
  in panel:, **extra then perform_panel(panel, **extra)
18
- in query:, **extra then api.query(query, extra[:data])
18
+ in query:, **extra then perform_query(query, **extra)
19
19
  in business_objects: true then api.business_objects
20
20
  in auth_token: true then api.auth_token
21
- in certificate: then api.imis_id
22
- in show_config: then config_path
21
+ in certificate: _ then api.imis_id
22
+ in show_config: true then config_path
23
23
  in version: true then api.class.version
24
24
  end
25
25
  rescue NoMatchingPatternError => e
@@ -33,8 +33,7 @@ module Usps
33
33
  in mapper: true then converted[:mapper] = api.mapper
34
34
  in on: then converted[:on] = api.on(on)
35
35
  in panel: then converted[:panel] = api.panels.public_send(panel)
36
- else
37
- # Nothing to convert
36
+ else # Nothing to convert
38
37
  end
39
38
 
40
39
  # Remove flags when false
@@ -59,8 +58,7 @@ module Usps
59
58
  in data: then on.put_fields(data)
60
59
  in fields: then on.get_fields(*fields)
61
60
  in field: then on.get_field(field)
62
- else
63
- on.get
61
+ else on.get
64
62
  end
65
63
  end
66
64
 
@@ -75,6 +73,19 @@ module Usps
75
73
  in ordinal: then panel.get(ordinal)
76
74
  end
77
75
  end
76
+
77
+ def perform_query(query, **options)
78
+ case options
79
+ in page: _, page_size:, offset:, data: then api.query(query, page_size:, offset:, **data).page
80
+ in page: _, page_size:, offset: then api.query(query, page_size:, offset:).page
81
+ in page: _, page_size:, data: then api.query(query, page_size:, **data).page
82
+ in page: _, page_size: then api.query(query, page_size:).page
83
+ in page_size:, offset:, data: then api.query(query, page_size:, offset:, **data)
84
+ in page_size:, data: then api.query(query, page_size:, **data)
85
+ in data: then api.query(query, **data)
86
+ else api.query(query)
87
+ end
88
+ end
78
89
  end
79
90
  end
80
91
  end
@@ -3,6 +3,7 @@
3
3
  require 'optimist'
4
4
  require 'colorize'
5
5
  require 'erb'
6
+ require 'csv'
6
7
 
7
8
  module Usps
8
9
  module Imis
@@ -34,22 +34,36 @@ module Usps
34
34
  @logger_level = logger.class::SEV_LABEL[logger.level].downcase.to_sym
35
35
  end
36
36
 
37
+ # Define the API environment
38
+ #
39
+ # @param env [String] Environment to use
40
+ #
37
41
  def environment=(env)
38
42
  @environment = ActiveSupport::StringInquirer.new(env.to_s)
39
43
  end
40
44
 
45
+ # Override the main logger
46
+ #
47
+ # @param logger [Logger] Configured logging object
48
+ #
41
49
  def logger=(logger)
42
50
  @base_logger = logger.tap { it.formatter = LoggerFormatter.new }
43
51
  @base_logger.singleton_class.include(LoggerHelpers)
44
52
  @logger = ActiveSupport::TaggedLogging.new(@base_logger)
45
53
  end
46
54
 
55
+ # Define the main logger
56
+ #
57
+ # @param path [path, nil] Path to write log to, or +nil+ to log to +STDOUT+
58
+ #
47
59
  def logger_file=(path)
48
60
  @logger_file = path
49
61
  @base_logger = Logger.new(@logger_file.nil? ? $stdout : @logger_file, level: logger.level)
50
62
  @logger = ActiveSupport::TaggedLogging.new(@base_logger)
51
63
  end
52
64
 
65
+ # Current global mirror debug logger
66
+ #
53
67
  def global_logger
54
68
  return @global_logger if @global_logger
55
69
 
@@ -57,12 +71,18 @@ module Usps
57
71
  @global_logger
58
72
  end
59
73
 
74
+ # Current path for the global mirror debug logger
75
+ #
60
76
  def global_log_path
61
77
  return @global_log_path if defined?(@global_log_path)
62
78
 
63
79
  self.global_log_path = DEFAULT_GLOBAL_LOG_PATH
64
80
  end
65
81
 
82
+ # Define the global mirror debug logger
83
+ #
84
+ # @param path [path, nil] Path to write log to, or +nil+ to disable
85
+ #
66
86
  def global_log_path=(path)
67
87
  @global_log_path = path
68
88
  @global_logger = build_global_logger
@@ -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
@@ -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
 
@@ -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 ||= []
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Usps
4
4
  module Imis
5
- VERSION = '0.11.41'
5
+ VERSION = '0.12.0'
6
6
  end
7
7
  end
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.41
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
@@ -51,6 +51,20 @@ dependencies:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: 1.1.0
54
+ - !ruby/object:Gem::Dependency
55
+ name: csv
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 3.3.5
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 3.3.5
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: optimist
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,7 @@ files:
80
94
  - lib/usps/imis/blank_object.rb
81
95
  - lib/usps/imis/business_object.rb
82
96
  - lib/usps/imis/command_line.rb
97
+ - lib/usps/imis/command_line/formatters.rb
83
98
  - lib/usps/imis/command_line/interface.rb
84
99
  - lib/usps/imis/command_line/options_parser.rb
85
100
  - lib/usps/imis/command_line/performers.rb