visualize_packs 0.5.14 → 0.5.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23b734b878b51ec2da854f99e7f723b5cb00f59e1b2d0712b5ebcd8f0b05d638
4
- data.tar.gz: f7ef0ac5c923a939067c6f0e8ed52dc899f80e60556a4d2469b453d14009e3be
3
+ metadata.gz: a3844051eddac8142057acc5912277e386450da923f96714d7ab2f4b664d75ee
4
+ data.tar.gz: 646315741ca5d8706de1a8397948e231b04295b6513bd4a0cf69d943a546c41b
5
5
  SHA512:
6
- metadata.gz: 0e7f6b1d1ec02ad20d524c2bd3bdb84841c799f4a4782742afd0c1ae310fce4ba90d780ce8d8c98fb15be68ed2d085daf03eb70b6d70870af9bb5bda7b00d80e
7
- data.tar.gz: da4fafcf7b5639a300d2242971d40b2cf0c5b19f05d39941ff6610a0bb99e0d4dc4ad47e93ed503472574e8284af352dc3ead275bfadb6b9c450cfbd0f712790
6
+ metadata.gz: 5d8a1125327c319356a386ef1dfa5efe5fadb94a848d36e465d0a3bebd356f4597bc3db2e67ae35c2c54c7668f968e793dcb11457a1e1fd8f4b7b50bc12d39a8
7
+ data.tar.gz: 0f066a5bf9897d8a5a495ee6f9f6bcc1aacb1ea0e6c00e5422cc8470c6308c5fe9d0b665847c67b0a1d1d8b453362777917cded5395173b812e34638de7526db
data/README.md CHANGED
@@ -19,7 +19,7 @@ find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs
19
19
  If your app is large and has many packages and todos, the above graphs will likely be too big. Try this version to get only the edges to and from the focus package for each diagram:
20
20
 
21
21
  ```
22
- find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --only=% --only-edges-to-focus > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
22
+ find . -iname 'package.yml' | sed 's/\/package.yml//g' | sed 's/\.\///' | xargs -I % sh -c "bundle exec visualize_packs --only=% --focus-pack-edge-mode=inout > %/packs.dot && dot %/packs.dot -Tpng -o %/packs.png"
23
23
  ```
24
24
 
25
25
 
data/bin/visualize_packs CHANGED
@@ -6,43 +6,30 @@ require "optparse"
6
6
  require "ostruct"
7
7
 
8
8
  require_relative '../lib/visualize_packs'
9
- require_relative '../lib/options'
10
9
 
11
10
  options = Options.new
12
11
 
13
- supported_todo_types = %w[
14
- privacy
15
- architecture
16
- visibility
17
- dependency
18
- ].sort.freeze
19
-
20
- def validated_list(o, valid_arguments)
21
- list = o.to_s.split(",").uniq
22
- raise OptionParser::InvalidArgument, o unless (list - valid_arguments).empty?
23
- list
24
- end
25
-
26
12
  OptionParser.new do |opt|
27
13
  opt.on('--no-legend', "Don't show legend") { |o| options.show_legend = false }
14
+
28
15
  opt.on('--no-layers', "Don't show architectural layers") { |o| options.show_layers = false }
29
- opt.on('--no-dependencies', "Don't show accepted dependencies") { |o| options.show_dependencies = false }
30
- opt.on('--no-todos', "Don't show package todos") { |o| options.show_todos = false }
31
- opt.on('--only-todo-types=privacy,architecture,etc', "Show only these types of todos (supported types: #{supported_todo_types.join(', ')})") { |o| options.only_todo_types = validated_list(o, supported_todo_types) }
32
- opt.on('--no-privacy', "Don't show privacy enforcement") { |o| options.show_privacy = false }
16
+
33
17
  opt.on('--no-teams', "Don't show team colors") { |o| options.show_teams = false }
