usps-imis-api 0.12.10 → 0.13.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: 885f7ace4c5c5f77d9e986c1b09e12d9e1d811596800b6181220b24fe3fecbe8
4
- data.tar.gz: 397ad89928f4efdbfea3299123378685c4fcbe78c87edf852f2fd60873acd4a5
3
+ metadata.gz: 01ea56e2c86361876d694df871ed74b17ead231c2a04956cbcf4121e9ea81a43
4
+ data.tar.gz: f1bb3827652a82ef2bbd821267305e200da82adc5305a3e8743634574ac8cba7
5
5
  SHA512:
6
- metadata.gz: '07083a6c15f1177f94c2039f1a3b80c893bfd671a6d8f9cbcfeabad33d16a8d1da3d162132acf0864ed2d21768ac0ca773e72a65b0e6a02bbb08fe9a262342f5'
7
- data.tar.gz: e5933277a7c6923b729c26fa68a65a63cf91eb997b6bc18221c57db027cb4d310f96fe2dc3d554f2d0f1ec79803154eddc4bdcb2ab268a4c52de66f9908ee596
6
+ metadata.gz: 7d827dc920c5b0db49ec6e965d1a6991e6c2198671db810fc8bd76f8d50e74ae1f3f8bcfe4c98bc1af97a6f54444b41ed94893f240bad5ec0987772bae2fe95b
7
+ data.tar.gz: c0887342a3a94477e4a2bf9e888443b4a1db68ce343b0555b5dcd9a8dd1706f70c15962a7088c19d2613f3e13f1ef6c669bdcd8f192e5c1708c41f34f77591f6
@@ -44,7 +44,12 @@ module Usps
44
44
  #
45
45
  # @return [Usps::Imis::Query] Query wrapper
46
46
  #
47
- def query = api.query(business_object_name)
47
+ def query(**) = api.query(business_object_name, **)
48
+
49
+ # Get all records from the business object for the current member
50
+ #
51
+ def get_all(**) = query(**, id: api.imis_id).to_a
52
+ alias list get_all
48
53
 
49
54
  # Support passthrough for Api#with
50
55
  #
@@ -69,6 +69,8 @@ module Usps
69
69
  CSV.generate(headers:, write_headers: !headers.nil?) do |csv|
70
70
  headers ? value.each { csv << it } : csv << value
71
71
  end
72
+ rescue StandardError
73
+ raise Errors::CommandLineError, 'Unable to format response as CSV'
72
74
  end
73
75
  end
