packwerk-extensions 0.3.0 → 0.4.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: ec06b679c031e028a1dca4bb93e0cac394f13a3af2e86a19892efcf5e26ce6fe
4
- data.tar.gz: 98835c87573ac3b47f13a50c9de8e9af6370c7f88debf12a24578e0040d87324
3
+ metadata.gz: 10da1ea58224fce898e99dd53a7775dd59cb3714a13a0940cc3a3d42a17fe6ab
4
+ data.tar.gz: 6cfb154342f96cc03bab150f6fbc16839014d368e25553a7d46a4915ce36a334
5
5
  SHA512:
6
- metadata.gz: 6e37b7e13b22e77dc428a3d3bd210a6dea8c5eddbac5baf9c0ce31ae207b6b5e9bcfdf0cb9c3a1c041524c20a4a3f0a0affb9d08e90f105d78b28746b67ae7d5
7
- data.tar.gz: ff5c5b5d73118ac391a086c13edb8733f0b682e4c87e404e4aaa3a5fc7e7736b655a1ed15e18e059758e854fa895cedb67d81eb93889d7767ad16a778b300d82
6
+ metadata.gz: 2abe25b9dedf146e0483a99365a454a98844b464f3af2d61cdc1b6b9a688bc889c9823f3b0170ef03552f4d6ef13019144964506915a614babf1e4b474112f3c
7
+ data.tar.gz: 27fd29f382047cda7bcf8c8c457053ec83015aca2b286189cab26464cab1bce186fcdd8bbf50b491d3c8e19d79dd187a4ab8e2dab3ea95197bd1aeca7ab66bd5
data/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  Currently, it ships the following checkers to help improve the boundaries between packages. These checkers are:
6
6
  - A `privacy` checker that ensures other packages are using your package's public API
7
7
  - A `visibility` checker that allows packages to be private except to an explicit group of other packages.
8
- - A `folder_privacy` checker that allows packages to their sibling packs and parent pack (to be used in an application that uses folder packs)
9
- - A `layer` (formerly `architecture`) checker that allows packages to specify their "layer" and requires that each layer only communicate with layers below it.
8
+ - A `folder_privacy` checker that allows packages to be private to their sibling packs and parent pack (to be used in an application that uses folder packs)
9
+ - A `layer` (formerly `architecture`) checker that allows packages to specify their "layer" and ensures they cannot use packages from higher layers
10
10
 
11
11
  ## Installation
12
12
 
@@ -63,7 +63,7 @@ public_path: my/custom/path/
63
63
  ### Defining public constants through sigil
64
64
 
65
65
  > [!WARNING]