18
+
19
+ opt.on('--no-dependency-arrows', "Don't show accepted dependencies") { |o| options.show_dependencies = false }
34
20
 
35
- opt.on('--focus-folder=FOLDER', "Draw package diagram only for packages in FOLDER. Matches with 'include' for partial matches") { |o| options.focus_folder = o.empty? ? nil : o }
36
- opt.on('--focus-pack=pack1,pack2', "Focus on a specific package(s). Wildcards support: 'packs/*'") { |o| options.focus_pack = o.to_s.split(",") }
37
- opt.on('--only-edges-to-focus=[in,out,inout]', "If focus-pack is set, this shows only the edges into / out of / in and out of the focus node instead of all edges in the focussed graph.") { |o| options.show_only_edges_to_focus_pack = FocusPackEdgeDirection.deserialize(o) }
21
+ opt.on('--no-todo-arrows', "Don't show pack todos") { |o| options.show_todos = false }
22
+ opt.on("--only-todo-types=", "Show only the selected types of todos. Comma-separated list of #{EdgeTodoTypes.values.map &:serialize}") { |o| options.only_todo_types = o.to_s.split(",").uniq.map { EdgeTodoTypes.deserialize(_1) } }
23
+ opt.on('--no-privacy-boxes', "Don't show privacy enforcement box on a pack") { |o| options.show_privacy = false }
38
24
 
39
- opt.on('--roll-nested-into-parent-packs', "Don't show nested packages (not counting root). Connect edges to top-level package instead") { |o| options.roll_nested_into_parent_packs = true }
40
- opt.on('--no-nested-relationships', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
25
+ opt.on('--no-nesting-arrows', "Don't draw relationships between parents and nested packs") { |o| options.show_nested_relationships = false }
26
+ opt.on('--roll-nested-into-parent-packs', "Don't show nested packs (not counting root). Connect edges to top-level pack instead") { |o| options.roll_nested_into_parent_packs = true }
41
27
 
42
- opt.on('--exclude-packs=pack1,pack2,etc', "Exclude listed packs from diagram. If used with include you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.exclude_packs = o.to_s.split(",") }
43
- opt.on('--include-packs=pack1,pack2,etc', "Include only listed packs in diagram. If used with exclude you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.include_packs = o.to_s.split(",") }
28
+ opt.on('--focus-pack=', "Focus on a specific pack(s). Comma-separated list of packs. Wildcards supported: 'packs/*'") { |o| options.focus_pack = o.to_s.split(",") }
29
+ opt.on('--focus-pack-edge-mode=', "If focus-pack is set, this shows only between focussed packs (when set to none) or the edges into / out of / in and out of the focus packs to non-focus packs (which will be re-added to the graph). One of #{FocusPackEdgeDirection.values.map &:serialize}") { |o| options.show_only_edges_to_focus_pack = FocusPackEdgeDirection.deserialize(o) }
30
+ opt.on('--exclude-packs=', "Exclude listed packs from diagram. If used with include you will get all included that are not excluded. Wildcards support: 'packs/ignores/*'") { |o| options.exclude_packs = o.to_s.split(",") }
44
31
 
45
- opt.on('--remote-base-url=PACKAGE', "Link package nodes to an URL (affects graphviz SVG generation)") { |o| options.remote_base_url = o }
32
+ opt.on('--remote-base-url=', "Link pack packs to a URL (affects graphviz SVG generation)") { |o| options.remote_base_url = o }
46
33
 
47
34
  opt.on_tail("-h", "--help", "Show this message") do
48
35
  puts opt
@@ -53,5 +40,5 @@ end.parse!
53
40
  puts VisualizePacks.package_graph!(
54
41
  options,
55
42
  ParsePackwerk::Configuration.fetch.raw,
56
- Packs.all.map { |pack| ParsePackwerk.find(pack.name) }
43
+ Packs.all.map { ParsePackwerk.find(_1.name) }
57
44
  )
data/lib/graph.dot.erb CHANGED
@@ -81,10 +81,7 @@ digraph package_diagram {
81
81
  <%- end -%>
82
82
  <%- if options.show_todos -%>
83
83
  <%- all_packages.each do |package| -%>
84
- <%- filtered_todos = package.violations -%>
85
- <%- if options.only_todo_types.any? -%>
86
- <%- filtered_todos = filtered_todos.select { options.only_todo_types.include?(_1.type) } -%>
87
- <%- end -%>
84
+ <%- filtered_todos = package.violations.select { options.only_todo_types.include?(EdgeTodoTypes.deserialize(_1.type)) } -%>
88
85
  <%- todos_by_package = filtered_todos.group_by(&:to_package_name) -%>
89
86
  <%- todos_by_package.keys.each do |todos_to_package| -%>
90
87
  <%- todo_types = todos_by_package[todos_to_package].group_by(&:type) -%>
@@ -1,8 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
  # typed: strict
3
3
 
4
+ class EdgeTodoTypes < T::Enum
5
+ enums do
6
+ Dependency = new
7
+ Privacy = new
8
+ Architecture = new
9
+ Visibility = new
10
+ end
11
+ end
12
+
4
13
  class FocusPackEdgeDirection < T::Enum
5
14
  enums do
15
+ None = new
16
+ All = new
6
17
  In = new
7
18
  Out = new
8
19
  InOut = new
@@ -16,19 +27,17 @@ class Options < T::Struct
16
27
  prop :show_layers, T::Boolean, default: true
17
28
  prop :show_dependencies, T::Boolean, default: true
18
29
  prop :show_todos, T::Boolean, default: true
19
- prop :only_todo_types, T::Array[String], default: []
30
+ prop :only_todo_types, T::Array[EdgeTodoTypes], default: EdgeTodoTypes.values
20
31
  prop :show_privacy, T::Boolean, default: true
21
32
  prop :show_teams, T::Boolean, default: true
22
33
 
23
- prop :focus_folder, T.nilable(String)
24
34
  prop :focus_pack, T::Array[String], default: []
25
- prop :show_only_edges_to_focus_pack, T.nilable(FocusPackEdgeDirection), default: nil
35
+ prop :show_only_edges_to_focus_pack, FocusPackEdgeDirection, default: FocusPackEdgeDirection::All
26
36
 
27
37
  prop :roll_nested_into_parent_packs, T::Boolean, default: false
28
38
  prop :show_nested_relationships, T::Boolean, default: true
29
39
 
30
40
  prop :exclude_packs, T::Array[String], default: []
31
- prop :include_packs, T.nilable(T::Array[String]), default: nil
32
41
 
33
42
  prop :remote_base_url, T.nilable(String)
34
43
  end
@@ -6,6 +6,8 @@ require 'packs-specification'
6
6
  require 'parse_packwerk'
7
7
  require 'digest/md5'
8
8
 
9
+ require 'visualize_packs/options'
10
+
9
11
  module VisualizePacks
10
12
  extend T::Sig
11
13
 
@@ -55,20 +57,19 @@ module VisualizePacks
55
57
  sig { params(options: Options, max_todo_count: T.nilable(Integer)).returns(String) }
56
58
  def self.diagram_title(options, max_todo_count)
57
59
  app_name = File.basename(Dir.pwd)
58
- focus_edge_info = options.focus_pack.any? && options.show_only_edges_to_focus_pack ? "showing only edges to/from focus pack" : "showing all edges between visible packs"
59
- focus_info = options.focus_pack.any? || options.focus_folder ? "Focus on #{[limited_sentence(options.focus_pack), options.focus_folder].compact.join(' and ')} (#{focus_edge_info})" : "All packs"
60
+ focus_edge_info = options.focus_pack.any? && options.show_only_edges_to_focus_pack != FocusPackEdgeDirection::All ? "showing only edges to/from focus pack" : "showing all edges between visible packs"
61
+ focus_info = options.focus_pack.any? ? "Focus on #{limited_sentence(options.focus_pack)} (#{focus_edge_info})" : "All packs"
60
62
  skipped_info =
61
63
  [
62
64
  options.show_legend ? nil : "hiding legend",
63
65
  options.show_layers ? nil : "hiding layers",
64
66
  options.show_dependencies ? nil : "hiding dependencies",
65
67
  options.show_todos ? nil : "hiding todos",
66
- options.only_todo_types.empty? ? nil : "only #{limited_sentence(options.only_todo_types)} todos",
68
+ EdgeTodoTypes.values.size == options.only_todo_types.size ? nil : "only #{limited_sentence(options.only_todo_types.map &:serialize)} todos",
67
69
  options.show_privacy ? nil : "hiding privacy",
68
70
  options.show_teams ? nil : "hiding teams",
69
71
  options.roll_nested_into_parent_packs ? "hiding nested packs" : nil,
70
72
  options.show_nested_relationships ? nil : "hiding nested relationships",
71
- options.include_packs ? "including only: #{limited_sentence(options.include_packs)}" : nil,
72
73
  options.exclude_packs.empty? ? nil : "excluding pack#{options.exclude_packs.size > 1 ? 's' : ''}: #{limited_sentence(options.exclude_packs)}",
73
74
  ].compact.join(', ').strip
74
75
  main_title = "#{app_name}: #{focus_info}#{skipped_info != '' ? ' - ' + skipped_info : ''}"
@@ -93,25 +94,19 @@ module VisualizePacks
93
94
  sig { params(options: Options, all_package_names: T::Array[String]).returns(T.proc.params(arg0: String, arg1: String).returns(T::Boolean)) }
94
95
  def self.show_edge_builder(options, all_package_names)
95
96
  return lambda do |start_node, end_node|
97
+ all_package_names.include?(start_node) &&
98
+ all_package_names.include?(end_node) &&
96
99
  (
97
- !options.show_only_edges_to_focus_pack &&
98
- all_package_names.include?(start_node) &&
99
- all_package_names.include?(end_node)
100
- ) ||
101
- (
102
- options.show_only_edges_to_focus_pack &&
103
- all_package_names.include?(start_node) &&
104
- all_package_names.include?(end_node) &&
105
- (
106
- case options.show_only_edges_to_focus_pack
107
- when FocusPackEdgeDirection::InOut then
108
- match_packs?(start_node, options.focus_pack) || match_packs?(end_node, options.focus_pack)
109
- when FocusPackEdgeDirection::In then
110
- match_packs?(end_node, options.focus_pack)
111
- when FocusPackEdgeDirection::Out then
112
- match_packs?(start_node, options.focus_pack)
113
- end
114
- )
100
+ case options.show_only_edges_to_focus_pack
101
+ when FocusPackEdgeDirection::All then
102
+ true
103
+ when FocusPackEdgeDirection::InOut then
104
+ match_packs?(start_node, options.focus_pack) || match_packs?(end_node, options.focus_pack)
105
+ when FocusPackEdgeDirection::In then
106
+ match_packs?(end_node, options.focus_pack)
107
+ when FocusPackEdgeDirection::Out then
108
+ match_packs?(start_node, options.focus_pack)
109
+ end
115
110
  )
116
111
  end
117
112
  end
@@ -138,7 +133,7 @@ module VisualizePacks
138
133
  todos_by_package&.keys&.each do |todos_to_package|
139
134
  todo_types = todos_by_package&& todos_by_package[todos_to_package]&.group_by(&:type)
140
135
  todo_types&.keys&.each do |todo_type|
141
- if options.only_todo_types.empty? || options.only_todo_types.include?(todo_type)
136
+ if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo_type))
142
137
  if show_edge.call(package.name, todos_to_package)
143
138
  key = "#{package.name}->#{todos_to_package}:#{todo_type}"
144
139
  todo_counts[key] = todo_types && todo_types[todo_type]&.count
@@ -167,18 +162,18 @@ module VisualizePacks
167
162
  count_delta = todo_count - min_count
168
163
 
169
164
  width_delta = count_delta / todo_range.to_f * width_range
165
+ width_delta = 0 if width_delta.nan?
166
+
170
167
  edge_width = min_width + width_delta
171
168
  edge_width.round(2)
172
- end
169
+ end
173
170
 
174
- sig { params(packages: T::Array[ParsePackwerk::Package], options: Options).returns(T::Array[ParsePackwerk::Package]) }
175
- def self.filtered(packages, options)
171
+ sig { params(packages: T::Array[ParsePackwerk::Package], options: Options).returns(T::Array[ParsePackwerk::Package]) }
172
+ def self.filtered(packages, options)
176
173
  focus_pack = options.focus_pack
177
- focus_folder = options.focus_folder
178
- include_packs = options.include_packs
179
174
  exclude_packs = options.exclude_packs
180
175
 
181
- return packages unless focus_pack.any? || focus_folder || include_packs || exclude_packs.any?
176
+ return packages unless focus_pack.any? || exclude_packs.any?
182
177
 
183
178
  nested_packages = all_nested_packages(packages.map { |p| p.name })
184
179
 
@@ -196,10 +191,10 @@ module VisualizePacks
196
191
  if options.show_dependencies
197
192
  result += packages.select { |p| p.dependencies.any? { |d| match_packs?(d, focus_pack) }}.map { |pack| pack.name }
198
193
  end
199
- if options.show_todos && [nil, FocusPackEdgeDirection::In, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
194
+ if options.show_todos && [FocusPackEdgeDirection::All, FocusPackEdgeDirection::In, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
200
195
  result += packages.select do
201
196
  |p| (p.violations || []).inject([]) do |res, todo|
202
- res << todo.to_package_name if options.only_todo_types.empty? || options.only_todo_types.include?(todo.type)
197
+ res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
203
198
  res
204
199
  end.any? { |v| match_packs?(v, focus_pack) }
205
200
  end.map { |pack| pack.name }
@@ -208,9 +203,9 @@ module VisualizePacks
208
203
  if options.show_dependencies
209
204
  result += packages_by_name[p].dependencies
210
205
  end
211
- if options.show_todos && [nil, FocusPackEdgeDirection::Out, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
206
+ if options.show_todos && [FocusPackEdgeDirection::All, FocusPackEdgeDirection::Out, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
212
207
  result += (packages_by_name[p].violations || []).inject([]) do |res, todo|
213
- res << todo.to_package_name if options.only_todo_types.empty? || options.only_todo_types.include?(todo.type)
208
+ res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
214
209
  res
215
210
  end
216
211
  end
@@ -223,14 +218,6 @@ module VisualizePacks
223
218
  result = (result + parent_packs).uniq.compact
224
219
  end
225
220
 
226
- if focus_folder
227
- result = result.select { |p| p.include? focus_folder }
228
- end
229
-
230
- if include_packs
231
- result = result.select { |p| match_packs?(p, include_packs) }
232
- end
233
-
234
221
  if exclude_packs.any?
235
222
  result = result.reject { |p| match_packs?(p, exclude_packs) }
236
223
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visualize_packs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.14
4
+ version: 0.5.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-03 00:00:00.000000000 Z
11
+ date: 2023-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,8 +120,8 @@ files:
120
120
  - bin/tapioca
121
121
  - bin/visualize_packs
122
122
  - lib/graph.dot.erb
123
- - lib/options.rb
124
123
  - lib/visualize_packs.rb
124
+ - lib/visualize_packs/options.rb
125
125
  homepage: https://github.com/rubyatscale/visualize_packs
126
126
  licenses:
127
127
  - MIT