74
76
  end
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ module CommandLine
6
+ # Custom help page generator for the command line interface
7
+ #
8
+ # @private
9
+ #
10
+ module Help
11
+ TERMINAL_WIDTH = 120
12
+ GAP = 4
13
+
14
+ def banner_header(version)
15
+ <<~BANNER
16
+ #{version.bold.blue}
17
+ #{'P/R/C Julian Fiander, SN'.gray}
18
+ BANNER
19
+ end
20
+
21
+ def banner_contents
22
+ <<~BANNER
23
+ #{'Usage'.underline}
24
+
25
+ #{'imis'.bold} #{'[command] [options]'.gray}
26
+
27
+
28
+ #{'Further Help'.underline}
29
+
30
+ For an explanation of how to provide API configuration, more details on the options,
31
+ and usage examples, please refer to the wiki:
32
+
33
+ https://github.com/unitedstatespowersquadrons/imis-api-ruby/wiki/Command-Line
34
+
35
+ BANNER
36
+ end
37
+
38
+ # Build the custom help page
39
+ #
40
+ def custom_help
41
+ [banner_header(Api.version), '', banner_contents].tap do |lines|
42
+ help_commands(lines)
43
+ help_options(lines)
44
+ help_legacy_flags(lines)
45
+ end.join("\n")
46
+ end
47
+
48
+ # Format a single option line for the help page
49
+ #
50
+ def format_option(key)
51
+ raw_description, details = options[key]
52
+ details ||= {}
53
+
54
+ flag = option_flag_string(key, details).ljust(option_column_width)
55
+ left_width = option_column_width + indent(3).length # Indent additional lines one step further
56
+ tags = [
57
+ (" (default: #{details[:default]})" if details[:default]),
58
+ (" (max: #{details[:max]})" if details[:max])
59
+ ].compact.join
60
+
61
+ "#{flag}#{wrap_description(raw_description, left_width, suffix: tags)}"
62
+ end
63
+
64
+ private
65
+
66
+ def help_commands(lines)
67
+ # Adjust the underlying command padding to account for non-printing characters
68
+ #
69
+ # Bold and gray each add 14:
70
+ # '-'.bold.length == 15
71
+ # '-'.gray.length == 15
72
+ #
73
+ escape_padding = 14
74
+
75
+ command_lengths = subcommands.map { |name, details| name.length + details[:value].to_s.length }
76
+ command_width = command_lengths.max + GAP + escape_padding
77
+
78
+ lines << "#{'Commands'.underline}\n"
79
+ subcommands.each do |name, details|
80
+ combined_name = details[:value] ? "#{name.bold} #{"<#{details[:value]}>".gray}" : name.bold
81
+ lines << [
82
+ indent(1),
83
+ combined_name.ljust(command_width + (details[:value] ? escape_padding : 0)),
84
+ details[:description]
85
+ ].join
86
+ end
87
+ lines << "\n"
88
+ end
89
+
90
+ def help_options(lines)
91
+ lines << "#{'Options'.underline}\n"
92
+ option_groups.each do |group_name, option_keys|
93
+ lines << "#{indent(1)}#{group_name.underline}"
94
+ option_keys.each { lines << "#{indent(2)}#{format_option(it)}" }
95
+ lines << ''
96
+ end
97
+ end
98
+
99
+ def help_legacy_flags(lines)
100
+ lines << "#{indent(1)}#{'Legacy Flags'.underline}\n"
101
+ lines << "#{indent(2)}The following options are still supported, but have been replaced by subcommands:\n"
102
+ legacy_flags.each do |flags, replacement|
103
+ lines << "#{indent(2)}#{flags.ljust(option_column_width)}use: #{replacement}"
104
+ end
105
+ lines << "\n"
106
+ end
107
+
108
+ def indent(level) = ' ' * level
109
+
110
+ def option_flag_string(key, details)
111
+ [
112
+ details[:short] ? "-#{details[:short]}, " : indent(2),
113
+ "--#{key.to_s.tr('_', '-')}",
114
+ type_suffix(details[:type])
115
+ ].join
116
+ end
117
+
118
+ def type_suffix(type)
119
+ case type
120
+ when :string then '=<s>'
121
+ when :strings then '=<s+>'
122
+ when :integer then '=<i>'
123
+ when :ints then '=<i+>'
124
+ when :float then '=<f>'
125
+ when :floats then '=<f+>'
126
+ when :date then '=<d>'
127
+ when :dates then '=<d+>'
128
+ when :io then '=<io>'
129
+ when :ios then '=<io+>'
130
+ else ''
131
+ end
132
+ end
133
+
134
+ def wrap_description(text, left_width, suffix: '')
135
+ max_width = TERMINAL_WIDTH - left_width
136
+ padding = "\n#{' ' * left_width}"
137
+
138
+ lines = text.split("\n").flat_map { word_wrap(it, max_width) }
139
+
140
+ if suffix.empty? || visible_length("#{lines.last}#{suffix}") <= max_width
141
+ lines[-1] = "#{lines.last}#{suffix}"
142
+ else
143
+ lines << suffix.lstrip
144
+ end
145
+
146
+ lines.join(padding)
147
+ end
148
+
149
+ def word_wrap(text, max_width)
150
+ return [text] if max_width <= 0 || visible_length(text) <= max_width
151
+
152
+ words = text.split
153
+ lines = [words.shift]
154
+ words.each do |word|
155
+ candidate = "#{lines.last} #{word}"
156
+ if visible_length(candidate) <= max_width
157
+ lines[-1] = candidate
158
+ else
159
+ lines << word
160
+ end
161
+ end
162
+ lines
163
+ end
164
+
165
+ def visible_length(text)
166
+ text.gsub(/\e\[[0-9;]*m/, '').length
167
+ end
168
+
169
+ def option_column_width
170
+ option_widths = option_groups.values.flatten.map do |key|
171
+ _, details = options[key]
172
+ option_flag_string(key, details || {}).length
173
+ end
174
+
175
+ all_widths = option_widths + legacy_flags.keys.map(&:length)
176
+ all_widths.max + GAP
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
@@ -1,134 +1,166 @@
1
- # IDs
2
- certificate:
3
- - Member certificate number
4
- - type: string
5
- short: c
6
- id:
7
- - Member iMIS ID
8
- - type: integer
9
- short: i
10
- record_id:
11
- - Specific Record ID
12
- - type: integer
13
- short: I
14
- uuid:
15
- - Record UUID
16
- - type: string
17
- short: u
1
+ Subcommands:
2
+ object:
3
+ description: Interact with a Business Object
4
+ value: name
5
+ legacy_name: 'on'
6
+ option:
7
+ - Business Object name
8
+ - type: string
9
+ short: O
10
+ panel:
11
+ description: Interact with a Panel
12
+ value: name
13
+ option:
14
+ - Panel name
15
+ - type: string
16
+ short: P
17
+ query:
18
+ description: Run an IQA or Business Object Query
19
+ value: name
20
+ option:
21
+ - IQA Query or Business Object name to query
22
+ - type: string
23
+ short: Q
24
+ mapper:
25
+ description: Interact with mapped fields
26
+ option:
27
+ - Interact with mapped fields
28
+ - short: M
29
+ map:
30
+ description: "Shorthand for `<%= 'mapper -f'.green %>` to access a single mapped field"
31
+ value: field
32
+ option:
33
+ - "Shorthand for <%= '-Mf'.green %> to access a single mapped field"
34
+ - type: string
35
+ short: m
36
+ business-objects:
37
+ description: List available Business Objects
38
+ option:
39
+ - List available Business Objects
40
+ - short: B
41
+ auth-token:
42
+ description: Return an auth token for other language wrappers
43
+ option:
44
+ - Return an auth token for other language wrappers
45
+ - short: T
18
46
 
19
- # Primary interactions
20
- 'on':
21
- - Business Object name
22
- - type: string
23
- short: O
24
- panel:
25
- - Panel name
26
- - type: string
27
- short: P
28
- query:
29
- - IQA Query or Business Object name to query
30
- - type: string
31
- short: Q
32
- mapper:
33
- - Interact with mapped fields
34
- - short: M
35
- map:
36
- - "Shorthand for <%= '-Mf'.green %> to access a single mapped field"
37
- - type: string
38
- short: m
39
- business_objects:
40
- - List available Business Objects
41
- - short: B
47
+ Options:
48
+ Identity:
49
+ certificate:
50
+ - Member certificate number
51
+ - type: string
52
+ short: c
53
+ id:
54
+ - Member iMIS ID
55
+ - type: integer
56
+ short: i
57
+ record_id:
58
+ - Specific Record ID
59
+ - type: integer
60
+ short: I
61
+ uuid:
62
+ - Record UUID
63
+ - type: string
64
+ short: u
42
65
 
43
- # Alternate verbs
44
- create:
45
- - "Send a <%= 'POST'.cyan %> request"
46
- - short: C
47
- delete:
48
- - "Send a <%= 'DELETE'.cyan %> request"
49
- - short: D
66
+ Business Object or Panel:
67
+ create:
68
+ - "Send a <%= 'POST'.cyan %> request"
69
+ - short: C
70
+ delete:
71
+ - "Send a <%= 'DELETE'.cyan %> request"
72
+ - short: D
73
+ all:
74
+ - "Send a <%= 'GET'.cyan %> request for all records for a member"
75
+ - short: A
50
76
 
51
- # Data
52
- ordinal:
53
- - Ordinal ID within a Panel
54
- - type: integer
55
- short: r
56
- field:
57
- - Specific field to return or update
58
- - type: string
59
- short: f
60
- fields:
61
- - Specific field(s) to return
62
- - type: strings
63
- short: F
64
- data:
65
- - "JSON string input -- <%= 'STDIN'.red %> takes priority"
66
- - type: string
67
- short: d
77
+ Panel:
78
+ ordinal:
79
+ - Ordinal ID within a Panel
80
+ - type: integer
81
+ short: r
68
82
 
69
- # Query params
70
- page:
71
- - Specific page number from a query to return
72
- - type: integer
73
- short: p
74
- page_size:
75
- - Maximum number of records to include on a single page (max 500)
76
- - type: integer
77
- default: 100
78
- short: -s
79
- offset:
80
- - Number of records to skip from the beginning of a query
81
- - type: integer
82
- short: -o
83
+ Query:
84
+ page:
85
+ - Specific page number from a query to return
86
+ - type: integer
87
+ short: p
88
+ page_size:
89
+ - Maximum number of records to include on a single page
90
+ - type: integer
91
+ default: 100
92
+ max: 500
93
+ short: s
94
+ offset:
95
+ - Number of records to skip from the beginning of a query
96
+ - type: integer
97
+ short: o
83
98
 
84
- # Output formats
85
- raw:
86
- - Return raw JSON output, rather than simplified data
87
- - short: R
88
- jsonl:
89
- - Format array output as JSONL
90
- - short: j
91
- csv:
92
- - Format output as CSV (if possible)
93
- - short: S
99
+ Data Input:
100
+ field:
101
+ - Specific field to return or update
102
+ - type: string
103
+ short: f
104
+ fields:
105
+ - Specific field(s) to return
106
+ - type: strings
107
+ short: F
108
+ data:
109
+ - "JSON string input -- <%= 'STDIN'.red %> takes priority"
110
+ - type: string
111
+ short: d
94
112
 
95
- # General config
96
- config:
97
- - "Path to the JSON/YAML config file to use, or one of the following preset options: \
98
- `<%= 'local_dot'.yellow %>`, \
99
- `<%= 'local'.yellow %>`, \
100
- `<%= 'local_dot_config'.yellow %>`, \
101
- `<%= 'local_config'.yellow %>`, \
102
- `<%= 'user'.yellow %>`, \
103
- `<%= 'system'.yellow %>`. \
104
- If no option is provided, the first matching preset option will be automatically used."
105
- - type: string
106
- short: Y
107
- show_config:
108
- - Return the active config file path
109
- - short: X
110
- include_ids:
111
- - "Include any <%= 'iMIS ID'.yellow %> and <%= 'Ordinal'.yellow %> properties in returned data"
112
- - short: N
113
+ Output Format:
114
+ raw:
115
+ - Return raw JSON output, rather than simplified data
116
+ - short: R
117
+ jsonl:
118
+ - Format array output as JSONL
119
+ - short: j
120
+ csv:
121
+ - Format output as CSV (if possible)
122
+ - short: S
113
123
 
114
- # Interactions for supporting other language wrappers
115
- auth_token:
116
- - Return an auth token for other language wrappers
117
- - short: T
118
- token:
119
- - Provide an existing auth token
120
- - type: string
121
- short: t
124
+ Configuration:
125
+ config:
126
+ - "Path to the JSON/YAML config file to use, or one of the following preset options:\
127
+ \n`<%= 'local_dot'.yellow %>`, \
128
+ `<%= 'local'.yellow %>`, \
129
+ `<%= 'local_dot_config'.yellow %>`, \
130
+ `<%= 'local_config'.yellow %>`, \
131
+ `<%= 'user'.yellow %>`, \
132
+ `<%= 'system'.yellow %>`\
133
+ \nIf no option is provided, the first matching preset option will be automatically used."
134
+ - type: string
135
+ short: Y
136
+ show_config:
137
+ - Return the active config file path
138
+ - short: X
139
+ include_ids:
140
+ - "Include any <%= 'iMIS ID'.yellow %> and <%= 'Ordinal'.yellow %> properties in returned data"
141
+ - short: N
142
+ token:
143
+ - Provide an existing auth token
144
+ - type: string
145
+ short: t
122
146
 
123
- # Logging
124
- quiet:
125
- - "Suppress logging to <%= 'STDERR'.red %>"
126
- - short: q
127
- log:
128
- - "Redirect logging to <%= 'STDOUT'.red %>"
129
- - short: l
130
- log_level:
131
- - Set the logging level
132
- - type: string
133
- default: info
134
- short: L
147
+ Logging:
148
+ quiet:
149
+ - "Suppress logging to <%= 'STDERR'.red %>"
150
+ - short: q
151
+ log:
152
+ - "Redirect logging to <%= 'STDOUT'.red %>"
153
+ - short: l
154
+ log_level:
155
+ - Set the logging level
156
+ - type: string
157
+ default: info
158
+ short: L
159
+
160
+ Misc:
161
+ version:
162
+ - Print version and exit
163
+ - short: v
164
+ help:
165
+ - Show this message
166
+ - short: h
@@ -6,12 +6,15 @@ module Usps
6
6
  # Command line options parser
7
7
  #
8
8
  class OptionsParser
9
+ extend OptionsParserConfig
10
+ extend Help
11
+
9
12
  SOLO_FLAGS = %i[show_config auth_token business_objects].freeze
10
13
  QUERY_FLAGS = %i[query page page_size offset].freeze
11
14
  CONFLICTING_OPTION_GROUPS = [
12
15
  %i[certificate id uuid],
13
- %i[record_id uuid],
14
- %i[on panel query mapper map] + SOLO_FLAGS,
16
+ %i[certificate record_id uuid],
17
+ %i[object panel query mapper map] + SOLO_FLAGS,
15
18
  %i[field fields map query],
16
19
  %i[raw include_ids],
17
20
  %i[raw jsonl csv],
@@ -25,71 +28,56 @@ module Usps
25
28
 
26
29
  *(SOLO_FLAGS + QUERY_FLAGS + %i[mapper map field fields certificate]).map { [:create, it] },
27
30
  *(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] },
31
+ *(SOLO_FLAGS + QUERY_FLAGS + %i[mapper map object]).map { [:ordinal, it] },
29
32
  *(SOLO_FLAGS + %i[certificate]).map { [:data, it] }
30
33
  ].freeze
31
34
 
32
- attr_reader :arguments, :options
33
-
34
- def self.options
35
- return @options if @options
36
-
37
- raw_yaml_erb = File.read("#{File.dirname(__FILE__)}/options.yml.erb")
38
- rendered_yaml = ERB.new(raw_yaml_erb).result.gsub("\x1b", '\u001b')
39
- options = YAML.safe_load(rendered_yaml)
40
-
41
- @options = options.transform_keys(&:to_sym).transform_values do |description, details|
42
- next [description] if details.nil?
43
-
44
- details = details.transform_keys(&:to_sym).each_with_object({}) do |(key, value), hash|
45
- hash[key] = key == :default ? value : value.to_sym
46
- end
47
-
48
- [description, details]
49
- end
50
- end
35
+ attr_reader :options
51
36
 
52
- def self.banner_header(version)
53
- <<~BANNER
54
- #{version.bold.blue}
55
- #{'P/R/C Julian Fiander, SN'.gray}\n \n
56
- BANNER
37
+ # Render the custom help page and exit
38
+ #
39
+ # :nocov:
40
+ def self.help
41
+ IO.popen('less -R', 'w') { it.puts custom_help }
42
+ exit 0
57
43
  end
44
+ # :nocov:
58
45
 
59
- def self.banner_contents
60
- <<~BANNER
61
- #{'Usage'.underline}
62
-
63
- #{'imis'.bold} #{'[options]'.gray}
64
-
65
-
66
- #{'Further Help'.underline}
46
+ # Pre-process ARGV to convert subcommands and legacy aliases to current flags
47
+ #
48
+ def self.preprocess_argv!
49
+ return if ARGV.empty?
67
50
 
