visualize_packs 0.5.18 → 0.5.20

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: 3c493faea12dcf090c4823910d9ecdcfc7da5eca6e370732caa2e063a832a704
4
- data.tar.gz: 80b1906deaf843d82c4b317f15234e0ec023fe5fc66efcb865bf94f519101c92
3
+ metadata.gz: b8efefa896a6d002c7333dad53f2a8fa0be10d8c0004895682239c7a7f6a1105
4
+ data.tar.gz: 0046a3a518c25de488b4b2e0d89c04ced6e45c1ff5d90e9e85d71d46b5256e89
5
5
  SHA512:
6
- metadata.gz: dab454f3ae4f6dac67e0027417bd996640fc85ab6ac397690051fd77c8a66aeb86175b86c4df39f18027a55d516f1f0b12f587fe090f2788991e6d927511dce0
7
- data.tar.gz: 9d1fbc976c03a3540dd6f385193d7cd95e0b97a3f1c2fa6261000204a78924f280718b63568d8f510afd76f33d96db29a63984faeb6255e3ad971905948b6f70
6
+ metadata.gz: 5282d8a1af4103a3d6c38675c378adee512029eb4320a29874b91463c2fc4aa7380a76165306f8dc2d8163b67e60875b2496aeacca209b40ebdb09217744888c
7
+ data.tar.gz: 99f84713ec95080f82668184bd69ce4e67dc30fbc739803f67efe8ebbe51728dbd4717d22eec946a2e24ce1128cd646d3cca47413a09a481718b76c029c47ae7
data/bin/visualize_packs CHANGED
@@ -34,6 +34,13 @@ OptionParser.new do |opt|
34
34
 
35
35
  opt.on('--title=STRING', "Set a custom diagram title") { |o| options.title = o }
36
36
 
37
+ opt.on('-V', '--version', "Show version") do
38
+ spec_path = File.expand_path("../visualize_packs.gemspec", __dir__)
39
+ spec = Gem::Specification::load(spec_path)
40
+ puts "Version #{spec.version}"
41
+ exit
42
+ end
43
+
37
44
  opt.on_tail("-h", "--help", "Show this message") do
38
45
  puts opt
39
46
  exit
