Skip to content

Commit 658ac79

Browse files
authored
sanity check + initializer generator (stimulusreflex#105)
1 parent 9dfb072 commit 658ac79

File tree

5 files changed

+192
-0
lines changed

5 files changed

+192
-0
lines changed

Diff for: lib/cable_ready.rb

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require "rails/engine"
4+
require "open-uri"
45
require "active_record"
56
require "action_view"
67
require "active_support/all"
@@ -13,6 +14,7 @@
1314
require "cable_ready/operation_builder"
1415
require "cable_ready/config"
1516
require "cable_ready/broadcaster"
17+
require "cable_ready/sanity_checker"
1618
require "cable_ready/compoundable"
1719
require "cable_ready/channel"
1820
require "cable_ready/channels"
@@ -21,6 +23,10 @@
2123

2224
module CableReady
2325
class Engine < Rails::Engine
26+
initializer "cable_ready.sanity_check" do
27+
SanityChecker.check! unless Rails.env.production?
28+
end
29+
2430
initializer "renderer" do
2531
ActiveSupport.on_load(:action_controller) do
2632
ActionController::Renderers.add :operations do |operations, options|

Diff for: lib/cable_ready/config.rb

+3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ class Config
77
include Observable
88
include Singleton
99

10+
attr_accessor :on_failed_sanity_checks, :on_new_version_available
1011
attr_writer :verifier_key
1112

1213
def initialize
1314
super
1415
@operation_names = Set.new(default_operation_names)
16+
@on_failed_sanity_checks = :exit
17+
@on_new_version_available = :ignore
1518
end
1619

1720
def observers

Diff for: lib/cable_ready/sanity_checker.rb

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# frozen_string_literal: true
2+
3+
class CableReady::SanityChecker
4+
LATEST_VERSION_FORMAT = /^(\d+\.\d+\.\d+)$/
5+
NODE_VERSION_FORMAT = /(\d+\.\d+\.\d+.*):/
6+
JSON_VERSION_FORMAT = /(\d+\.\d+\.\d+.*)"/
7+
8+
class << self
9+
def check!
10+
return if CableReady.config.on_failed_sanity_checks == :ignore
11+
return if called_by_generate_config?
12+
13+
instance = new
14+
instance.check_javascript_package_version
15+
instance.check_new_version_available
16+
end
17+
18+
private
19+
20+
def called_by_generate_config?
21+
ARGV.include? "cable_ready:initializer"
22+
end
23+
end
24+
25+
def check_javascript_package_version
26+
if javascript_package_version.nil?
27+
warn_and_exit <<~WARN
28+
Can't locate the cable_ready npm package.
29+
Either add it to your package.json as a dependency or use "yarn link cable_ready" if you are doing development.
30+
WARN
31+
end
32+
33+
unless javascript_version_matches?
34+
warn_and_exit <<~WARN
35+
The cable_ready npm package version (#{javascript_package_version}) does not match the Rubygem version (#{gem_version}).
36+
To update the cable_ready npm package:
37+
yarn upgrade cable_ready@#{gem_version}
38+
WARN
39+
end
40+
end
41+
42+
def check_new_version_available
43+
return unless Rails.env.development?
44+
return if CableReady.config.on_new_version_available == :ignore
45+
return unless using_stable_release
46+
begin
47+
latest_version = URI.open("https://raw.githubusercontent.com/hopsoft/cable_ready/master/LATEST", open_timeout: 1, read_timeout: 1).read.strip
48+
if latest_version != CableReady::VERSION
49+
puts <<~WARN
50+
51+
There is a new version of CableReady available!
52+
Current: #{CableReady::VERSION} Latest: #{latest_version}
53+
54+
If you upgrade, it is very important that you update BOTH Gemfile and package.json
55+
Then, run `bundle install && yarn install` to update to #{latest_version}.
56+
57+
WARN
58+
exit if CableReady.config.on_new_version_available == :exit
59+
end
60+
rescue
61+
puts "CableReady #{CableReady::VERSION} update check skipped: connection timeout"
62+
end
63+
end
64+
65+
private
66+
67+
def javascript_version_matches?
68+
javascript_package_version == gem_version
69+
end
70+
71+
def using_stable_release
72+
stable = CableReady::VERSION.match?(LATEST_VERSION_FORMAT)
73+
puts "CableReady #{CableReady::VERSION} update check skipped: pre-release build" unless stable
74+
stable
75+
end
76+
77+
def gem_version
78+
@_gem_version ||= CableReady::VERSION.gsub(".pre", "-pre")
79+
end
80+
81+
def javascript_package_version
82+
@_js_version ||= find_javascript_package_version
83+
end
84+
85+
def find_javascript_package_version
86+
if (match = search_file(package_json_path, regex: /version/))
87+
match[JSON_VERSION_FORMAT, 1]
88+
elsif (match = search_file(yarn_lock_path, regex: /^cable_ready/))
89+
match[NODE_VERSION_FORMAT, 1]
90+
end
91+
end
92+
93+
def search_file(path, regex:)
94+
return unless File.exist?(path)
95+
File.foreach(path).grep(regex).first
96+
end
97+
98+
def package_json_path
99+
Rails.root.join("node_modules", "cable_ready", "package.json")
100+
end
101+
102+
def yarn_lock_path
103+
Rails.root.join("yarn.lock")
104+
end
105+
106+
def initializer_path
107+
@_initializer_path ||= Rails.root.join("config", "initializers", "cable_ready.rb")
108+
end
109+
110+
def warn_and_exit(text)
111+
puts "WARNING:"
112+
puts text
113+
exit_with_info if CableReady.config.on_failed_sanity_checks == :exit
114+
end
115+
116+
def exit_with_info
117+
puts
118+
119+
if File.exist?(initializer_path)
120+
puts <<~INFO
121+
If you know what you are doing and you want to start the application anyway,
122+
you can add the following directive to the CableReady initializer,
123+
which is located at #{initializer_path}
124+
125+
CableReady.configure do |config|
126+
config.on_failed_sanity_checks = :warn
127+
end
128+
129+
INFO
130+
else
131+
puts <<~INFO
132+
If you know what you are doing and you want to start the application anyway,
133+
you can create a CableReady initializer with the command:
134+
135+
bundle exec rails generate cable_ready:config
136+
137+
Then open your initializer at
138+
139+
#{initializer_path}
140+
141+
and then add the following directive:
142+
143+
CableReady.configure do |config|
144+
config.on_failed_sanity_checks = :warn
145+
end
146+
147+
INFO
148+
end
149+
exit false unless Rails.env.test?
150+
end
151+
end

Diff for: lib/generators/cable_ready/initializer_generator.rb

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# frozen_string_literal: true
2+
3+
require "rails/generators"
4+
5+
module CableReady
6+
class InitializerGenerator < Rails::Generators::Base
7+
desc "Creates a CableReady initializer template in config/initializers"
8+
source_root File.expand_path("templates", __dir__)
9+
10+
def copy_initializer_file
11+
copy_file "config/initializers/cable_ready.rb"
12+
end
13+
end
14+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# frozen_string_literal: true
2+
3+
CableReady.configure do |config|
4+
# Enable/disable exiting / warning when the sanity checks fail options:
5+
# `:exit` or `:warn` or `:ignore`
6+
7+
# config.on_failed_sanity_checks = :exit
8+
9+
# Enable/disable exiting / warning when there's a new CableReady release
10+
# `:exit` or `:warn` or `:ignore`
11+
12+
# config.on_new_version_available = :ignore
13+
14+
# Define your own custom operations
15+
# https://cableready.stimulusreflex.com/customization#custom-operations
16+
17+
# config.add_operation_name :jazz_hands
18+
end

0 commit comments

Comments
 (0)