68
- For an explanation of how to provide API configuration, more details on the options,
69
- and usage examples, please refer to the wiki:
51
+ ARGV.map! do |arg|
52
+ flag, value = arg.split('=', 2)
53
+ next arg unless legacy_aliases.key?(flag)
70
54
 
71
- https://github.com/unitedstatespowersquadrons/imis-api-ruby/wiki/Command-Line
55
+ [legacy_aliases[flag], value].compact.join('=')
56
+ end
72
57
 
58
+ return unless (subcommand = subcommands[ARGV[0]])
73
59
 
74
- #{'Options'.underline}
75
- BANNER
60
+ name = ARGV.shift
61
+ value = ARGV.shift if subcommand[:value]
62
+ ARGV.unshift("--#{name}", *[value].compact)
76
63
  end
77
64
 
78
65
  def initialize
66
+ self.class.preprocess_argv!
67
+
68
+ # Manually render help page before parsing options, to override the default behavior
69
+ #
70
+ # :nocov:
71
+ self.class.help if ARGV.delete('-h') || ARGV.delete('--help')
72
+ # :nocov:
73
+
79
74
  @options = parse_options.compact
80
- @arguments = ARGV # Not currently used
81
75
 
82
76
  # Set the default behavior to --help instead of --version
83
77
  #
