-
-
Notifications
You must be signed in to change notification settings - Fork 635
/
Copy pathversion_checker.rb
131 lines (105 loc) · 4.44 KB
/
version_checker.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# frozen_string_literal: true
module ReactOnRails
# Responsible for checking versions of rubygem versus yarn node package
# against each other at runtime.
class VersionChecker
attr_reader :node_package_version
MAJOR_MINOR_PATCH_VERSION_REGEX = /(\d+)\.(\d+)\.(\d+)/
def self.build
new(NodePackageVersion.build)
end
def initialize(node_package_version)
@node_package_version = node_package_version
end
# For compatibility, the gem and the node package versions should always match,
# unless the user really knows what they're doing. So we will give a
# warning if they do not.
def log_if_gem_and_node_package_versions_differ
return if node_package_version.raw.nil? || node_package_version.local_path_or_url?
return log_node_semver_version_warning if node_package_version.semver_wildcard?
node_major_minor_patch = node_package_version.major_minor_patch
gem_major_minor_patch = gem_major_minor_patch_version
versions_match = node_major_minor_patch[0] == gem_major_minor_patch[0] &&
node_major_minor_patch[1] == gem_major_minor_patch[1] &&
node_major_minor_patch[2] == gem_major_minor_patch[2]
log_differing_versions_warning unless versions_match
end
private
def common_error_msg
<<-MSG.strip_heredoc
Detected: #{node_package_version.raw}
gem: #{gem_version}
Ensure the installed version of the gem is the same as the version of
your installed node package. Do not use >= or ~> in your Gemfile for react_on_rails.
Do not use ^ or ~ in your package.json for react-on-rails.
Run `yarn add react-on-rails --exact` in the directory containing folder node_modules.
MSG
end
def log_differing_versions_warning
msg = "**WARNING** ReactOnRails: ReactOnRails gem and node package versions do not match\n#{common_error_msg}"
Rails.logger.warn(msg)
end
def log_node_semver_version_warning
msg = "**WARNING** ReactOnRails: Your node package version for react-on-rails contains a " \
"^ or ~\n#{common_error_msg}"
Rails.logger.warn(msg)
end
def gem_version
ReactOnRails::VERSION
end
def gem_major_minor_patch_version
match = gem_version.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
[match[1], match[2], match[3]]
end
class NodePackageVersion
attr_reader :package_json
def self.build
new(package_json_path)
end
def self.package_json_path
Rails.root.join(ReactOnRails.configuration.node_modules_location, "package.json")
end
def initialize(package_json)
@package_json = package_json
end
def raw
return @raw if defined?(@raw)
if File.exist?(package_json)
parsed_package_contents = JSON.parse(package_json_contents)
if parsed_package_contents.key?("dependencies") &&
parsed_package_contents["dependencies"].key?("react-on-rails")
return @raw = parsed_package_contents["dependencies"]["react-on-rails"]
end
end
msg = "No 'react-on-rails' entry in the dependencies of #{NodePackageVersion.package_json_path}, " \
"which is the expected location according to ReactOnRails.configuration.node_modules_location"
Rails.logger.warn(msg)
@raw = nil
end
def semver_wildcard?
# See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
# We want to disallow all expressions other than exact versions
# and the ones allowed by local_path_or_url?
raw.blank? || raw.match(/[~^><|*-]/).present?
end
def local_path_or_url?
# See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
# All path and protocol "version ranges" include / somewhere,
# but we want to make an exception for npm:@scope/pkg@version.
!raw.nil? && raw.include?("/") && !raw.start_with?("npm:")
end
def major_minor_patch
return if local_path_or_url?
match = raw.match(MAJOR_MINOR_PATCH_VERSION_REGEX)
unless match
raise ReactOnRails::Error, "Cannot parse version number '#{raw}' (only exact versions are supported)"
end
[match[1], match[2], match[3]]
end
private
def package_json_contents
@package_json_contents ||= File.read(package_json)
end
end
end
end