react-manifest-rails 0.2.21 → 0.2.22
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/README.md +12 -0
- data/lib/react_manifest/generator.rb +13 -0
- data/lib/react_manifest/scanner.rb +38 -3
- data/lib/react_manifest/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c87f68d7ed8248c19732ce3b946a1207ed85907a92bd39ab5a2eda665f5b001e
|
|
4
|
+
data.tar.gz: 7ee42c73f25048a31d8ca713d0cdfc23b344eb99ec68d1f72c58b5cfda3b635d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d71e1c8b255678a3b1a72df766134b80dadd8bf7553d4380e240d3a8b526dff5e6f6ef848574b93c86f6778feef896cc04b945a0f020d03d0bccf034acfe7d74
|
|
7
|
+
data.tar.gz: 874538d0cd06e8b8a121d9343a3846649b6612cd3ad4bb8c0c28a7c1589c1e05bf2f48b80ae0fe6a8af478d07a3d4309d9a5bc692536f4cdebeeed90b89ca74c
|
data/README.md
CHANGED
|
@@ -235,6 +235,18 @@ If you see errors like `UserSignInForm is not defined` (often from `eval` inside
|
|
|
235
235
|
|
|
236
236
|
Using `defer: true` can cause `react_component` inline scripts to run before your `ux_*.js` bundles are executed.
|
|
237
237
|
|
|
238
|
+
### `Identifier '<Name>' has already been declared`
|
|
239
|
+
|
|
240
|
+
This usually means the same component/function is being loaded from two separate bundles.
|
|
241
|
+
|
|
242
|
+
Common cause: a file outside `ux/` (for example `app/assets/javascripts/components/navbar/*` loaded by `application.js`) references a symbol defined in `ux/app/<controller>/...`, while that controller bundle is also loaded via `react_bundle_tag`.
|
|
243
|
+
|
|
244
|
+
Recommended fix:
|
|
245
|
+
- Move globally reused symbols out of `ux/app/*` into a shared dir (`ux/components`, `ux/hooks`, `ux/lib`) so they are emitted once via `ux_shared.js`.
|
|
246
|
+
- Keep controller-specific symbols in `ux/app/*` and avoid importing/using them from non-ux global assets.
|
|
247
|
+
|
|
248
|
+
If you use `external_roots`, `react_manifest:analyze` and generation warnings will now flag this pattern explicitly.
|
|
249
|
+
|
|
238
250
|
## Compatibility
|
|
239
251
|
|
|
240
252
|
- Ruby: 3.2+
|
|
@@ -132,6 +132,8 @@ module ReactManifest
|
|
|
132
132
|
next
|
|
133
133
|
end
|
|
134
134
|
|
|
135
|
+
warn_on_external_controller_references(file_path, symbol_to_bundle)
|
|
136
|
+
|
|
135
137
|
extract_defined_symbols(file_path).each do |sym|
|
|
136
138
|
external_symbol_to_require[sym] ||= req_path
|
|
137
139
|
end
|
|
@@ -372,6 +374,17 @@ module ReactManifest
|
|
|
372
374
|
path.to_s.sub(/\.js\.jsx$/, "").sub(/\.jsx$/, "").sub(/\.js$/, "")
|
|
373
375
|
end
|
|
374
376
|
|
|
377
|
+
def warn_on_external_controller_references(file_path, symbol_to_bundle)
|
|
378
|
+
extract_used_component_symbols(file_path).each do |sym|
|
|
379
|
+
dep_bundle = symbol_to_bundle[sym]
|
|
380
|
+
next unless dep_bundle
|
|
381
|
+
|
|
382
|
+
warn "[ReactManifest] External file '#{relative_require_path(file_path)}' references " \
|
|
383
|
+
"controller-only symbol '#{sym}' (#{dep_bundle}). " \
|
|
384
|
+
"Move '#{sym}' to a shared ux dir to avoid duplicate runtime declarations."
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
375
388
|
def auto_generated?(path)
|
|
376
389
|
# Avoid TOCTOU: don't check existence separately — just attempt the read
|
|
377
390
|
# and treat a missing/unreadable file as not auto-generated.
|
|
@@ -57,7 +57,8 @@ module ReactManifest
|
|
|
57
57
|
Object Array String Number Boolean Symbol Map Set WeakMap
|
|
58
58
|
].freeze
|
|
59
59
|
|
|
60
|
-
Result = Struct.new(:symbol_index, :controller_usages, :warnings, :shared_violations,
|
|
60
|
+
Result = Struct.new(:symbol_index, :controller_usages, :warnings, :shared_violations,
|
|
61
|
+
:external_violations, keyword_init: true)
|
|
61
62
|
|
|
62
63
|
def initialize(config = ReactManifest.configuration)
|
|
63
64
|
@config = config
|
|
@@ -67,6 +68,7 @@ module ReactManifest
|
|
|
67
68
|
def scan(classification)
|
|
68
69
|
warnings = []
|
|
69
70
|
symbol_index = {}
|
|
71
|
+
external_file_paths = {} # file_path => relative_require_path for external_roots files
|
|
70
72
|
|
|
71
73
|
# Phase 1a: index symbols from shared dirs
|
|
72
74
|
shared_file_paths = {} # file_path => relative_require_path for all shared files
|
|
@@ -90,7 +92,8 @@ module ReactManifest
|
|
|
90
92
|
abs_root = abs_external_root(root_path)
|
|
91
93
|
js_files_in(abs_root).each do |file_path|
|
|
92
94
|
relative = relative_require_path(file_path)
|
|
93
|
-
|
|
95
|
+
external_file_paths[file_path] = relative
|
|
96
|
+
symbols = extract_definitions(file_path)
|
|
94
97
|
symbols.each do |sym|
|
|
95
98
|
symbol_index[sym] ||= relative
|
|
96
99
|
end
|
|
@@ -119,6 +122,7 @@ module ReactManifest
|
|
|
119
122
|
|
|
120
123
|
# Phase 1e: detect shared files that use app-dir (controller) symbols
|
|
121
124
|
shared_violations = detect_shared_violations(shared_file_paths, controller_symbol_index, warnings)
|
|
125
|
+
external_violations = detect_external_root_violations(external_file_paths, controller_symbol_index, warnings)
|
|
122
126
|
|
|
123
127
|
# Phase 2: scan controller dirs for usage
|
|
124
128
|
controller_usages = {}
|
|
@@ -147,7 +151,8 @@ module ReactManifest
|
|
|
147
151
|
symbol_index: symbol_index,
|
|
148
152
|
controller_usages: controller_usages,
|
|
149
153
|
warnings: warnings,
|
|
150
|
-
shared_violations: shared_violations
|
|
154
|
+
shared_violations: shared_violations,
|
|
155
|
+
external_violations: external_violations
|
|
151
156
|
)
|
|
152
157
|
end
|
|
153
158
|
# rubocop:enable Metrics/MethodLength,Metrics/AbcSize,Metrics/PerceivedComplexity
|
|
@@ -229,6 +234,36 @@ module ReactManifest
|
|
|
229
234
|
violations
|
|
230
235
|
end
|
|
231
236
|
|
|
237
|
+
def detect_external_root_violations(external_file_paths, controller_symbol_index, warnings)
|
|
238
|
+
violations = []
|
|
239
|
+
external_file_paths.each do |file_path, relative|
|
|
240
|
+
content = begin
|
|
241
|
+
File.read(file_path, encoding: "utf-8")
|
|
242
|
+
rescue Errno::ENOENT, Errno::EACCES, Encoding::InvalidByteSequenceError
|
|
243
|
+
next
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
local_syms = Set.new
|
|
247
|
+
DEFINITION_PATTERNS.each { |p| content.scan(p) { |m| local_syms << m[0] } }
|
|
248
|
+
|
|
249
|
+
[PASCAL_TOKEN_PATTERN, HOOK_TOKEN_PATTERN].each do |pattern|
|
|
250
|
+
content.scan(pattern) do |match|
|
|
251
|
+
sym = match[0]
|
|
252
|
+
next if local_syms.include?(sym)
|
|
253
|
+
next unless controller_symbol_index.key?(sym)
|
|
254
|
+
|
|
255
|
+
info = controller_symbol_index[sym]
|
|
256
|
+
violations << { external_file: relative, symbol: sym,
|
|
257
|
+
controller: info[:controller], app_file: info[:file] }
|
|
258
|
+
warnings << "External file '#{relative}' uses app-dir symbol '#{sym}' " \
|
|
259
|
+
"(from ux/app/#{info[:controller]}). " \
|
|
260
|
+
"Move '#{sym}' into a shared ux dir to avoid duplicate runtime declarations."
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
violations
|
|
265
|
+
end
|
|
266
|
+
|
|
232
267
|
# Count how many controllers use each shared file
|
|
233
268
|
def emit_fanout_warnings(controller_usages, warnings)
|
|
234
269
|
fanout = Hash.new(0)
|