84
- # Passing any subcommands as arguments will cause this conditional to fail
85
- #
86
- # If this is disabled:
87
- #
88
- # - The default behavior is to print just the version label to the terminal
89
- # - CommandLine::Performers#perform! *must* expect a `version:` pattern,
90
- # and will return a quoted string of the version label
91
- #
92
- Optimist.educate if ARGV.empty? && defaults?
78
+ # :nocov:
79
+ self.class.help if ARGV.empty? && defaults?
80
+ # :nocov:
93
81
 
94
82
  pre_process_options!
95
83
  end
@@ -130,15 +118,24 @@ module Usps
130
118
  @options[:data] = JSON.parse(@options[:data]) if @options[:data]
131
119
 
132
120
  validate_query_options!
133
-
134
- raise Errors::CommandLineError, 'Maximum page size is 500' if @options[:page_size] > 500
121
+ validate_max_values!
135
122
 
136
123
  @options[:offset] = (@options[:page] - 1) * @options[:page_size] if @options[:page]
137
124
 
138
- # Support shorthand for setting `certificate` param on queries
139
- return unless @options[:query] && @options[:certificate]
125
+ set_shorthand_query_data if @options[:query]
126
+ end
140
127
 
141
- @options[:data] = { 'certificate' => @options.delete(:certificate) }
128
+ # Support shorthand for setting identity param on queries
129
+ #
130
+ # Doesn't currently support record_id
131
+ #
132
+ def set_shorthand_query_data
133
+ case @options
134
+ in id: _ then @options[:data] = { 'id' => @options.delete(:id) }
135
+ in certificate: _ then @options[:data] = { 'certificate' => @options.delete(:certificate) }
136
+ in uuid: _ then @options[:data] = { 'id' => @options.delete(:uuid) }
137
+ else # Do nothing
138
+ end
142
139
  end
143
140
 
144
141
  def validate_query_options!
@@ -147,6 +144,14 @@ module Usps
147
144
 
148
145
  Optimist.die(:query, "must be provided if any of --#{query_options.join(', --').gsub('_', '-')} are provided")
149
146
  end
147
+
148
+ def validate_max_values!
149
+ self.class.options.each do |option, (_, details)|
150
+ next unless details&.key?(:max) && @options[option] > details[:max]
151
+
152
+ Optimist.die(option, "must be at most #{details[:max]}")
153
+ end
154
+ end
150
155
  end
151
156
  end
152
157
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ module CommandLine
6
+ # Command line options parser config loading and processing
7
+ #
8
+ # @private
9
+ #
10
+ module OptionsParserConfig
11
+ def subcommands
12
+ @subcommands ||= yaml['Subcommands'].transform_values { it.transform_keys(&:to_sym) }
13
+ end
14
+
15
+ def option_groups
16
+ @option_groups ||= yaml['Options'].transform_values { it.keys.map(&:to_sym) }
17
+ end
18
+
19
+ def options
20
+ @options ||= merged_options.transform_keys(&:to_sym).transform_values do |description, details|
21
+ [
22
+ description,
23
+ details.transform_keys(&:to_sym).each_with_object({}) do |(key, value), hash|
24
+ hash[key] = %i[type short].include?(key) ? value.to_sym : value
25
+ end
26
+ ]
27
+ end
28
+ end
29
+
30
+ def legacy_aliases
31
+ @legacy_aliases ||= subcommands.each_with_object({}) do |(name, details), aliases|
32
+ next unless details[:legacy_name]
33
+
34
+ aliases["--#{details[:legacy_name]}"] = "--#{name}"
35
+ end
36
+ end
37
+
38
+ def legacy_flags
39
+ @legacy_flags ||= subcommands.to_h do |name, details|
40
+ flag_name = details[:legacy_name] || name.tr('-', '_')
41
+ option_key = name.tr('-', '_').to_sym
42
+ _, option_details = options[option_key]
43
+
44
+ display = option_flag_string(flag_name.to_sym, option_details || {})
45
+ replacement = ["imis #{name}".bold, details[:value] && "<#{details[:value]}>".gray].compact.join(' ')
46
+
47
+ [display, replacement]
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def yaml
54
+ return @yaml if @yaml
55
+
56
+ raw_yaml_erb = File.read("#{File.dirname(__FILE__)}/options.yml.erb")
57
+ rendered_yaml = ERB.new(raw_yaml_erb).result.gsub("\x1b", '\u001b')
58
+ @yaml = YAML.safe_load(rendered_yaml)
59
+ end
60
+
61
+ def merged_options
62
+ subcommand_options = subcommands.transform_values { it[:option] }.transform_keys { it.gsub('-', '_') }
63
+ yaml['Options'].values.inject(:merge).merge(subcommand_options)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -13,7 +13,7 @@ module Usps
13
13
  def perform!