66
- > This way of of defining the public API of a package should be considered WIP. It is not supported by all tooling in the RubyAtScale ecosystem, as @alexevanczuk pointed out in a [comment on the PR](https://github.com/rubyatscale/packwerk-extensions/pull/35#discussion_r1334331797):
66
+ > This way of defining the public API of a package should be considered WIP. It is not supported by all tooling in the RubyAtScale ecosystem, as @alexevanczuk pointed out in a [comment on the PR](https://github.com/rubyatscale/packwerk-extensions/pull/35#discussion_r1334331797):
67
67
  >
68
68
  > There are a couple of other places that will require changes related to this sigil. Namely, everything that is coupled to the public folder implementation of privacy.
69
69
  >
@@ -195,12 +195,15 @@ packs/c VIOLATION
195
195
  ```
196
196
 
197
197
  ## Layer Checker
198
- The layer checker can be used to enforce constraints on what can depend on what.
198
+ The layer checker can be used to define layers and then enforce constraints on the dependencies that packages can have.
199
+ Dependencies are only allowed to packages in or below the same layer.
199
200
 
200
201
  To enforce layers for your package, first define the `layers` in `packwerk.yml`, for example:
202
+
201
203
  ```
202
204
  layers:
203
- - package
205
+ - feature
206
+ - core
204
207
  - utility
205
208
  ```
206
209
 
@@ -208,10 +211,10 @@ Then, turn on the checker in your package:
208
211
  ```yaml
209
212
  # components/merchandising/package.yml
210
213
  enforce_layers: true
211
- layer: utility
214
+ layer: core
212
215
  ```
213
216
 
214
- Now this pack can only depend on other utility packages.
217
+ Now this pack can only depend on other packages from the `core` or `utility` layers. It cannot depend on packages from the higher `feature` layer.
215
218
 
216
219
  ### Deprecated Architecture Checker
217
220
  The "Layer Checker" was formerly named "Architecture Checker". The associated keys were:
@@ -7,21 +7,18 @@ require 'packwerk/folder_privacy/validator'
7
7
  module Packwerk
8
8
  module FolderPrivacy
9
9
  class Checker
10
- extend T::Sig
11
10
  include Packwerk::Checker
12
11
 
13
- VIOLATION_TYPE = T.let('folder_privacy', String)
12
+ VIOLATION_TYPE = 'folder_privacy'
14
13
 
15
- sig { override.returns(String) }
14
+ # @override
15
+ #: -> String
16
16
  def violation_type
17
17
  VIOLATION_TYPE
18
18
  end
19
19
 
20
- sig do
21
- override
22
- .params(reference: Packwerk::Reference)
23
- .returns(T::Boolean)
24
- end
20
+ # @override
21
+ #: (Packwerk::Reference reference) -> bool
25
22
  def invalid_reference?(reference)
26
23
  referencing_package = reference.package
27
24
  referenced_package = reference.constant.package
@@ -41,21 +38,15 @@ module Packwerk
41
38
  true
42
39
  end
43
40
 
44
- sig do
45
- override
46
- .params(listed_offense: Packwerk::ReferenceOffense)
47
- .returns(T::Boolean)
48
- end
41
+ # @override
42
+ #: (Packwerk::ReferenceOffense listed_offense) -> bool
49
43
  def strict_mode_violation?(listed_offense)
50
44
  publishing_package = listed_offense.reference.constant.package
51
45
  publishing_package.config['enforce_folder_privacy'] == 'strict'
52
46
  end
53
47
 
54
- sig do
55
- override
56
- .params(reference: Packwerk::Reference)
57
- .returns(String)
58
- end
48
+ # @override
49
+ #: (Packwerk::Reference reference) -> String
59
50
  def message(reference)
60
51
  source_desc = "'#{reference.package}'"
61
52
 
@@ -71,15 +62,12 @@ module Packwerk
71
62
 
72
63
  private
73
64
 
74
- sig do
75
- params(visibility_option: T.nilable(T.any(T::Boolean, String)))
76
- .returns(T::Boolean)
77
- end
65
+ #: ((bool | String)? visibility_option) -> bool
78
66
  def enforcement_disabled?(visibility_option)
79
67
  [false, nil].include?(visibility_option)
80
68
  end
81
69
 
82
- sig { params(reference: Reference).returns(String) }
70
+ #: (Reference reference) -> String
83
71
  def standard_help_message(reference)
84
72
  standard_message = <<~MESSAGE.chomp
85
73
  Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
@@ -3,15 +3,17 @@
3
3
 
4
4
  module Packwerk
5
5
  module FolderPrivacy
6
- class Package < T::Struct
7
- extend T::Sig
6
+ class Package
7
+ #: (bool | String)?
8
+ attr_reader :enforce_folder_privacy
8
9
 
9
- const :enforce_folder_privacy, T.nilable(T.any(T::Boolean, String))
10
+ #: (enforce_folder_privacy: (bool | String)?) -> void
11
+ def initialize(enforce_folder_privacy:)
12
+ @enforce_folder_privacy = enforce_folder_privacy
13
+ end
10
14
 
11
15
  class << self
12
- extend T::Sig
13
-
14
- sig { params(package: ::Packwerk::Package).returns(Package) }
16
+ #: (::Packwerk::Package package) -> Package
15
17
  def from(package)
16
18
  Package.new(
17
19
  enforce_folder_privacy: package.config['enforce_folder_privacy']
@@ -4,14 +4,14 @@
4
4
  module Packwerk
5
5
  module FolderPrivacy
6
6
  class Validator
7
- extend T::Sig
8
7
  include Packwerk::Validator
9
8
 
10
9
  Result = Packwerk::Validator::Result
11
10
 
12
- sig { override.params(package_set: PackageSet, configuration: Configuration).returns(Result) }
11
+ # @override
12
+ #: (PackageSet package_set, Configuration configuration) -> Result
13
13
  def call(package_set, configuration)
14
- results = T.let([], T::Array[Result])
14
+ results = [] #: Array[Result]
15
15
 
16
16
  package_manifests_settings_for(configuration, 'enforce_folder_privacy').each do |config, setting|
17
17
  next if setting.nil?
@@ -27,9 +27,10 @@ module Packwerk
27
27
  merge_results(results, separator: "\n---\n")
28
28
  end
29
29
 
30
- sig { override.returns(T::Array[String]) }
30
+ # @override
31
+ #: -> Array[String]
31
32
  def permitted_keys
32
- %w[enforce_folder_privacy]
33
+ %w(enforce_folder_privacy)
33
34
  end
34
35
  end
35
36
  end
@@ -28,45 +28,31 @@ module Packwerk
28
28
  # C) A potential sequencing for modularizing a system (starting with lower layers first).
29
29
  #
30
30
  class Checker
31
- extend T::Sig
32
31
  include Packwerk::Checker
33
32
 
34
- sig { void }
35
- def initialize
36
- @violation_type = T.let(@violation_type, T.nilable(String))
37
- end
38
-
39
- sig { override.returns(String) }
33
+ # @override
34
+ #: -> String
40
35
  def violation_type
41
- @violation_type ||= layer_config.violation_key
36
+ @violation_type ||= layer_config.violation_key #: String?
42
37
  end
43
38
 
44
- sig do
45
- override
46
- .params(reference: Packwerk::Reference)
47
- .returns(T::Boolean)
48
- end
39
+ # @override
40
+ #: (Packwerk::Reference reference) -> bool
49
41
  def invalid_reference?(reference)
50
42
  constant_package = Package.from(reference.constant.package, layers)
51
43
  referencing_package = Package.from(reference.package, layers)
52
- !referencing_package.can_depend_on?(constant_package, layers: layers)
44
+ !referencing_package.can_depend_on?(constant_package, layers:)
53
45
  end
54
46
 
55
- sig do
56
- override
57
- .params(listed_offense: Packwerk::ReferenceOffense)
58
- .returns(T::Boolean)
59
- end
47
+ # @override
48
+ #: (Packwerk::ReferenceOffense listed_offense) -> bool
60
49
  def strict_mode_violation?(listed_offense)
61
50
  constant_package = listed_offense.reference.package
62
51
  constant_package.config[layer_config.enforce_key] == 'strict'
63
52
  end
64
53
 
65
- sig do
66
- override
67
- .params(reference: Packwerk::Reference)
68
- .returns(String)
69
- end
54
+ # @override
55
+ #: (Packwerk::Reference reference) -> String
70
56
  def message(reference)
71
57
  constant_package = Package.from(reference.constant.package, layers)
72
58
  referencing_package = Package.from(reference.package, layers)
@@ -84,7 +70,7 @@ module Packwerk
84
70
  end
85
71
 
86
72
  # TODO: Extract this out into a common helper, can call it StandardViolationHelpMessage.new(...) and implements .to_s
87
- sig { params(reference: Reference).returns(String) }
73
+ #: (Reference reference) -> String
88
74
  def standard_help_message(reference)
89
75
  standard_message = <<~MESSAGE.chomp
90
76
  Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
@@ -94,14 +80,14 @@ module Packwerk
94
80
  standard_message.chomp
95
81
  end
96
82
 
97
- sig { returns(Layers) }
83
+ #: -> Layers
98
84
  def layers
99
- @layers ||= T.let(Layers.new, T.nilable(Packwerk::Layer::Layers))
85
+ @layers ||= Layers.new #: Packwerk::Layer::Layers?
100
86
  end
101
87
 
102
- sig { returns(Config) }
88
+ #: -> Config
103
89
  def layer_config
104
- @layer_config ||= T.let(Config.new, T.nilable(Config))
90
+ @layer_config ||= Config.new #: Config?
105
91
  end
106
92
  end
107
93
  end
@@ -4,40 +4,32 @@
4
4
  module Packwerk
5
5
  module Layer
6
6
  class Config
7
- extend T::Sig
7
+ ARCHITECTURE_VIOLATION_TYPE = 'architecture'
8
+ ARCHITECTURE_ENFORCE = 'enforce_architecture'
9
+ LAYER_VIOLATION_TYPE = 'layer'
10
+ LAYER_ENFORCE = 'enforce_layers'
8
11
 
9
- ARCHITECTURE_VIOLATION_TYPE = T.let('architecture', String)
10
- ARCHITECTURE_ENFORCE = T.let('enforce_architecture', String)
11
- LAYER_VIOLATION_TYPE = T.let('layer', String)
12
- LAYER_ENFORCE = T.let('enforce_layers', String)
13
-
14
- sig { void }
15
- def initialize
16
- @layers_key_configured = T.let(@layers_key_configured, T.nilable(T::Boolean))
17
- @layers_list = T.let(@layers_list, T.nilable(T::Array[String]))
18
- end
19
-
20
- sig { returns(T::Array[String]) }
12
+ #: -> Array[String]
21
13
  def layers_list
22
- @layers_list ||= YAML.load_file('packwerk.yml')[layers_key] || []
14
+ @layers_list ||= YAML.load_file('packwerk.yml')[layers_key] || [] #: Array[String]?
23
15
  end
24
16
 
25
- sig { returns(T::Boolean) }
17
+ #: -> bool
26
18
  def layers_key_configured?
27
- @layers_key_configured ||= YAML.load_file('packwerk.yml')['architecture_layers'].nil?
19
+ @layers_key_configured ||= YAML.load_file('packwerk.yml')['architecture_layers'].nil? #: bool?
28
20
  end
29
21
 
30
- sig { returns(String) }
22
+ #: -> String
31
23
  def layers_key
32
24
  layers_key_configured? ? 'layers' : 'architecture_layers'
33
25
  end
34
26
 
35
- sig { returns(String) }
27
+ #: -> String
36
28
  def violation_key
37
29
  layers_key_configured? ? LAYER_VIOLATION_TYPE : ARCHITECTURE_VIOLATION_TYPE
38
30
  end
39
31
 
40
- sig { returns(String) }
32
+ #: -> String
41
33
  def enforce_key
42
34
  layers_key_configured? ? LAYER_ENFORCE : ARCHITECTURE_ENFORCE
43
35
  end
@@ -4,15 +4,7 @@
4
4
  module Packwerk
5
5
  module Layer
6
6
  class Layers
7
- extend T::Sig
8
-
9
- sig { void }
10
- def initialize
11
- @names = T.let(@names, T.nilable(T::Set[String]))
12
- @names_list = T.let(@names_list, T.nilable(T::Array[String]))
13
- end
14
-
15
- sig { params(layer: String).returns(Integer) }
7
+ #: (String layer) -> Integer
16
8
  def index_of(layer)
17
9
  index = names_list.reverse.find_index(layer)
18
10
  if index.nil?
@@ -22,14 +14,14 @@ module Packwerk
22
14
  index
23
15
  end
24
16
 
25
- sig { returns(T::Set[String]) }
17
+ #: -> Set[String]
26
18
  def names
27
- @names ||= Set.new(names_list)
19
+ @names ||= Set.new(names_list) #: Set[String]?
28
20
  end
29
21
 
30
- sig { returns(T::Array[String]) }
22
+ #: -> Array[String]
31
23
  def names_list
32
- @names_list ||= Config.new.layers_list
24
+ @names_list ||= Config.new.layers_list #: Array[String]?
33
25
  end
34
26
  end
35
27
  end
@@ -3,19 +3,29 @@
3
3
 
4
4
  module Packwerk
5
5
  module Layer
6
- class Package < T::Struct
7
- extend T::Sig
6
+ class Package
7
+ #: String?
8
+ attr_reader :layer
8
9
 
9
- const :layer, T.nilable(String)
10
- const :enforcement_setting, T.nilable(T.any(T::Boolean, String, T::Array[String]))
11
- const :config, T::Hash[T.untyped, T.untyped]
10
+ #: (bool | String | Array[String])?
11
+ attr_reader :enforcement_setting
12
12
 
13
- sig { returns(T::Boolean) }
13
+ #: Hash[untyped, untyped]
14
+ attr_reader :config
15
+
16
+ #: (layer: String?, enforcement_setting: (bool | String | Array[String])?, config: Hash[untyped, untyped]) -> void
17
+ def initialize(layer:, enforcement_setting:, config:)
18
+ @layer = layer
19
+ @enforcement_setting = enforcement_setting
20
+ @config = config
21
+ end
22
+
23
+ #: -> bool
14
24
  def enforces?
15
25
  enforcement_setting == true || enforcement_setting == 'strict'
16
26
  end
17
27
 
18
- sig { params(other_package: Package, layers: Layers).returns(T::Boolean) }
28
+ #: (Package other_package, layers: Layers) -> bool
19
29
  def can_depend_on?(other_package, layers:)
20
30
  return true if !enforces?
21
31
 
@@ -28,9 +38,7 @@ module Packwerk
28
38
  end
29
39
 
30
40
  class << self
31
- extend T::Sig
32
-
33
- sig { params(package: ::Packwerk::Package, layers: Layers).returns(Package) }
41
+ #: (::Packwerk::Package package, Layers layers) -> Package
34
42
  def from(package, layers)
35
43
  config = package.config
36
44
 
@@ -45,9 +53,9 @@ module Packwerk
45
53
  end
46
54
 
47
55
  Package.new(
48
- layer: layer,
56
+ layer:,
49
57
  enforcement_setting: config[Config.new.enforce_key],
50
- config: config
58
+ config:
51
59
  )
52
60
  end
53
61
  end
@@ -4,14 +4,14 @@
4
4
  module Packwerk
5
5
  module Layer
6
6
  class Validator
7
- extend T::Sig
8
7
  include Packwerk::Validator
9
8
 
10
9
  Result = Packwerk::Validator::Result
11
10
 
12
- sig { override.params(package_set: PackageSet, configuration: Configuration).returns(Result) }
11
+ # @override
12
+ #: (PackageSet package_set, Configuration configuration) -> Result
13
13
  def call(package_set, configuration)
14
- results = T.let([], T::Array[Result])
14
+ results = [] #: Array[Result]
15
15
 
16
16
  package_set.each do |package|
17
17
  config = package.config
@@ -36,24 +36,23 @@ module Packwerk
36
36
  merge_results(results, separator: "\n---\n")
37
37
  end
38
38
 
39
- sig { returns(Layers) }
39
+ #: -> Layers
40
40
  def layers
41
- @layers ||= T.let(Layers.new, T.nilable(Packwerk::Layer::Layers))
41
+ @layers ||= Layers.new #: Packwerk::Layer::Layers?
42
42
  end
43
43
 
44
- sig { returns(Config) }
44
+ #: -> Config
45
45
  def layer_config
46
- @layer_config ||= T.let(Config.new, T.nilable(Config))
46
+ @layer_config ||= Config.new #: Config?
47
47
  end
48
48
 
49
- sig { override.returns(T::Array[String]) }
49
+ # @override
50
+ #: -> Array[String]
50
51
  def permitted_keys
51
52
  [layer_config.enforce_key, 'layer']
52
53
  end
53
54
 
54
- sig do
55
- params(package: Package, config_file_path: String, config: T::Hash[T.untyped, T.untyped]).returns(Result)
56
- end
55
+ #: (Package package, String config_file_path, Hash[untyped, untyped] config) -> Result
57
56
  def check_enforce_key(package, config_file_path, config)
58
57
  enforce_layer_present = !config[Config::LAYER_ENFORCE].nil?
59
58
  enforce_architecture_present = !config[Config::ARCHITECTURE_ENFORCE].nil?
@@ -73,9 +72,7 @@ module Packwerk
73
72
  end
74
73
  end
75
74
 
76
- sig do
77
- params(package: Package, config_file_path: String).returns(Result)
78
- end
75
+ #: (Package package, String config_file_path) -> Result
79
76
  def check_layer_setting(package, config_file_path)
80
77
  layer = package.layer
81
78
  valid_layer = layer.nil? || layers.names.include?(layer)
@@ -95,9 +92,7 @@ module Packwerk
95
92
  end
96
93
  end
97
94
 
98
- sig do
99
- params(config_file_path: String, setting: T.untyped).returns(Result)
100
- end
95
+ #: (String config_file_path, untyped setting) -> Result
101
96
  def check_enforce_layers_setting(config_file_path, setting)
102
97
  activated_value = [true, 'strict'].include?(setting)
103
98
  valid_value = [true, nil, false, 'strict'].include?(setting)
@@ -8,52 +8,52 @@ module Packwerk
8
8
  module Privacy
9
9
  # Checks whether a given reference references a private constant of another package.
10
10
  class Checker
11
- extend T::Sig
12
11
  include Packwerk::Checker
13
12
 
14
- VIOLATION_TYPE = T.let('privacy', String)
15
- PUBLICIZED_SIGIL = T.let('pack_public: true', String)
16
- PUBLICIZED_SIGIL_REGEX = T.let(/#.*pack_public:\s*true/, Regexp)
17
- @publicized_locations = T.let({}, T::Hash[String, T::Boolean])
13
+ VIOLATION_TYPE = 'privacy'
14
+ PUBLICIZED_SIGIL = 'pack_public: true'
15
+ PUBLICIZED_SIGIL_REGEX = /pack_public:\s*true/
16
+ @publicized_locations = {} #: Hash[String, bool]
18
17
 
19
18
  class << self
20
- extend T::Sig
19
+ #: Hash[String, bool]
20
+ attr_reader :publicized_locations
21
21
 
22
- sig { returns(T::Hash[String, T::Boolean]) }
23
- def publicized_locations
24
- @publicized_locations
25
- end
26
-
27
- sig { params(location: String).returns(T::Boolean) }
22
+ #: (String location) -> bool
28
23
  def publicized_location?(location)
29
24
  unless publicized_locations.key?(location)
30
25
  publicized_locations[location] = check_for_publicized_sigil(location)
31
26
  end
32
27
 
33
- T.must(publicized_locations[location])
28
+ publicized_locations.fetch(location)
34
29
  end
35
30
 
36
- sig { params(location: String).returns(T::Boolean) }
31
+ #: (String location) -> bool
37
32
  def check_for_publicized_sigil(location)
38
33
  content_contains_sigil?(File.readlines(location))
39
34
  end
40
35
 
41
- sig { params(lines: T::Array[String]).returns(T::Boolean) }
36
+ #: (Array[String] lines) -> bool
42
37
  def content_contains_sigil?(lines)
43
- T.must(lines[0..4]).any? { |l| l =~ PUBLICIZED_SIGIL_REGEX }
38
+ lines.first(5).any? do |l|
39
+ # Only the sigil's existence matters, so it is enough to look for it after the
40
+ # line's first `#`. Searching from there keeps the scan linear in the length of
41
+ # the line, where matching `/#.*pack_public:\s*true/` would retry the `.*` scan
42
+ # once per `#` in the line.
43
+ comment_start = l.index('#')
44
+ !comment_start.nil? && PUBLICIZED_SIGIL_REGEX.match?(l, comment_start + 1)
45
+ end
44
46
  end
45
47
  end
46
48
 
47
- sig { override.returns(String) }
49
+ # @override
50
+ #: -> String
48
51
  def violation_type
49
52
  VIOLATION_TYPE
50
53
  end
51
54
 
52
- sig do
53
- override
54
- .params(reference: Packwerk::Reference)
55
- .returns(T::Boolean)
56
- end
55
+ # @override
56
+ #: (Packwerk::Reference reference) -> bool
57
57
  def invalid_reference?(reference)
58
58
  constant_package = reference.constant.package
59
59
  privacy_package = Package.from(constant_package)
@@ -69,11 +69,8 @@ module Packwerk
69
69
  explicitly_private_constant?(reference.constant, explicitly_private_constants: privacy_package.private_constants)
70
70
  end
71
71
 
72
- sig do
73
- override
74
- .params(listed_offense: Packwerk::ReferenceOffense)
75
- .returns(T::Boolean)
76
- end
72
+ # @override
73
+ #: (Packwerk::ReferenceOffense listed_offense) -> bool
77
74
  def strict_mode_violation?(listed_offense)
78
75
  publishing_package = listed_offense.reference.constant.package
79
76
 
@@ -86,11 +83,8 @@ module Packwerk
86
83
  true
87
84
  end
88
85
 
89
- sig do
90
- override
91
- .params(reference: Packwerk::Reference)
92
- .returns(String)
93
- end
86
+ # @override
87
+ #: (Packwerk::Reference reference) -> String
94
88
  def message(reference)
95
89
  source_desc = "'#{reference.package}'"
96
90
 
@@ -106,12 +100,7 @@ module Packwerk
106
100
 
107
101
  private
108
102
 
109
- sig do
110
- params(
111
- constant: ConstantContext,
112
- explicitly_private_constants: T::Array[String]
113
- ).returns(T::Boolean)
114
- end
103
+ #: (ConstantContext constant, explicitly_private_constants: Array[String]) -> bool
115
104
  def explicitly_private_constant?(constant, explicitly_private_constants:)
116
105
  return true if explicitly_private_constants.empty?
117
106
 
@@ -120,15 +109,12 @@ module Packwerk
120
109
  explicitly_private_constants.any? { |epc| constant.name.start_with?("#{epc}::") }
121
110
  end
122
111
 
123
- sig do
124
- params(privacy_option: T.nilable(T.any(T::Boolean, String, T::Array[String])))
125
- .returns(T::Boolean)
126
- end
112
+ #: ((bool | String | Array[String])? privacy_option) -> bool
127
113
  def enforcement_disabled?(privacy_option)
128
114
  [false, nil].include?(privacy_option)
129
115
  end
130
116
 
131
- sig { params(reference: Reference).returns(String) }
117
+ #: (Reference reference) -> String
132
118
  def standard_help_message(reference)
133
119
  standard_message = <<~MESSAGE.chomp
134
120
  Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
@@ -138,7 +124,7 @@ module Packwerk
138
124
  standard_message.chomp
139
125
  end
140
126
 
141
- sig { params(globs: T::Array[String], path: Pathname).returns(T::Boolean) }
127
+ #: (Array[String] globs, Pathname path) -> bool
142
128
  def exclude_from_strict?(globs, path)
143
129
  globs.any? do |glob|
144
130
  path.fnmatch(glob, File::FNM_EXTGLOB)
@@ -3,25 +3,56 @@
3
3
 
4
4
  module Packwerk
5
5
  module Privacy
6
- class Package < T::Struct
7
- extend T::Sig
6
+ class Package
7
+ #: String
8
+ attr_reader :public_path
8
9
 
9
- const :public_path, String
10
- const :user_defined_public_path, T.nilable(String)
11
- const :enforce_privacy, T.nilable(T.any(T::Boolean, String))
12
- const :private_constants, T::Array[String]
13
- const :ignored_private_constants, T::Array[String]
14
- const :strict_privacy_ignored_patterns, T::Array[String]
10
+ #: String?
11
+ attr_reader :user_defined_public_path
15
12
 
16
- sig { params(path: String).returns(T::Boolean) }
13
+ #: (bool | String)?
14
+ attr_reader :enforce_privacy
15
+
16
+ #: Array[String]
17
+ attr_reader :private_constants
18
+
19
+ #: Array[String]
20
+ attr_reader :ignored_private_constants
21
+
22
+ #: Array[String]
23
+ attr_reader :strict_privacy_ignored_patterns
24
+
25
+ #: (
26
+ #| public_path: String,
27
+ #| user_defined_public_path: String?,
28
+ #| enforce_privacy: (bool | String)?,
29
+ #| private_constants: Array[String],
30
+ #| ignored_private_constants: Array[String],
31
+ #| strict_privacy_ignored_patterns: Array[String]
32
+ #| ) -> void
33
+ def initialize(
34
+ public_path:,
35
+ user_defined_public_path:,
36
+ enforce_privacy:,
37
+ private_constants:,
38
+ ignored_private_constants:,
39
+ strict_privacy_ignored_patterns:
40
+ )
41
+ @public_path = public_path
42
+ @user_defined_public_path = user_defined_public_path
43
+ @enforce_privacy = enforce_privacy
44
+ @private_constants = private_constants
45
+ @ignored_private_constants = ignored_private_constants
46
+ @strict_privacy_ignored_patterns = strict_privacy_ignored_patterns
47
+ end
48
+
49
+ #: (String path) -> bool
17
50
  def public_path?(path)
18
51
  path.start_with?(public_path)
19
52
  end
20
53
 
21
54
  class << self
22
- extend T::Sig
23
-
24
- sig { params(package: ::Packwerk::Package).returns(Package) }
55
+ #: (::Packwerk::Package package) -> Package
25
56
  def from(package)
26
57
  Package.new(
27
58
  public_path: public_path_for(package),
@@ -33,7 +64,7 @@ module Packwerk
33
64
  )
34
65
  end
35
66
 
36
- sig { params(package: ::Packwerk::Package).returns(T.nilable(String)) }
67
+ #: (::Packwerk::Package package) -> String?
37
68
  def user_defined_public_path(package)
38
69
  return unless package.config['public_path']
39
70
  return package.config['public_path'] if package.config['public_path'].end_with?('/')
@@ -41,7 +72,7 @@ module Packwerk
41
72
  "#{package.config['public_path']}/"
42
73
  end
43
74
 
44
- sig { params(package: ::Packwerk::Package).returns(String) }
75
+ #: (::Packwerk::Package package) -> String
45
76
  def public_path_for(package)
46
77
  unprefixed_public_path = user_defined_public_path(package) || 'app/public/'
47
78
 
@@ -4,20 +4,18 @@
4
4
  module Packwerk
5
5
  module Privacy
6
6
  class Validator
7
- extend T::Sig
8
7
  include Packwerk::Validator
9
8
 
10
9
  Result = Packwerk::Validator::Result
11
10
 
12
- sig { override.params(package_set: PackageSet, configuration: Configuration).returns(Result) }
11
+ # @override
12
+ #: (PackageSet package_set, Configuration configuration) -> Result
13
13
  def call(package_set, configuration)
14
14
  privacy_settings = package_manifests_settings_for(configuration, 'enforce_privacy')
15
15
 
16
- results = T.let([], T::Array[Result])
17
-
18
- privacy_settings.each do |config_file_path, setting|
19
- results << check_enforce_privacy_setting(config_file_path, setting)
20
- end
16
+ results = privacy_settings.map do |config_file_path, setting|
17
+ check_enforce_privacy_setting(config_file_path, setting)
18
+ end #: Array[Result]
21
19
 
22
20
  results += verify_private_constants_setting(package_set, configuration)
23
21
 
@@ -29,17 +27,18 @@ module Packwerk
29
27
  merge_results(results, separator: "\n---\n")
30
28
  end
31
29
 
32
- sig { override.returns(T::Array[String]) }
30
+ # @override
31
+ #: -> Array[String]
33
32
  def permitted_keys
34
- %w[public_path enforce_privacy private_constants ignored_private_constants strict_privacy_ignored_patterns]
33
+ %w(public_path enforce_privacy private_constants ignored_private_constants strict_privacy_ignored_patterns)
35
34
  end
36
35
 
37
36
  private
38
37
 
39
- sig { params(package_set: PackageSet, configuration: Configuration).returns(T::Array[Result]) }
38
+ #: (PackageSet package_set, Configuration configuration) -> Array[Result]
40
39
  def verify_private_constants_setting(package_set, configuration)
41
40
  private_constants_setting = package_manifests_settings_for(configuration, 'private_constants')
42
- results = T.let([], T::Array[Result])
41
+ results = [] #: Array[Result]
43
42
  resolver = ConstantResolver.new(
44
43
  root_path: configuration.root_path,
45
44
  load_paths: configuration.load_paths,
@@ -65,19 +64,17 @@ module Packwerk
65
64
 
66
65
  constant_locations.each do |name, location|
67
66
  results << if location
68
- check_private_constant_location(configuration, package_set, name, location, config_file_path)
69
- else
70
- private_constant_unresolvable(name, config_file_path)
71
- end
67
+ check_private_constant_location(configuration, package_set, name, location, config_file_path)
68
+ else
69
+ private_constant_unresolvable(name, config_file_path)
70
+ end
72
71
  end
73
72
  end
74
73
 
75
74
  results
76
75
  end
77
76
 
78
- sig do
79
- params(config_file_path: String, setting: T.untyped).returns(Result)
80
- end
77
+ #: (String config_file_path, untyped setting) -> Result
81
78
  def check_public_path(config_file_path, setting)
82
79
  if setting.is_a?(String) || setting.nil?
83
80
  Result.new(ok: true)
@@ -89,9 +86,7 @@ module Packwerk
89
86
  end
90
87
  end
91
88
 
92
- sig do
93
- params(config_file_path: String, setting: T.untyped).returns(Result)
94
- end
89
+ #: (String config_file_path, untyped setting) -> Result
95
90
  def check_enforce_privacy_setting(config_file_path, setting)
96
91
  if [TrueClass, FalseClass, NilClass].include?(setting.class) || setting == 'strict'
97
92
  Result.new(ok: true)
@@ -103,10 +98,13 @@ module Packwerk
103
98
  end
104
99
  end
105
100
 
106
- sig do
107
- params(configuration: Configuration, package_set: PackageSet, name: T.untyped, location: T.untyped,
108
- config_file_path: T.untyped).returns(Result)
109
- end
101
+ #: (
102
+ #| Configuration configuration,
103
+ #| PackageSet package_set,
104
+ #| untyped name,
105
+ #| untyped location,
106
+ #| untyped config_file_path
107
+ #| ) -> Result
110
108
  def check_private_constant_location(configuration, package_set, name, location, config_file_path)
111
109
  declared_package = package_set.package_from_path(relative_path(configuration, config_file_path))
112
110
  constant_package = package_set.package_from_path(location)
@@ -121,7 +119,7 @@ module Packwerk
121
119
  end
122
120
  end
123
121
 
124
- sig { params(location: String, constant_package: Packwerk::Package, name: T.untyped).returns(Result) }
122
+ #: (String location, Packwerk::Package constant_package, untyped name) -> Result
125
123
  def check_for_publicized_constant(location, constant_package, name)
126
124
  if Packwerk::Privacy::Checker.publicized_location?(location)
127
125
  sigil = Packwerk::Privacy::Checker::PUBLICIZED_SIGIL
@@ -138,7 +136,7 @@ module Packwerk
138
136
  end
139
137
  end
140
138
 
141
- sig { params(constants: T.untyped, config_file_path: String).returns(T::Array[Result]) }
139
+ #: (untyped constants, String config_file_path) -> Array[Result]
142
140
  def assert_constants_can_be_loaded(constants, config_file_path)
143
141
  constants.map do |constant|
144
142
  if constant.start_with?('::')
@@ -149,13 +147,13 @@ module Packwerk
149
147
  'prefixed with the top-level namespace operator `::`.'
150
148
  Result.new(
151
149
  ok: false,
152
- error_value: error_value
150
+ error_value:
153
151
  )
154
152
  end
155
153
  end
156
154
  end
157
155
 
158
- sig { params(name: T.untyped, config_file_path: T.untyped).returns(Result) }
156
+ #: (untyped name, untyped config_file_path) -> Result
159
157
  def private_constant_unresolvable(name, config_file_path)
160
158
  explicit_filepath = "#{(name.start_with?('::') ? name[2..] : name).underscore}.rb"
161
159
 
@@ -8,21 +8,18 @@ module Packwerk
8
8
  module Visibility
9
9
  # Checks whether a given reference references a constant from a package that does not permit visibility
10
10
  class Checker
11
- extend T::Sig
12
11
  include Packwerk::Checker
13
12
 
14
- VIOLATION_TYPE = T.let('visibility', String)
13
+ VIOLATION_TYPE = 'visibility'
15
14
 
16
- sig { override.returns(String) }
15
+ # @override
16
+ #: -> String
17
17
  def violation_type
18
18
  VIOLATION_TYPE
19
19
  end
20
20
 
21
- sig do
22
- override
23
- .params(reference: Packwerk::Reference)
24
- .returns(T::Boolean)
25
- end
21
+ # @override
22
+ #: (Packwerk::Reference reference) -> bool
26
23
  def invalid_reference?(reference)
27
24
  constant_package = reference.constant.package
28
25
  visibility_package = Package.from(constant_package)
@@ -32,21 +29,15 @@ module Packwerk
32
29
  !visibility_package.visible_to.include?(reference.package.name)
33
30
  end
34
31
 
35
- sig do
36
- override
37
- .params(listed_offense: Packwerk::ReferenceOffense)
38
- .returns(T::Boolean)
39
- end
32
+ # @override
33
+ #: (Packwerk::ReferenceOffense listed_offense) -> bool
40
34
  def strict_mode_violation?(listed_offense)
41
35
  publishing_package = listed_offense.reference.constant.package
42
36
  publishing_package.config['enforce_visibility'] == 'strict'
43
37
  end
44
38
 
45
- sig do
46
- override
47
- .params(reference: Packwerk::Reference)
48
- .returns(String)
49
- end
39
+ # @override
40
+ #: (Packwerk::Reference reference) -> String
50
41
  def message(reference)
51
42
  source_desc = "'#{reference.package}'"
52
43
 
@@ -62,15 +53,12 @@ module Packwerk
62
53
 
63
54
  private
64
55
 
65
- sig do
66
- params(visibility_option: T.nilable(T.any(T::Boolean, String)))
67
- .returns(T::Boolean)
68
- end
56
+ #: ((bool | String)? visibility_option) -> bool
69
57
  def enforcement_disabled?(visibility_option)
70
58
  [false, nil].include?(visibility_option)
71
59
  end
72
60
 
73
- sig { params(reference: Reference).returns(String) }
61
+ #: (Reference reference) -> String
74
62
  def standard_help_message(reference)
75
63
  standard_message = <<~MESSAGE.chomp
76
64
  Inference details: this is a reference to #{reference.constant.name} which seems to be defined in #{reference.constant.location}.
@@ -3,16 +3,21 @@
3
3
 
4
4
  module Packwerk
5
5
  module Visibility
6
- class Package < T::Struct
7
- extend T::Sig
6
+ class Package
7
+ #: Array[String]
8
+ attr_reader :visible_to
8
9
 
9
- const :visible_to, T::Array[String]
10
- const :enforce_visibility, T.nilable(T.any(T::Boolean, String))
10
+ #: (bool | String)?
11
+ attr_reader :enforce_visibility
11
12
 
12
- class << self
13
- extend T::Sig
13
+ #: (visible_to: Array[String], enforce_visibility: (bool | String)?) -> void
14
+ def initialize(visible_to:, enforce_visibility:)
15
+ @visible_to = visible_to
16
+ @enforce_visibility = enforce_visibility
17
+ end
14
18
 
15
- sig { params(package: ::Packwerk::Package).returns(Package) }
19
+ class << self
20
+ #: (::Packwerk::Package package) -> Package
16
21
  def from(package)
17
22
  Package.new(
18
23
  visible_to: package.config['visible_to'] || [],
@@ -4,15 +4,15 @@
4
4
  module Packwerk
5
5
  module Visibility
6
6
  class Validator
7
- extend T::Sig
8
7
  include Packwerk::Validator
9
8
 
10
9
  Result = Packwerk::Validator::Result
11
10
 
12
- sig { override.params(package_set: PackageSet, configuration: Configuration).returns(Result) }
11
+ # @override
12
+ #: (PackageSet package_set, Configuration configuration) -> Result
13
13
  def call(package_set, configuration)
14
14
  visible_settings = package_manifests_settings_for(configuration, 'visible_to')
15
- results = T.let([], T::Array[Result])
15
+ results = [] #: Array[Result]
16
16
 
17
17
  all_package_names = package_set.to_set(&:name)
18
18
 
@@ -50,9 +50,10 @@ module Packwerk
50
50
  merge_results(results, separator: "\n---\n")
51
51
  end
52
52
 
53
- sig { override.returns(T::Array[String]) }
53
+ # @override
54
+ #: -> Array[String]
54
55
  def permitted_keys
55
- %w[visible_to enforce_visibility]
56
+ %w(visible_to enforce_visibility)
56
57
  end
57
58
  end
58
59
  end
@@ -1,7 +1,6 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'sorbet-runtime'
5
4
  require 'packwerk'
6
5
 
7
6
  require 'packwerk/privacy/checker'
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packwerk-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gusto Engineers
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-28 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: packwerk
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: 2.2.1
18
+ version: '3'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: 2.2.1
25
+ version: '3'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: railties
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -38,20 +37,6 @@ dependencies:
38
37
  - - ">="
39
38
  - !ruby/object:Gem::Version
40
39
  version: 6.0.0
41
- - !ruby/object:Gem::Dependency
42
- name: sorbet-runtime
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
40
  - !ruby/object:Gem::Dependency
56
41
  name: zeitwerk
57
42
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +122,7 @@ dependencies:
137
122
  - !ruby/object:Gem::Version
138
123
  version: '0'
139
124
  - !ruby/object:Gem::Dependency
140
- name: sorbet
125
+ name: rubocop-gusto
141
126
  requirement: !ruby/object:Gem::Requirement
142
127
  requirements:
143
128
  - - ">="
@@ -151,7 +136,7 @@ dependencies:
151
136
  - !ruby/object:Gem::Version
152
137
  version: '0'
153
138
  - !ruby/object:Gem::Dependency
154
- name: sorbet-static
139
+ name: sorbet
155
140
  requirement: !ruby/object:Gem::Requirement
156
141
  requirements:
157
142
  - - ">="
@@ -209,7 +194,6 @@ metadata:
209
194
  source_code_uri: https://github.com/rubyatscale/packwerk-extensions
210
195
  changelog_uri: https://github.com/rubyatscale/packwerk-extensions/releases
211
196
  allowed_push_host: https://rubygems.org
212
- post_install_message:
213
197
  rdoc_options: []
214
198
  require_paths:
215
199
  - lib
@@ -217,15 +201,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
217
201
  requirements:
218
202
  - - ">="
219
203
  - !ruby/object:Gem::Version
220
- version: '2.7'
204
+ version: '3.3'
221
205
  required_rubygems_version: !ruby/object:Gem::Requirement
222
206
  requirements:
223
207
  - - ">="
224
208
  - !ruby/object:Gem::Version
225
209
  version: '0'
226
210
  requirements: []
227
- rubygems_version: 3.5.11
228
- signing_key:
211
+ rubygems_version: 3.6.9
229
212
  specification_version: 4
230
213
  summary: A collection of extensions for packwerk packages.
231
214
  test_files: []