appydave-tools 0.74.1 → 0.75.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/appydave/tools/jump/cli.rb +19 -4
- data/lib/appydave/tools/jump/commands/report.rb +56 -12
- data/lib/appydave/tools/jump/formatters/base.rb +4 -0
- data/lib/appydave/tools/jump/formatters/table_formatter.rb +182 -1
- data/lib/appydave/tools/version.rb +1 -1
- data/package.json +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e45ff57b507a705f826281a7d361abf0724d719eaf1c1ba4795198f3a4551a7f
|
|
4
|
+
data.tar.gz: edfc8fcdb775c290d9c59a588215de3e2c613075ee49332836bf19de92a5126b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5d45772ed9304ac22cca51417c0d48b0d176d824933feaafbc4a34c50ff8585bbce93a4f423ecadc39ac64aeca5e0e2724556a1407c428a318fa86926a65899
|
|
7
|
+
data.tar.gz: ab16611805c302aeb6fe1930e3502d4330cb00833bd282e2631e9cbb25f6fc179eb66c7e6cd4535a89005cd743cc0db6c3e9eaaaeea0a22c671274e5b6f9b43d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [0.74.1](https://github.com/appydave/appydave-tools/compare/v0.74.0...v0.74.1) (2026-02-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* remove redundant rubocop disable comments blocking CI ([0aa8956](https://github.com/appydave/appydave-tools/commit/0aa89561f229488c01c2a9467c829ac3a8851e72))
|
|
7
|
+
|
|
1
8
|
# [0.74.0](https://github.com/appydave/appydave-tools/compare/v0.73.0...v0.74.0) (2025-12-18)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -241,16 +241,25 @@ module Appydave
|
|
|
241
241
|
|
|
242
242
|
def run_report(args)
|
|
243
243
|
format = format_option(args)
|
|
244
|
+
limit = extract_option(args, '--limit')&.to_i
|
|
245
|
+
skip_unassigned = !args.delete('--include-unassigned')
|
|
244
246
|
report_type = args.shift
|
|
245
247
|
filter = args.first
|
|
246
248
|
|
|
247
249
|
unless report_type
|
|
248
|
-
output.puts 'Usage: jump report <type> [filter]'
|
|
250
|
+
output.puts 'Usage: jump report <type> [filter] [--limit N] [--include-unassigned]'
|
|
249
251
|
output.puts 'Types: categories, brands, clients, types, tags, by-brand, by-client, by-type, by-tag, summary'
|
|
250
252
|
return EXIT_INVALID_INPUT
|
|
251
253
|
end
|
|
252
254
|
|
|
253
|
-
cmd = Commands::Report.new(
|
|
255
|
+
cmd = Commands::Report.new(
|
|
256
|
+
load_config,
|
|
257
|
+
report_type,
|
|
258
|
+
filter: filter,
|
|
259
|
+
limit: limit,
|
|
260
|
+
skip_unassigned: skip_unassigned,
|
|
261
|
+
path_validator: path_validator
|
|
262
|
+
)
|
|
254
263
|
result = cmd.run
|
|
255
264
|
|
|
256
265
|
format_output(result, format)
|
|
@@ -577,7 +586,7 @@ module Appydave
|
|
|
577
586
|
output.puts <<~HELP
|
|
578
587
|
jump report - Generate reports
|
|
579
588
|
|
|
580
|
-
Usage: jump report <type> [filter]
|
|
589
|
+
Usage: jump report <type> [filter] [--limit N] [--include-unassigned]
|
|
581
590
|
|
|
582
591
|
Report Types:
|
|
583
592
|
categories List all category definitions
|
|
@@ -591,9 +600,15 @@ module Appydave
|
|
|
591
600
|
by-tag Group locations by tag
|
|
592
601
|
summary Overview of all data
|
|
593
602
|
|
|
603
|
+
Options:
|
|
604
|
+
--limit N Limit output to top N items/groups
|
|
605
|
+
--include-unassigned Show unassigned groups (hidden by default)
|
|
606
|
+
|
|
594
607
|
Examples:
|
|
595
608
|
jump report brands
|
|
596
|
-
jump report
|
|
609
|
+
jump report tags --limit 20
|
|
610
|
+
jump report by-brand --include-unassigned
|
|
611
|
+
jump report by-client appydave --limit 5
|
|
597
612
|
jump report tags --format json
|
|
598
613
|
HELP
|
|
599
614
|
end
|
|
@@ -12,12 +12,14 @@ module Appydave
|
|
|
12
12
|
summary
|
|
13
13
|
].freeze
|
|
14
14
|
|
|
15
|
-
attr_reader :report_type, :filter
|
|
15
|
+
attr_reader :report_type, :filter, :limit, :skip_unassigned
|
|
16
16
|
|
|
17
|
-
def initialize(config, report_type,
|
|
18
|
-
super(config, path_validator: path_validator, **options)
|
|
17
|
+
def initialize(config, report_type, **options)
|
|
18
|
+
super(config, path_validator: options[:path_validator] || PathValidator.new, **options)
|
|
19
19
|
@report_type = report_type
|
|
20
|
-
@filter = filter
|
|
20
|
+
@filter = options[:filter]
|
|
21
|
+
@limit = options[:limit]
|
|
22
|
+
@skip_unassigned = options.fetch(:skip_unassigned, true)
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def run
|
|
@@ -96,10 +98,15 @@ module Appydave
|
|
|
96
98
|
{ type: type, location_count: count }
|
|
97
99
|
end
|
|
98
100
|
|
|
101
|
+
sorted = types.sort_by { |t| -t[:location_count] }
|
|
102
|
+
limited = limit ? sorted.take(limit) : sorted
|
|
103
|
+
|
|
99
104
|
success_result(
|
|
100
105
|
report: 'types',
|
|
101
|
-
count:
|
|
102
|
-
|
|
106
|
+
count: limited.size,
|
|
107
|
+
total_count: types.size,
|
|
108
|
+
results: limited,
|
|
109
|
+
truncated: limit && types.size > limit
|
|
103
110
|
)
|
|
104
111
|
end
|
|
105
112
|
|
|
@@ -113,37 +120,51 @@ module Appydave
|
|
|
113
120
|
{ tag: tag, location_count: count }
|
|
114
121
|
end
|
|
115
122
|
|
|
123
|
+
sorted = tags.sort_by { |t| -t[:location_count] }
|
|
124
|
+
limited = limit ? sorted.take(limit) : sorted
|
|
125
|
+
|
|
116
126
|
success_result(
|
|
117
127
|
report: 'tags',
|
|
118
|
-
count:
|
|
119
|
-
|
|
128
|
+
count: limited.size,
|
|
129
|
+
total_count: tags.size,
|
|
130
|
+
results: limited,
|
|
131
|
+
truncated: limit && tags.size > limit
|
|
120
132
|
)
|
|
121
133
|
end
|
|
122
134
|
|
|
123
135
|
def report_by_brand
|
|
124
136
|
grouped = group_by_field(:brand, filter)
|
|
137
|
+
grouped = apply_group_filters(grouped)
|
|
125
138
|
success_result(
|
|
126
139
|
report: 'by-brand',
|
|
127
140
|
filter: filter,
|
|
128
|
-
groups: grouped
|
|
141
|
+
groups: grouped,
|
|
142
|
+
limit: limit,
|
|
143
|
+
skip_unassigned: skip_unassigned
|
|
129
144
|
)
|
|
130
145
|
end
|
|
131
146
|
|
|
132
147
|
def report_by_client
|
|
133
148
|
grouped = group_by_field(:client, filter)
|
|
149
|
+
grouped = apply_group_filters(grouped)
|
|
134
150
|
success_result(
|
|
135
151
|
report: 'by-client',
|
|
136
152
|
filter: filter,
|
|
137
|
-
groups: grouped
|
|
153
|
+
groups: grouped,
|
|
154
|
+
limit: limit,
|
|
155
|
+
skip_unassigned: skip_unassigned
|
|
138
156
|
)
|
|
139
157
|
end
|
|
140
158
|
|
|
141
159
|
def report_by_type
|
|
142
160
|
grouped = group_by_field(:type, filter)
|
|
161
|
+
grouped = apply_group_filters(grouped)
|
|
143
162
|
success_result(
|
|
144
163
|
report: 'by-type',
|
|
145
164
|
filter: filter,
|
|
146
|
-
groups: grouped
|
|
165
|
+
groups: grouped,
|
|
166
|
+
limit: limit,
|
|
167
|
+
skip_unassigned: skip_unassigned
|
|
147
168
|
)
|
|
148
169
|
end
|
|
149
170
|
|
|
@@ -158,10 +179,15 @@ module Appydave
|
|
|
158
179
|
end
|
|
159
180
|
end
|
|
160
181
|
|
|
182
|
+
grouped = grouped.sort_by { |_, locs| -locs.size }.to_h
|
|
183
|
+
grouped = apply_group_filters(grouped)
|
|
184
|
+
|
|
161
185
|
success_result(
|
|
162
186
|
report: 'by-tag',
|
|
163
187
|
filter: filter,
|
|
164
|
-
groups: grouped
|
|
188
|
+
groups: grouped,
|
|
189
|
+
limit: limit,
|
|
190
|
+
skip_unassigned: skip_unassigned
|
|
165
191
|
)
|
|
166
192
|
end
|
|
167
193
|
|
|
@@ -207,6 +233,24 @@ module Appydave
|
|
|
207
233
|
description: location.description
|
|
208
234
|
}.compact
|
|
209
235
|
end
|
|
236
|
+
|
|
237
|
+
def apply_group_filters(grouped)
|
|
238
|
+
# Remove unassigned group if skip_unassigned is true
|
|
239
|
+
grouped = grouped.reject { |key, _| key == 'unassigned' } if skip_unassigned
|
|
240
|
+
|
|
241
|
+
# Apply limit to each group (limit items per group)
|
|
242
|
+
if limit
|
|
243
|
+
grouped.transform_values do |locations|
|
|
244
|
+
{
|
|
245
|
+
items: locations.take(limit),
|
|
246
|
+
total: locations.size,
|
|
247
|
+
truncated: locations.size > limit
|
|
248
|
+
}
|
|
249
|
+
end
|
|
250
|
+
else
|
|
251
|
+
grouped
|
|
252
|
+
end
|
|
253
|
+
end
|
|
210
254
|
end
|
|
211
255
|
end
|
|
212
256
|
end
|
|
@@ -26,7 +26,12 @@ module Appydave
|
|
|
26
26
|
def format
|
|
27
27
|
return format_error unless success?
|
|
28
28
|
return format_info if info_result?
|
|
29
|
+
return format_summary if summary_result?
|
|
30
|
+
return format_groups unless groups.empty?
|
|
29
31
|
return format_empty if results.empty?
|
|
32
|
+
return format_definition_report if definition_report?
|
|
33
|
+
return format_count_report if count_report?
|
|
34
|
+
return format_category_report if category_report?
|
|
30
35
|
|
|
31
36
|
format_results
|
|
32
37
|
end
|
|
@@ -41,13 +46,47 @@ module Appydave
|
|
|
41
46
|
end
|
|
42
47
|
|
|
43
48
|
def format_empty
|
|
44
|
-
|
|
49
|
+
message = case data[:report]
|
|
50
|
+
when 'brands'
|
|
51
|
+
'No brands defined in config.'
|
|
52
|
+
when 'clients'
|
|
53
|
+
'No clients defined in config.'
|
|
54
|
+
else
|
|
55
|
+
'No locations found.'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
colorize(message, :yellow)
|
|
45
59
|
end
|
|
46
60
|
|
|
47
61
|
def info_result?
|
|
48
62
|
data.key?(:config_path)
|
|
49
63
|
end
|
|
50
64
|
|
|
65
|
+
def summary_result?
|
|
66
|
+
data.key?(:total_locations) && data.key?(:by_type)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def count_report?
|
|
70
|
+
return false if results.empty?
|
|
71
|
+
|
|
72
|
+
first = results.first
|
|
73
|
+
first.key?(:location_count) && (first.key?(:tag) || first.key?(:type))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def definition_report?
|
|
77
|
+
return false if results.empty?
|
|
78
|
+
|
|
79
|
+
first = results.first
|
|
80
|
+
first.key?(:key) && first.key?(:description) && first.key?(:aliases) && first.key?(:location_count)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def category_report?
|
|
84
|
+
return false if results.empty?
|
|
85
|
+
|
|
86
|
+
first = results.first
|
|
87
|
+
first.key?(:name) && first.key?(:description) && first.key?(:values)
|
|
88
|
+
end
|
|
89
|
+
|
|
51
90
|
def format_info
|
|
52
91
|
[
|
|
53
92
|
format_info_header,
|
|
@@ -84,6 +123,103 @@ module Appydave
|
|
|
84
123
|
]
|
|
85
124
|
end
|
|
86
125
|
|
|
126
|
+
def format_summary
|
|
127
|
+
lines = []
|
|
128
|
+
lines << colorize('Jump Locations Summary', :bold)
|
|
129
|
+
lines << ''
|
|
130
|
+
lines << "#{colorize('Total Locations:', :cyan)} #{data[:total_locations]}"
|
|
131
|
+
lines << ''
|
|
132
|
+
|
|
133
|
+
# By Type
|
|
134
|
+
lines << colorize('By Type:', :bold)
|
|
135
|
+
data[:by_type].sort_by { |_, count| -count }.each do |type, count|
|
|
136
|
+
lines << " #{pad(type, 15)} #{colorize(count.to_s.rjust(3), :green)}"
|
|
137
|
+
end
|
|
138
|
+
lines << ''
|
|
139
|
+
|
|
140
|
+
# By Brand
|
|
141
|
+
lines << colorize('By Brand:', :bold)
|
|
142
|
+
data[:by_brand].sort_by { |_, count| -count }.each do |brand, count|
|
|
143
|
+
lines << " #{pad(brand, 15)} #{colorize(count.to_s.rjust(3), :green)}"
|
|
144
|
+
end
|
|
145
|
+
lines << ''
|
|
146
|
+
|
|
147
|
+
# By Client
|
|
148
|
+
lines << colorize('By Client:', :bold)
|
|
149
|
+
data[:by_client].sort_by { |_, count| -count }.each do |client, count|
|
|
150
|
+
lines << " #{pad(client, 15)} #{colorize(count.to_s.rjust(3), :green)}"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
lines.join("\n")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def format_definition_report
|
|
157
|
+
lines = []
|
|
158
|
+
report_type = data[:report] || 'items'
|
|
159
|
+
|
|
160
|
+
lines << colorize("#{report_type.capitalize} Definitions", :bold)
|
|
161
|
+
lines << header_separator
|
|
162
|
+
lines << ''
|
|
163
|
+
|
|
164
|
+
results.each do |item|
|
|
165
|
+
lines << colorize(item[:key], :cyan)
|
|
166
|
+
lines << " #{item[:description]}" if item[:description]
|
|
167
|
+
lines << " Aliases: #{item[:aliases].join(', ')}" if item[:aliases]&.any?
|
|
168
|
+
lines << " Locations: #{colorize(item[:location_count].to_s, :green)}"
|
|
169
|
+
lines << ''
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
lines << colorize("Total: #{count} #{report_type}", :dim)
|
|
173
|
+
|
|
174
|
+
lines.join("\n")
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def format_count_report
|
|
178
|
+
lines = []
|
|
179
|
+
report_type = data[:report] || 'items'
|
|
180
|
+
|
|
181
|
+
lines << colorize("#{report_type.capitalize} Report", :bold)
|
|
182
|
+
lines << header_separator
|
|
183
|
+
lines << ''
|
|
184
|
+
|
|
185
|
+
results.each do |item|
|
|
186
|
+
name = item[:tag] || item[:type] || 'unknown'
|
|
187
|
+
count = item[:location_count] || 0
|
|
188
|
+
lines << "#{pad(name, 20)} #{colorize(count.to_s.rjust(4), :green)}"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
lines << ''
|
|
192
|
+
|
|
193
|
+
# Show truncation message if data was limited
|
|
194
|
+
if data[:truncated]
|
|
195
|
+
total = data[:total_count] || data[:count]
|
|
196
|
+
shown = results.size
|
|
197
|
+
remaining = total - shown
|
|
198
|
+
lines << colorize("Showing top #{shown} of #{total} (#{remaining} more)", :dim)
|
|
199
|
+
else
|
|
200
|
+
lines << colorize("Total: #{data[:total_count] || count} #{report_type}", :dim)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
lines.join("\n")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def format_category_report
|
|
207
|
+
lines = []
|
|
208
|
+
|
|
209
|
+
lines << colorize('Location Categories', :bold)
|
|
210
|
+
lines << header_separator
|
|
211
|
+
lines << ''
|
|
212
|
+
|
|
213
|
+
results.each do |category|
|
|
214
|
+
lines << colorize(category[:name], :cyan)
|
|
215
|
+
lines << " #{category[:description]}" if category[:description]
|
|
216
|
+
lines << " Values: #{category[:values].join(', ')}" if category[:values]
|
|
217
|
+
lines << ''
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
lines.join("\n")
|
|
221
|
+
end
|
|
222
|
+
|
|
87
223
|
def format_results
|
|
88
224
|
lines = []
|
|
89
225
|
|
|
@@ -103,6 +239,51 @@ module Appydave
|
|
|
103
239
|
lines.join("\n")
|
|
104
240
|
end
|
|
105
241
|
|
|
242
|
+
def format_groups
|
|
243
|
+
lines = []
|
|
244
|
+
total_locations = 0
|
|
245
|
+
total_groups = 0
|
|
246
|
+
|
|
247
|
+
groups.each do |group_name, group_data|
|
|
248
|
+
# Handle both old format (array) and new format (hash with items/total/truncated)
|
|
249
|
+
locations, total_in_group, truncated = if group_data.is_a?(Hash) && group_data.key?(:items)
|
|
250
|
+
[group_data[:items], group_data[:total], group_data[:truncated]]
|
|
251
|
+
else
|
|
252
|
+
[group_data, group_data.length, false]
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
next if locations.empty?
|
|
256
|
+
|
|
257
|
+
# Group header
|
|
258
|
+
lines << ''
|
|
259
|
+
lines << colorize("#{group_name.upcase} (#{total_in_group} location#{'s' unless total_in_group == 1})", :bold)
|
|
260
|
+
lines << header_separator
|
|
261
|
+
|
|
262
|
+
# Add index to each location for display
|
|
263
|
+
locations.each_with_index do |location, idx|
|
|
264
|
+
location[:index] = idx + 1
|
|
265
|
+
lines << format_row(location)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Show truncation message if group was limited
|
|
269
|
+
if truncated
|
|
270
|
+
remaining = total_in_group - locations.length
|
|
271
|
+
lines << colorize(" ... and #{remaining} more", :dim)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
total_locations += total_in_group
|
|
275
|
+
total_groups += 1
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Footer
|
|
279
|
+
lines << ''
|
|
280
|
+
footer = "Total: #{total_locations} location(s) in #{total_groups} group(s)"
|
|
281
|
+
footer += ' (unassigned hidden)' if data[:skip_unassigned]
|
|
282
|
+
lines << colorize(footer, :dim)
|
|
283
|
+
|
|
284
|
+
lines.join("\n")
|
|
285
|
+
end
|
|
286
|
+
|
|
106
287
|
def format_header
|
|
107
288
|
cols = [
|
|
108
289
|
pad('#', 3),
|
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appydave-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.75.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|