14
14
  case convert(options)
15
15
  in mapper:, **extra then perform_mapper(mapper, **extra)
16
- in on:, **extra then perform_on(on, **extra)
16
+ in object:, **extra then perform_object(object, **extra)
17
17
  in panel:, **extra then perform_panel(panel, **extra)
18
18
  in query:, **extra then perform_query(query, **extra)
19
19
  in business_objects: true then api.business_objects
@@ -31,7 +31,7 @@ module Usps
31
31
  case converted
32
32
  in map: then converted.merge!(mapper: api.mapper, field: map)
33
33
  in mapper: true then converted[:mapper] = api.mapper
34
- in on: then converted[:on] = api.on(on)
34
+ in object: then converted[:object] = api.on(object)
35
35
  in panel: then converted[:panel] = api.panels.public_send(panel)
36
36
  else # Nothing to convert
37
37
  end
@@ -50,15 +50,16 @@ module Usps
50
50
  end
51
51
  end
52
52
 
53
- def perform_on(on, **options)
53
+ def perform_object(object, **options)
54
54
  case options
55
- in delete: true then on.delete
56
- in create: true, data: then on.post(data)
57
- in data:, field: then on.put_field(field, data)
58
- in data: then on.put_fields(data)
59
- in fields: then on.get_fields(*fields)
60
- in field: then on.get_field(field)
61
- else on.get
55
+ in delete: true then object.delete
56
+ in create: true, data: then object.post(data)
57
+ in all: true then object.list
58
+ in data:, field: then object.put_field(field, data)
59
+ in data: then object.put_fields(data)
60
+ in fields: then object.get_fields(*fields)
61
+ in field: then object.get_field(field)
62
+ else object.get
62
63
  end
63
64
  end
64
65
 
@@ -66,6 +67,7 @@ module Usps
66
67
  case options
67
68
  in delete: true, ordinal: then panel.delete(ordinal)
68
69
  in create: true, data: then panel.post(data)
70
+ in all: true then panel.list
69
71
  in ordinal:, data:, field: then panel.put_field(ordinal, field, data)
70
72
  in ordinal:, data: then panel.put_fields(ordinal, data)
71
73
  in ordinal:, fields: then panel.get_fields(ordinal, *fields)
@@ -13,5 +13,7 @@ module Usps
13
13
  end
14
14
  end
15
15
 
16
+ require_relative 'command_line/options_parser_config'
17
+ require_relative 'command_line/help'
16
18
  require_relative 'command_line/options_parser'
17
19
  require_relative 'command_line/interface'
@@ -11,7 +11,7 @@ module Usps
11
11
  log_chunks = [
12
12
  format('%-5s', severity.to_s),
13
13
  "[#{$PROCESS_ID}]",
14
- "[#{time.strftime('%Y-%m-%d %H:%M:%S %Z')}]",
14
+ "[#{time.iso8601(6)}]",
15
15
  'iMIS Ruby API',
16
16
  '|',
17
17
  formatted_tags,
@@ -21,6 +21,17 @@ module Usps
21
21
  @logger = Imis.logger('Panel')
22
22
  end
23
23
 
24
+ # Run a query on the entire business object
25
+ #
26
+ # @return [Usps::Imis::Query] Query wrapper
27
+ #
28
+ def query(**) = api.query(business_object_name, **)
29
+
30
+ # Get all records from the Panel for the current member
31
+ #
32
+ def get_all(**) = query(**, id: api.imis_id).to_a
33
+ alias list get_all
34
+
24
35
  # Get a specific object from the Panel
25
36
  #
26
37
  # If +fields+ is provided, will return only those field values
@@ -88,7 +88,7 @@ module Usps
88
88
 
89
89
  # Fetch a filtered query page, and update the current offset
90
90
  #
91
- def page = fetch_next['Items']['$values'].map { iqa? ? it.except('$type') : Imis::Data[it] }
91
+ def page = fetch_next['Items']['$values'].map { iqa? ? it.except('$type') : wrap(it) }
92
92
 
93
93
  # Fetch the next raw query page, and update the current offset
94
94
  #
@@ -148,6 +148,8 @@ module Usps
148
148
  "#{Imis::BusinessObject::API_PATH}/#{query_name}?#{path_params.to_query}"
149
149
  end
150
150
  end
151
+
152
+ def wrap(data) = query_name == 'Party' ? Imis::PartyData[data] : Imis::Data[data]
151
153
  end
152
154
  end
153
155
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Usps
4
4
  module Imis
5
- VERSION = '0.12.10'
5
+ VERSION = '0.13.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.12.10
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
@@ -95,9 +95,11 @@ files:
95
95
  - lib/usps/imis/business_object.rb
96
96
  - lib/usps/imis/command_line.rb
97
97
  - lib/usps/imis/command_line/formatters.rb
98
+ - lib/usps/imis/command_line/help.rb
98
99
  - lib/usps/imis/command_line/interface.rb
99
100
  - lib/usps/imis/command_line/options.yml.erb
100
101
  - lib/usps/imis/command_line/options_parser.rb
102
+ - lib/usps/imis/command_line/options_parser_config.rb
101
103
  - lib/usps/imis/command_line/performers.rb
102
104
  - lib/usps/imis/config.rb
103
105
  - lib/usps/imis/data.rb