packwerk 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +4 -2
- data/TROUBLESHOOT.md +1 -1
- data/USAGE.md +34 -18
- data/lib/packwerk.rb +0 -1
- data/lib/packwerk/application_validator.rb +10 -4
- data/lib/packwerk/association_inspector.rb +26 -11
- data/lib/packwerk/checker.rb +20 -0
- data/lib/packwerk/cli.rb +9 -1
- data/lib/packwerk/configuration.rb +11 -7
- data/lib/packwerk/dependency_checker.rb +3 -0
- data/lib/packwerk/deprecated_references.rb +1 -1
- data/lib/packwerk/generators/application_validation.rb +2 -2
- data/lib/packwerk/generators/templates/package.yml +4 -0
- data/lib/packwerk/generators/templates/packwerk +2 -2
- data/lib/packwerk/generators/templates/packwerk.yml.erb +1 -1
- data/lib/packwerk/node.rb +21 -5
- data/lib/packwerk/node_processor.rb +12 -0
- data/lib/packwerk/package.rb +8 -1
- data/lib/packwerk/package_set.rb +5 -3
- data/lib/packwerk/privacy_checker.rb +3 -0
- data/lib/packwerk/run_context.rb +1 -0
- data/lib/packwerk/version.rb +1 -1
- data/packwerk.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6adf93154744a85f6f49a1b830710dee4f4c7b8e05373de50aef86926167f23e
|
4
|
+
data.tar.gz: cfea93c802c34114e63966717e7a643cf1de94f3061b13ed434b04dd12469bed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00dfee149ce8b43ce862a0df57eda5af2583fd4066cd1596ffaae2a1a5f562150e8caf84d29f062e11a039bf08bea3eb360e9a2817b14c2d9229ce77a89dc2e4
|
7
|
+
data.tar.gz: f74cecc91b2fce594df2c1dae811d469a1f8e490daefbd396ed2fb87cb6438e7286de98f63c425d196af2b7ce4ed6f8ef6e0cfb9ddf8b47d17e38bbccda2a0db
|
data/.github/workflows/ci.yml
CHANGED
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -16,9 +16,9 @@ Packwerk supports MRI versions 2.6 and above.
|
|
16
16
|
|
17
17
|
## Demo
|
18
18
|
|
19
|
-
Watch a [1-minute video demo](https://
|
19
|
+
Watch a [1-minute video demo](https://www.youtube.com/watch?v=NwqlyBAxVpQ&feature=youtu.be) on how Packwerk works.
|
20
20
|
|
21
|
-
[![](./static/packwerk-check-demo.png)](https://
|
21
|
+
[![](./static/packwerk-check-demo.png)](https://www.youtube.com/watch?v=NwqlyBAxVpQ&feature=youtu.be)
|
22
22
|
|
23
23
|
## Installation
|
24
24
|
|
@@ -28,6 +28,8 @@ Watch a [1-minute video demo](https://drive.google.com/file/d/1D-t1nYduwgpHAP4DH
|
|
28
28
|
gem 'packwerk'
|
29
29
|
```
|
30
30
|
|
31
|
+
_Note: Packwerk has to be grouped in production environment within the Gemfile if your Rails app has custom inflections._
|
32
|
+
|
31
33
|
2. Install the gem
|
32
34
|
|
33
35
|
Execute:
|
data/TROUBLESHOOT.md
CHANGED
@@ -16,7 +16,7 @@ You can specify folders or packages in Packwerk commands for a shorter run time:
|
|
16
16
|
|
17
17
|
bundle exec packwerk check components/your_package
|
18
18
|
|
19
|
-
bundle exec packwerk update components/your_package
|
19
|
+
bundle exec packwerk update-deprecations components/your_package
|
20
20
|
|
21
21
|
_Note: You cannot specify folders or packages for `packwerk validate` because the command runs for the entire application._
|
22
22
|
|
data/USAGE.md
CHANGED
@@ -47,11 +47,11 @@ Here is a list of files generated:
|
|
47
47
|
|
48
48
|
| File | Location | Description |
|
49
49
|
|-----------------------------|--------------|------------|
|
50
|
-
| Packwerk configuration | packwerk.yml | See [Setting up configuration file](#Setting-up-configuration-file) |
|
50
|
+
| Packwerk configuration | packwerk.yml | See [Setting up the configuration file](#Setting-up-the-configuration-file) |
|
51
51
|
| Root package | package.yml | A package for the root folder |
|
52
52
|
| Bin script | bin/packwerk | For Rails applications to run Packwerk validation on CI, see [Validating the package system](#Validating-the-package-system) |
|
53
53
|
| Validation test | test/packwerk_validator_test.rb | For Ruby projects to run Packwerk validation using tests, see [Validating the package system](#Validating-the-package-system) |
|
54
|
-
| Custom inflections |
|
54
|
+
| Custom inflections | config/inflections.yml | A custom inflections file is only required if you have custom inflections in `inflections.rb`, see [Inflections](#Inflections) |
|
55
55
|
|
56
56
|
After that, you may begin creating packages for your application. See [Defining packages](#Defining-packages)
|
57
57
|
|
@@ -59,33 +59,37 @@ After that, you may begin creating packages for your application. See [Defining
|
|
59
59
|
|
60
60
|
Packwerk reads from the `packwerk.yml` configuration file in the root directory. Packwerk will run with the default configuration if any of these settings are not specified.
|
61
61
|
|
62
|
-
| Key | Default value
|
63
|
-
|
64
|
-
| include | **/*.{rb,rake,erb}
|
65
|
-
| exclude | {bin,node_modules,script,tmp}/**/* | list of patterns for folder paths to exclude |
|
66
|
-
| package_paths | **/
|
67
|
-
| load_paths | All application autoload paths
|
68
|
-
| custom_associations | N/A
|
62
|
+
| Key | Default value | Description |
|
63
|
+
|----------------------|-------------------------------------------|--------------|
|
64
|
+
| include | **/*.{rb,rake,erb} | list of patterns for folder paths to include |
|
65
|
+
| exclude | {bin,node_modules,script,tmp,vendor}/**/* | list of patterns for folder paths to exclude |
|
66
|
+
| package_paths | **/ | patterns to find package configuration files, see: Defining packages |
|
67
|
+
| load_paths | All application autoload paths | list of load paths |
|
68
|
+
| custom_associations | N/A | list of custom associations, if any |
|
69
69
|
|
70
70
|
|
71
71
|
### Inflections
|
72
72
|
|
73
73
|
Packwerk requires custom inflections to be defined in `inflections.yml` instead of the traditional `inflections.rb`. This is because Packwerk accounts for custom inflections, such as acronyms, when resolving constants. Additionally, Packwerk interprets Active Record associations as references to constants. For example, `has_many :birds` is reference to the `Birds` constant.
|
74
74
|
|
75
|
-
In order to make your custom inflections compatible with Active Support and Packwerk, you must create
|
75
|
+
In order to make your custom inflections compatible with Active Support and Packwerk, you must create a `config/inflections.yml` file and point `ActiveSupport::Inflector` to that file.
|
76
76
|
|
77
77
|
In `inflections.rb`, add:
|
78
78
|
|
79
79
|
```rb
|
80
|
+
require "packwerk/inflections/custom"
|
81
|
+
|
80
82
|
ActiveSupport::Inflector.inflections do |inflect|
|
81
83
|
# please add all custom inflections in the file below.
|
82
84
|
Packwerk::Inflections::Custom.new(
|
83
|
-
Rails.root.join("inflections.yml")
|
85
|
+
Rails.root.join("config", "inflections.yml")
|
84
86
|
).apply_to(inflect)
|
85
87
|
end
|
86
88
|
```
|
87
89
|
|
88
|
-
|
90
|
+
_Note: Packwerk has to be grouped in production environment within the Gemfile if you have custom inflections._
|
91
|
+
|
92
|
+
Next, move your existing custom inflections into `config/inflections.yml`:
|
89
93
|
|
90
94
|
```yaml
|
91
95
|
acronym:
|
@@ -97,9 +101,11 @@ irregular:
|
|
97
101
|
- ['reserve', 'reserves']
|
98
102
|
uncountable:
|
99
103
|
- 'payment_details'
|
104
|
+
singular:
|
105
|
+
- [!ruby/regexp /status$/, 'status']
|
100
106
|
```
|
101
107
|
|
102
|
-
Any new inflectors should be added to `inflections.yml`.
|
108
|
+
Any new inflectors should be added to `config/inflections.yml`.
|
103
109
|
|
104
110
|
## Validating the package system
|
105
111
|
|
@@ -168,7 +174,17 @@ enforce_privacy:
|
|
168
174
|
It will be a privacy violation when a file outside of the `components/merchandising` package tries to reference `Merchandising::Product`.
|
169
175
|
|
170
176
|
##### Using public folders
|
171
|
-
You may enforce privacy either way mentioned above and still expose a public API for your package by placing constants in the `app/public
|
177
|
+
You may enforce privacy either way mentioned above and still expose a public API for your package by placing constants in the public folder, which by default is `app/public`. The constants in the public folder will be made available for use by the rest of the application.
|
178
|
+
|
179
|
+
##### Defining your own public folder
|
180
|
+
|
181
|
+
You may prefer to override the default public folder, you can do so on a per-package basis by defining a `public_path`.
|
182
|
+
|
183
|
+
Example:
|
184
|
+
|
185
|
+
```yaml
|
186
|
+
public_path: my/custom/path/
|
187
|
+
```
|
172
188
|
|
173
189
|
#### Enforcing dependency boundary
|
174
190
|
A package's dependency boundary is violated whenever it references a constant in some package that has not been declared as a dependency.
|
@@ -210,17 +226,17 @@ For existing codebases, packages are likely to have existing boundary violations
|
|
210
226
|
|
211
227
|
If so, you will want to stop the bleeding and prevent more violations from occuring. The existing violations in the codebase can be recorded in a [deprecated references list](#Understanding_the_list_of_deprecated_references) by executing:
|
212
228
|
|
213
|
-
bundle exec packwerk update
|
229
|
+
bundle exec packwerk update-deprecations
|
214
230
|
|
215
|
-
Similar to `packwerk check`, you may also run `packwerk update` on folders or packages:
|
231
|
+
Similar to `packwerk check`, you may also run `packwerk update-deprecations` on folders or packages:
|
216
232
|
|
217
|
-
bundle exec packwerk update components/your_package
|
233
|
+
bundle exec packwerk update-deprecations components/your_package
|
218
234
|
|
219
235
|
![](static/packwerk_update.gif)
|
220
236
|
|
221
237
|
_Note: Changing dependencies or enabling dependencies will not require a full update of the codebase, only the package that changed. On the other hand, changing or enabling privacy will require a full update of the codebase._
|
222
238
|
|
223
|
-
`packwerk update` should only be run to record existing violations and to remove deprecated references that have been worked off. Running `packwerk update` to resolve a violation should be the very last resort.
|
239
|
+
`packwerk update-deprecations` should only be run to record existing violations and to remove deprecated references that have been worked off. Running `packwerk update-deprecations` to resolve a violation should be the very last resort.
|
224
240
|
|
225
241
|
See: [TROUBLESHOOT.md - Troubleshooting violations](TROUBLESHOOT.md#Troubleshooting_violations)
|
226
242
|
|
data/lib/packwerk.rb
CHANGED
@@ -34,7 +34,6 @@ require "packwerk/package_set"
|
|
34
34
|
require "packwerk/parsers"
|
35
35
|
require "packwerk/privacy_checker"
|
36
36
|
require "packwerk/reference_extractor"
|
37
|
-
require "packwerk/reference_lister"
|
38
37
|
require "packwerk/run_context"
|
39
38
|
require "packwerk/updating_deprecated_references"
|
40
39
|
require "packwerk/version"
|
@@ -113,7 +113,7 @@ module Packwerk
|
|
113
113
|
hash = YAML.load_file(f)
|
114
114
|
next unless hash
|
115
115
|
|
116
|
-
known_keys = %w(enforce_privacy enforce_dependencies dependencies metadata)
|
116
|
+
known_keys = %w(enforce_privacy enforce_dependencies public_path dependencies metadata)
|
117
117
|
unknown_keys = hash.keys - known_keys
|
118
118
|
|
119
119
|
unless unknown_keys.empty?
|
@@ -134,6 +134,12 @@ module Packwerk
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
+
if hash.key?("public_path")
|
138
|
+
unless hash["public_path"].is_a?(String)
|
139
|
+
errors << "'public_path' option must be a string in #{f.inspect}: #{hash['public_path'].inspect}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
137
143
|
next unless hash.key?("dependencies")
|
138
144
|
next if hash["dependencies"].is_a?(Array)
|
139
145
|
|
@@ -170,8 +176,8 @@ module Packwerk
|
|
170
176
|
Packwerk::Inflections::Custom.new(inflections_file).apply_to(test_inflections)
|
171
177
|
|
172
178
|
results = %i(plurals singulars uncountables humans acronyms).map do |type|
|
173
|
-
expected = ActiveSupport::Inflector.inflections.public_send(type).
|
174
|
-
actual = test_inflections.public_send(type).
|
179
|
+
expected = ActiveSupport::Inflector.inflections.public_send(type).to_set
|
180
|
+
actual = test_inflections.public_send(type).to_set
|
175
181
|
|
176
182
|
if expected == actual
|
177
183
|
Result.new(true)
|
@@ -325,7 +331,7 @@ module Packwerk
|
|
325
331
|
end
|
326
332
|
|
327
333
|
def package_manifests(glob_pattern)
|
328
|
-
|
334
|
+
PackageSet.package_paths(@configuration.root_path, glob_pattern).map(&:to_s)
|
329
335
|
end
|
330
336
|
|
331
337
|
def relative_paths(paths)
|
@@ -22,23 +22,38 @@ module Packwerk
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def constant_name_from_node(node, ancestors:)
|
25
|
-
return unless Node.
|
26
|
-
|
27
|
-
method_name = Node.method_name(node)
|
28
|
-
return nil unless @associations.include?(method_name)
|
25
|
+
return unless Node.method_call?(node)
|
26
|
+
return unless association?(node)
|
29
27
|
|
30
28
|
arguments = Node.method_arguments(node)
|
31
|
-
|
32
|
-
return nil unless association_name
|
29
|
+
return unless (association_name = association_name(arguments))
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
if class_name_node
|
38
|
-
Node.literal_value(class_name_node) if Node.type(class_name_node) == Node::STRING
|
31
|
+
if (class_name_node = custom_class_name(arguments))
|
32
|
+
return unless Node.string?(class_name_node)
|
33
|
+
Node.literal_value(class_name_node)
|
39
34
|
else
|
40
35
|
@inflector.classify(association_name.to_s)
|
41
36
|
end
|
42
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def association?(node)
|
42
|
+
method_name = Node.method_name(node)
|
43
|
+
@associations.include?(method_name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def custom_class_name(arguments)
|
47
|
+
association_options = arguments.detect { |n| Node.hash?(n) }
|
48
|
+
return unless association_options
|
49
|
+
|
50
|
+
Node.value_from_hash(association_options, :class_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def association_name(arguments)
|
54
|
+
return unless Node.symbol?(arguments[0])
|
55
|
+
|
56
|
+
Node.literal_value(arguments[0])
|
57
|
+
end
|
43
58
|
end
|
44
59
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
require "packwerk/reference_lister"
|
6
|
+
|
7
|
+
module Packwerk
|
8
|
+
module Checker
|
9
|
+
extend T::Sig
|
10
|
+
extend T::Helpers
|
11
|
+
|
12
|
+
interface!
|
13
|
+
|
14
|
+
sig { params(reference: Reference, reference_lister: ReferenceLister).returns(T::Boolean).abstract }
|
15
|
+
def invalid_reference?(reference, reference_lister); end
|
16
|
+
|
17
|
+
sig { params(reference: Reference).returns(String).abstract }
|
18
|
+
def message_for(reference); end
|
19
|
+
end
|
20
|
+
end
|
data/lib/packwerk/cli.rb
CHANGED
@@ -43,6 +43,8 @@ module Packwerk
|
|
43
43
|
check(args)
|
44
44
|
when "update"
|
45
45
|
update(args)
|
46
|
+
when "update-deprecations"
|
47
|
+
update_deprecations(args)
|
46
48
|
when "validate"
|
47
49
|
validate(args)
|
48
50
|
when nil, "help"
|
@@ -52,7 +54,8 @@ module Packwerk
|
|
52
54
|
Subcommands:
|
53
55
|
init - set up packwerk
|
54
56
|
check - run all checks
|
55
|
-
update - update deprecated references
|
57
|
+
update - update deprecated references (deprecated, use update-deprecations instead)
|
58
|
+
update-deprecations - update deprecated references
|
56
59
|
validate - verify integrity of packwerk and package configuration
|
57
60
|
help - display help information about packwerk
|
58
61
|
USAGE
|
@@ -117,6 +120,11 @@ module Packwerk
|
|
117
120
|
end
|
118
121
|
|
119
122
|
def update(paths)
|
123
|
+
warn("`packwerk update` is deprecated in favor of `packwerk update-deprecations`.")
|
124
|
+
update_deprecations(paths)
|
125
|
+
end
|
126
|
+
|
127
|
+
def update_deprecations(paths)
|
120
128
|
updating_deprecated_references = ::Packwerk::UpdatingDeprecatedReferences.new(@configuration.root_path)
|
121
129
|
@run_context = Packwerk::RunContext.from_configuration(
|
122
130
|
@configuration,
|
@@ -28,7 +28,7 @@ module Packwerk
|
|
28
28
|
|
29
29
|
DEFAULT_CONFIG_PATH = "packwerk.yml"
|
30
30
|
DEFAULT_INCLUDE_GLOBS = ["**/*.{rb,rake,erb}"]
|
31
|
-
DEFAULT_EXCLUDE_GLOBS = ["{bin,node_modules,script,tmp}/**/*"]
|
31
|
+
DEFAULT_EXCLUDE_GLOBS = ["{bin,node_modules,script,tmp,vendor}/**/*"]
|
32
32
|
|
33
33
|
attr_reader(
|
34
34
|
:include, :exclude, :root_path, :package_paths, :custom_associations, :load_paths, :inflections_file,
|
@@ -58,15 +58,19 @@ module Packwerk
|
|
58
58
|
(engine.config.autoload_paths + engine.config.eager_load_paths + engine.config.autoload_once_paths).uniq
|
59
59
|
end
|
60
60
|
|
61
|
-
|
62
|
-
|
61
|
+
bundle_path_match = Bundler.bundle_path.join("**").to_s
|
62
|
+
|
63
|
+
all_paths = all_paths.each_with_object([]) do |path_string, paths|
|
64
|
+
# ignore paths inside gems
|
63
65
|
path = Pathname.new(path_string)
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
|
67
|
+
next unless path.exist?
|
68
|
+
next if path.realpath.fnmatch(bundle_path_match)
|
69
|
+
|
70
|
+
paths << path.relative_path_from(Rails.root).to_s
|
67
71
|
end
|
68
72
|
|
69
|
-
all_paths.
|
73
|
+
all_paths.tap do |paths|
|
70
74
|
if paths.empty?
|
71
75
|
raise <<~EOS
|
72
76
|
No autoload paths have been set up in your Rails app. This is likely a bug, and
|
@@ -58,7 +58,7 @@ module Packwerk
|
|
58
58
|
#
|
59
59
|
# You can regenerate this file using the following command:
|
60
60
|
#
|
61
|
-
# bundle exec packwerk update #{@package.name}
|
61
|
+
# bundle exec packwerk update-deprecations #{@package.name}
|
62
62
|
MESSAGE
|
63
63
|
File.open(@filepath, "w") do |f|
|
64
64
|
f.write(message)
|
@@ -35,7 +35,7 @@ module Packwerk
|
|
35
35
|
return true
|
36
36
|
end
|
37
37
|
|
38
|
-
source_file_path = File.expand_path("
|
38
|
+
source_file_path = File.expand_path("templates/packwerk", __dir__)
|
39
39
|
FileUtils.cp(source_file_path, destination_file_path)
|
40
40
|
|
41
41
|
@out.puts("✅ Packwerk application validation bin script generated in #{destination_file_path}")
|
@@ -51,7 +51,7 @@ module Packwerk
|
|
51
51
|
return true
|
52
52
|
end
|
53
53
|
|
54
|
-
source_file_path = File.expand_path("
|
54
|
+
source_file_path = File.expand_path("templates/packwerk_validator_test.rb", __dir__)
|
55
55
|
FileUtils.cp(source_file_path, destination_file_path)
|
56
56
|
|
57
57
|
@out.puts("✅ Packwerk application validation test generated in #{destination_file_path}")
|
@@ -11,6 +11,10 @@ enforce_dependencies: true
|
|
11
11
|
# We recommend enabling this for any new packages you create to aid with encapsulation.
|
12
12
|
enforce_privacy: false
|
13
13
|
|
14
|
+
# By default the public path will be app/public/, however this may not suit all applications' architecture so
|
15
|
+
# this allows you to modify what your package's public path is.
|
16
|
+
# public_path: app/public/
|
17
|
+
|
14
18
|
# A list of this package's dependencies
|
15
19
|
# Note that packages in this list require their own `package.yml` file
|
16
20
|
# dependencies:
|
@@ -10,12 +10,12 @@ ENV["RAILS_ENV"] = "test"
|
|
10
10
|
packwerk_argv = ARGV.dup
|
11
11
|
|
12
12
|
begin
|
13
|
-
load(File.expand_path("
|
13
|
+
load(File.expand_path("spring", __dir__))
|
14
14
|
rescue LoadError => e
|
15
15
|
raise unless e.message.include?("spring")
|
16
16
|
end
|
17
17
|
|
18
|
-
require File.expand_path("
|
18
|
+
require File.expand_path("../config/environment", __dir__)
|
19
19
|
|
20
20
|
require "packwerk"
|
21
21
|
|
data/lib/packwerk/node.rb
CHANGED
@@ -103,8 +103,24 @@ module Packwerk
|
|
103
103
|
Location.new(location.line, location.column)
|
104
104
|
end
|
105
105
|
|
106
|
+
def method_call?(node)
|
107
|
+
type(node) == METHOD_CALL
|
108
|
+
end
|
109
|
+
|
110
|
+
def hash?(node)
|
111
|
+
type(node) == HASH
|
112
|
+
end
|
113
|
+
|
114
|
+
def string?(node)
|
115
|
+
type(node) == STRING
|
116
|
+
end
|
117
|
+
|
118
|
+
def symbol?(node)
|
119
|
+
type(node) == SYMBOL
|
120
|
+
end
|
121
|
+
|
106
122
|
def method_arguments(method_call_node)
|
107
|
-
raise TypeError unless
|
123
|
+
raise TypeError unless method_call?(method_call_node)
|
108
124
|
|
109
125
|
# (send (lvar :foo) :bar (int 1))
|
110
126
|
# "foo.bar(1)"
|
@@ -112,7 +128,7 @@ module Packwerk
|
|
112
128
|
end
|
113
129
|
|
114
130
|
def method_name(method_call_node)
|
115
|
-
raise TypeError unless
|
131
|
+
raise TypeError unless method_call?(method_call_node)
|
116
132
|
|
117
133
|
# (send (lvar :foo) :bar (int 1))
|
118
134
|
# "foo.bar(1)"
|
@@ -176,7 +192,7 @@ module Packwerk
|
|
176
192
|
end
|
177
193
|
|
178
194
|
def value_from_hash(hash_node, key)
|
179
|
-
raise TypeError unless
|
195
|
+
raise TypeError unless hash?(hash_node)
|
180
196
|
pair = hash_pairs(hash_node).detect { |pair_node| literal_value(hash_pair_key(pair_node)) == key }
|
181
197
|
hash_pair_value(pair) if pair
|
182
198
|
end
|
@@ -204,7 +220,7 @@ module Packwerk
|
|
204
220
|
end
|
205
221
|
|
206
222
|
def hash_pairs(hash_node)
|
207
|
-
raise TypeError unless
|
223
|
+
raise TypeError unless hash?(hash_node)
|
208
224
|
|
209
225
|
# (hash (pair (int 1) (int 2)) (pair (int 3) (int 4)))
|
210
226
|
# "{1 => 2, 3 => 4}"
|
@@ -222,7 +238,7 @@ module Packwerk
|
|
222
238
|
def module_creation?(node)
|
223
239
|
# "Class.new"
|
224
240
|
# "Module.new"
|
225
|
-
|
241
|
+
method_call?(node) &&
|
226
242
|
type(receiver(node)) == CONSTANT &&
|
227
243
|
["Class", "Module"].include?(constant_name(receiver(node))) &&
|
228
244
|
method_name(node) == :new
|
@@ -3,9 +3,21 @@
|
|
3
3
|
|
4
4
|
require "packwerk/node"
|
5
5
|
require "packwerk/offense"
|
6
|
+
require "packwerk/checker"
|
7
|
+
require "packwerk/reference_lister"
|
6
8
|
|
7
9
|
module Packwerk
|
8
10
|
class NodeProcessor
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
sig do
|
14
|
+
params(
|
15
|
+
reference_extractor: ReferenceExtractor,
|
16
|
+
reference_lister: ReferenceLister,
|
17
|
+
filename: String,
|
18
|
+
checkers: T::Array[Checker]
|
19
|
+
).void
|
20
|
+
end
|
9
21
|
def initialize(reference_extractor:, reference_lister:, filename:, checkers:)
|
10
22
|
@reference_extractor = reference_extractor
|
11
23
|
@reference_lister = reference_lister
|
data/lib/packwerk/package.rb
CHANGED
@@ -33,13 +33,20 @@ module Packwerk
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def public_path
|
36
|
-
@public_path ||= File.join(@name, "app/public/")
|
36
|
+
@public_path ||= File.join(@name, user_defined_public_path || "app/public/")
|
37
37
|
end
|
38
38
|
|
39
39
|
def public_path?(path)
|
40
40
|
path.start_with?(public_path)
|
41
41
|
end
|
42
42
|
|
43
|
+
def user_defined_public_path
|
44
|
+
return unless @config["public_path"]
|
45
|
+
return @config["public_path"] if @config["public_path"].end_with?("/")
|
46
|
+
|
47
|
+
@config["public_path"] + "/"
|
48
|
+
end
|
49
|
+
|
43
50
|
def <=>(other)
|
44
51
|
return nil unless other.is_a?(self.class)
|
45
52
|
name <=> other.name
|
data/lib/packwerk/package_set.rb
CHANGED
@@ -25,13 +25,15 @@ module Packwerk
|
|
25
25
|
new(packages)
|
26
26
|
end
|
27
27
|
|
28
|
-
private
|
29
|
-
|
30
28
|
def package_paths(root_path, package_pathspec)
|
29
|
+
bundle_path_match = Bundler.bundle_path.join("**").to_s
|
30
|
+
|
31
31
|
Dir.glob(File.join(root_path, package_pathspec, PACKAGE_CONFIG_FILENAME))
|
32
|
-
.map
|
32
|
+
.map { |path| Pathname.new(path) }.reject { |path| path.realpath.fnmatch(bundle_path_match) }
|
33
33
|
end
|
34
34
|
|
35
|
+
private
|
36
|
+
|
35
37
|
def create_root_package_if_none_in(packages)
|
36
38
|
return if packages.any?(&:root?)
|
37
39
|
packages << Package.new(name: Package::ROOT_PACKAGE_NAME, config: nil)
|
data/lib/packwerk/run_context.rb
CHANGED
@@ -39,6 +39,7 @@ module Packwerk
|
|
39
39
|
new(
|
40
40
|
root_path: configuration.root_path,
|
41
41
|
load_paths: configuration.load_paths,
|
42
|
+
package_paths: configuration.package_paths,
|
42
43
|
inflector: ActiveSupport::Inflector,
|
43
44
|
custom_associations: configuration.custom_associations,
|
44
45
|
reference_lister: default_reference_lister,
|
data/lib/packwerk/version.rb
CHANGED
data/packwerk.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.bindir = "exe"
|
34
34
|
spec.executables << "packwerk"
|
35
35
|
|
36
|
-
spec.files = Dir.chdir(
|
36
|
+
spec.files = Dir.chdir(__dir__) do
|
37
37
|
%x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
38
38
|
end
|
39
39
|
spec.require_paths = %w(lib)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packwerk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -185,6 +185,7 @@ files:
|
|
185
185
|
- lib/packwerk.rb
|
186
186
|
- lib/packwerk/application_validator.rb
|
187
187
|
- lib/packwerk/association_inspector.rb
|
188
|
+
- lib/packwerk/checker.rb
|
188
189
|
- lib/packwerk/checking_deprecated_references.rb
|
189
190
|
- lib/packwerk/cli.rb
|
190
191
|
- lib/packwerk/configuration.rb
|