data/lib/graph.dot.erb CHANGED
@@ -87,19 +87,19 @@ digraph package_diagram {
87
87
  <%- todo_types = todos_by_package[todos_to_package].group_by(&:type) -%>
88
88
  <%- todo_types.keys.each do |todo_type| -%>
89
89
  <%- if show_edge.call(package.name, todos_to_package) -%>
90
- "<%= package.name -%>" -> "<%= todos_to_package -%>"<%= todo_type == 'privacy' ? ':private' : '' -%> [ color=darkred style=dashed
90
+ "<%= package.name -%>" -> "<%= todos_to_package -%>"<%= todo_type == 'privacy' ? ':private' : '' -%> [
91
91
  <%- if !options.use_todos_for_layout -%>
92
92
  constraint=false
93
93
  <%- end -%>
94
94
  # headlabel="<%= todo_type -%>"
95
95
  <%- if todo_type == 'privacy' -%>
96
- arrowhead=crow
96
+ <%= VisualizePacks::ArrowHead::PrivacyTodo.serialize %>
97
97
  <%- elsif todo_type == 'architecture' -%>
98
- arrowhead=invodot
98
+ <%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>
99
99
  <%- elsif todo_type == 'visibility' -%>
100
- arrowhead=obox
100
+ <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>
101
101
  <%- elsif todo_type == 'dependency' -%>
102
- arrowhead=odot
102
+ <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>
103
103
  <%- end -%>
104
104
  penwidth=<%= todo_edge_width(todo_types[todo_type].count, max_todo_count) -%>
105
105
  ]
@@ -128,30 +128,46 @@ digraph package_diagram {
128
128
  subgraph cluster_legend {
129
129
  fontsize=16
130
130
  label="Edges Styles and Arrow Heads"
131
+ <%- if options.show_dependencies -%>
131
132
  A [ fontsize=12 shape=box label="package"]
132
133
  B [ fontsize=12 shape=box label="package"]
134
+ A -> B [label="accepted dependency" <%= VisualizePacks::ArrowHead::ConfiguredDependency.serialize %>]
135
+ <%- end -%>
136
+ <%- if options.show_nested_relationships -%>
133
137
  K [ fontsize=12 shape=box label="package"]
134
138
  L [ fontsize=12 shape=box label="package"]
139
+ K -> L [label="nested package" <%= VisualizePacks::ArrowHead::ConfiguredNested.serialize %>]
140
+ <%- end -%>
141
+ <%- if options.show_visibility -%>
135
142
  M [ fontsize=12 shape=box label="package"]
136
143
  N [ fontsize=12 shape=box label="package"]
137
-
144
+ M -> N [label="visibile to" <%= VisualizePacks::ArrowHead::ConfiguredVisibileTo.serialize %>]
145
+ <%- end -%>
146
+ <%- if options.show_todos -%>
147
+ <%- if options.only_todo_types.include?(EdgeTodoTypes::Privacy) -%>
138
148
  C [ fontsize=12 shape=box label="package"]
139
149
  D [ fontsize=12 shape=box label="package"]
150
+ C -> D [label="privacy todo" <%= VisualizePacks::ArrowHead::PrivacyTodo.serialize %>]
151
+ <%- end -%>
152
+ <%- if options.only_todo_types.include?(EdgeTodoTypes::Architecture) -%>
140
153
  E [ fontsize=12 shape=box label="package"]
141
154
  F [ fontsize=12 shape=box label="package"]
155
+ E -> F [label="architecture todo" <%= VisualizePacks::ArrowHead::ArchitectureTodo.serialize %>]
156
+ <%- end -%>
157
+ <%- if options.only_todo_types.include?(EdgeTodoTypes::Visibility) -%>
142
158
  G [ fontsize=12 shape=box label="package"]
143
159
  H [ fontsize=12 shape=box label="package"]
160
+ G -> H [label="visibility todo" <%= VisualizePacks::ArrowHead::VisibilityTodo.serialize %>]
161
+ <%- end -%>
162
+ <%- if options.only_todo_types.include?(EdgeTodoTypes::Dependency) -%>
144
163
  I [ fontsize=12 shape=box label="package"]
145
164
  J [ fontsize=12 shape=box label="package"]
146
-
147
- A -> B [label="accepted dependency" color=darkgreen]
148
- K -> L [label="nested package" color=purple]
149
- M -> N [label="visibile to" color=darkgreen]
150
-
151
- C -> D [label="privacy todo" color=darkred style=dashed arrowhead=crow]
152
- E -> F [label="architecture todo" color=darkred style=dashed arrowhead=invodot]
153
- G -> H [label="visibility todo" color=darkred style=dashed arrowhead=obox]
154
- I -> J [label="dependency todo" color=darkred style=dashed arrowhead=odot]
165
+ I -> J [label="dependency todo" <%= VisualizePacks::ArrowHead::DependencyTodo.serialize %>]
166
+ <%- end -%>
167
+ <%- end -%>
168
+ LEGEND_NODE_1 [ label="" peripheries=0 height=0 width=0 style=invis ]
169
+ LEGEND_NODE_2 [ label="" peripheries=0 height=0 width=0 style=invis ]
170
+ LEGEND_NODE_1 -> LEGEND_NODE_2 [ style=invis ]
155
171
  }
156
172
  <%- end -%>
157
173
  <%- if options.show_teams && all_team_names != [] -%>
@@ -172,7 +188,7 @@ digraph package_diagram {
172
188
  <%- end -%>
173
189
  }
174
190
  <%- if options.show_legend -%>
175
- J -> "<%= all_team_names.last %><%= all_team_names.last %>" [style=invis]
191
+ LEGEND_NODE_2 -> "<%= all_team_names.last %><%= all_team_names.last %>" [style=invis]
176
192
  <%- end -%>
177
193
  <%- end -%>
178
194
  }
@@ -11,6 +11,18 @@ require 'visualize_packs/options'
11
11
  module VisualizePacks
12
12
  extend T::Sig
13
13
 
14
+ class ArrowHead < T::Enum
15
+ enums do
16
+ DependencyTodo = new('color=darkred style=dashed arrowhead=odiamond')
17
+ PrivacyTodo = new('color=darkred style=dashed arrowhead=crow')
18
+ ArchitectureTodo = new('color=darkred style=dashed arrowhead=obox')
19
+ VisibilityTodo = new('color=darkred style=dashed arrowhead=tee')
20
+ ConfiguredDependency = new('color=darkgreen')
21
+ ConfiguredVisibileTo = new('color=blue')
22
+ ConfiguredNested = new('color=purple')
23
+ end
24
+ end
25
+
14
26
  sig { params(options: Options, raw_config: T::Hash[String, T.untyped], packages: T::Array[ParsePackwerk::Package]).returns(String) }
15
27
  def self.package_graph!(options, raw_config, packages)
16
28
  all_packages = filtered(packages, options).compact.sort_by {|x| x.name }
@@ -58,25 +70,31 @@ module VisualizePacks
58
70
  def self.diagram_title(options, max_todo_count)
59
71
  return "<<b>#{options.title}</b>>" if options.title
60
72
 
61
- app_name = File.basename(Dir.pwd)
62
- focus_edge_info = options.focus_pack && options.show_only_edges_to_focus_pack != FocusPackEdgeDirection::All ? "showing only edges to/from focus pack" : "showing all edges between visible packs"
63
- focus_info = options.focus_pack ? "Focus on #{limited_sentence(options.focus_pack)} (#{focus_edge_info})" : "All packs"
64
- skipped_info =
65
- [
66
- options.show_legend ? nil : "hiding legend",
67
- options.show_layers ? nil : "hiding layers",
68
- options.show_dependencies ? nil : "hiding dependencies",
69
- options.show_todos ? nil : "hiding todos",
70
- EdgeTodoTypes.values.size == options.only_todo_types.size ? nil : "only #{limited_sentence(options.only_todo_types.map &:serialize)} todos",
71
- options.show_privacy ? nil : "hiding privacy",
72
- options.show_teams ? nil : "hiding teams",
73
- options.show_visibility ? nil : "hiding visibility",
74
- options.roll_nested_into_parent_packs ? "hiding nested packs" : nil,
75
- options.show_nested_relationships ? nil : "hiding nested relationships",
76
- options.exclude_packs.empty? ? nil : "excluding pack#{options.exclude_packs.size > 1 ? 's' : ''}: #{limited_sentence(options.exclude_packs)}",
73
+ focus_info = if options.focus_pack
74
+ "Focus on #{limited_sentence(options.focus_pack)} (Edge mode: #{options.show_only_edges_to_focus_pack.serialize})"
75
+ else
76
+ "All packs"
77
+ end
78
+
79
+ hidden_aspects = [
80
+ options.show_legend ? nil : "legend",
81
+ options.show_layers ? nil : "layers",
82
+ options.show_dependencies ? nil : "dependencies",
83
+ options.show_todos ? nil : "todos",
84
+ options.show_privacy ? nil : "privacy",
85
+ options.show_teams ? nil : "teams",
86
+ options.show_visibility ? nil : "visibility",
87
+ options.roll_nested_into_parent_packs ? "nested packs" : nil,
88
+ options.show_nested_relationships ? nil : "nested relationships",
77
89
  ].compact.join(', ').strip
78
- main_title = "#{app_name}: #{focus_info}#{skipped_info != '' ? ' - ' + skipped_info : ''}"
79
- sub_title = ""
90
+ hidden_aspects_title = hidden_aspects != '' ? "Hiding #{hidden_aspects}" : nil
91
+
92
+ todo_types = EdgeTodoTypes.values.size == options.only_todo_types.size ? nil : "Only #{options.only_todo_types.map &:serialize} todos",
93
+
94
+ exclusions = options.exclude_packs.empty? ? nil : "Excluding pack#{options.exclude_packs.size > 1 ? 's' : ''}: #{limited_sentence(options.exclude_packs)}",
95
+
96
+ main_title = [focus_info, hidden_aspects_title, todo_types, exclusions].compact.join('. ')
97
+
80
98
  if options.show_todos && max_todo_count
81
99
  sub_title = "<br/><font point-size='12'>Widest todo edge is #{max_todo_count} todo#{max_todo_count > 1 ? 's' : ''}</font>"
82
100
  end
@@ -103,6 +121,8 @@ module VisualizePacks
103
121
  case options.show_only_edges_to_focus_pack
104
122
  when FocusPackEdgeDirection::All then
105
123
  true
124
+ when FocusPackEdgeDirection::None then
125
+ match_packs?(start_node, options.focus_pack) && match_packs?(end_node, options.focus_pack)
106
126
  when FocusPackEdgeDirection::InOut then
107
127
  match_packs?(start_node, options.focus_pack) || match_packs?(end_node, options.focus_pack)
108
128
  when FocusPackEdgeDirection::In then
@@ -188,36 +208,32 @@ module VisualizePacks
188
208
  result = T.let([], T::Array[T.nilable(String)])
189
209
  result = packages.map { |pack| pack.name }
190
210
 
191
- if focus_pack && !focus_pack.empty?
211
+ if focus_pack
192
212
  result = []
193
- result += packages.map { |pack| pack.name }.select { |p| match_packs?(p, focus_pack) }
194
- if options.show_dependencies
195
- result += packages.select { |p| p.dependencies.any? { |d| match_packs?(d, focus_pack) }}.map { |pack| pack.name }
196
- end
197
- if options.show_todos && [FocusPackEdgeDirection::All, FocusPackEdgeDirection::In, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
198
- result += packages.select do
199
- |p| (p.violations || []).inject([]) do |res, todo|
200
- res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
201
- res
202
- end.any? { |v| match_packs?(v, focus_pack) }
203
- end.map { |pack| pack.name }
213
+ focus_pack_name = packages.map { |pack| pack.name }.select { |p| match_packs?(p, focus_pack) }
214
+ result += focus_pack_name
215
+
216
+ dependents = options.show_dependencies ? dependents_on(packages, focus_pack_name) : []
217
+ dependencies = options.show_dependencies ? dependencies_of(packages, focus_pack_name) : []
218
+ todos_out = options.show_todos ? todos_out(packages, focus_pack_name, options) : []
219
+ todos_in = options.show_todos ? todos_in(packages, focus_pack_name, options) : []
220
+
221
+ case options.show_only_edges_to_focus_pack
222
+ when FocusPackEdgeDirection::All, FocusPackEdgeDirection::InOut then
223
+ result += dependents + dependencies + todos_out + todos_in
224
+ when FocusPackEdgeDirection::In then
225
+ result += dependents + todos_in
226
+ when FocusPackEdgeDirection::Out then
227
+ result += dependencies + todos_out
228
+ when FocusPackEdgeDirection::None then
229
+ # nothing to do
204
230
  end
205
- packages.map { |pack| pack.name }.select { |p| match_packs?(p, focus_pack) }.each do |p|
206
- if options.show_dependencies
207
- result += packages_by_name[p].dependencies
208
- end
209
- if options.show_todos && [FocusPackEdgeDirection::All, FocusPackEdgeDirection::Out, FocusPackEdgeDirection::InOut].include?(options.show_only_edges_to_focus_pack)
210
- result += (packages_by_name[p].violations || []).inject([]) do |res, todo|
211
- res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
212
- res
213
- end
214
- end
215
- end
216
- result = result.uniq
231
+
217
232
  parent_packs = result.inject([]) do |res, package_name|
218
233
  res << nested_packages[package_name]
219
234
  res
220
235
  end
236
+
221
237
  result = (result + parent_packs).uniq.compact
222
238
  end
223
239
 
@@ -306,4 +322,39 @@ module VisualizePacks
306
322
  def self.match_packs?(pack, packs_name_with_wildcards)
307
323
  !packs_name_with_wildcards || packs_name_with_wildcards.any? {|p| File.fnmatch(p, pack)}
308
324
  end
325
+
326
+ sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String]).returns(T::Array[String]) }
327
+ def self.dependencies_of(all_packages, focus_packs_names)
328
+ focus_packs = all_packages.select { focus_packs_names.include?(_1.name)}
329
+
330
+ focus_packs.inject([]) do |result, pack|
331
+ result += pack.dependencies
332
+ result
333
+ end.uniq
334
+ end
335
+
336
+ sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String]).returns(T::Array[String]) }
337
+ def self.dependents_on(all_packages, focus_packs_names)
338
+ all_packages.select { |pack| pack.dependencies.any? { focus_packs_names.include?(_1) }}.map &:name
339
+ end
340
+
341
+ sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String], options: Options).returns(T::Array[String]) }
342
+ def self.todos_in(all_packages, focus_packs_names, options)
343
+ all_packages.select do |p|
344
+ (p.violations || []).inject([]) do |res, todo|
345
+ res << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
346
+ res
347
+ end.any? { |v| focus_packs_names.include?(v) }
348
+ end.map { |pack| pack.name }
349
+ end
350
+
351
+ sig { params(all_packages: T::Array[ParsePackwerk::Package], focus_packs_names: T::Array[String], options: Options).returns(T::Array[String]) }
352
+ def self.todos_out(all_packages, focus_packs_names, options)
353
+ all_packages.inject([]) do |result, p|
354
+ focus_packs_names.include?(p.name) && (p.violations || []).each do |todo|
355
+ result << todo.to_package_name if options.only_todo_types.include?(EdgeTodoTypes.deserialize(todo.type))
356
+ end
357
+ result
358
+ end
359
+ end
309
360
  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.18
4
+ version: 0.5.20
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-08 00:00:00.000000000 Z
11
+ date: 2023-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler