packwerk 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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
|
-
[](https://
|
21
|
+
[](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
|

|
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
|