cable_ready 4.5.0 → 5.0.0.pre3
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/CHANGELOG.md +260 -161
- data/Gemfile.lock +141 -96
- data/LATEST +1 -0
- data/README.md +13 -13
- data/Rakefile +8 -2
- data/app/channels/cable_ready/stream.rb +12 -0
- data/app/helpers/cable_ready_helper.rb +11 -0
- data/app/jobs/cable_ready_broadcast_job.rb +14 -0
- data/bin/standardize +1 -1
- data/cable_ready.gemspec +3 -2
- data/lib/cable_ready.rb +40 -5
- data/lib/cable_ready/broadcaster.rb +3 -4
- data/lib/cable_ready/cable_car.rb +17 -0
- data/lib/cable_ready/channel.rb +12 -32
- data/lib/cable_ready/channels.rb +4 -7
- data/lib/cable_ready/compoundable.rb +11 -0
- data/lib/cable_ready/config.rb +17 -5
- data/lib/cable_ready/identifiable.rb +30 -0
- data/lib/cable_ready/operation_builder.rb +80 -0
- data/lib/cable_ready/sanity_checker.rb +151 -0
- data/lib/cable_ready/stream_identifier.rb +13 -0
- data/lib/cable_ready/version.rb +1 -1
- data/lib/generators/cable_ready/channel_generator.rb +71 -0
- data/lib/generators/cable_ready/initializer_generator.rb +14 -0
- data/lib/generators/cable_ready/stream_from_generator.rb +43 -0
- data/lib/generators/cable_ready/templates/config/initializers/cable_ready.rb +18 -0
- data/package.json +10 -5
- data/test/lib/cable_ready/cable_car_test.rb +50 -0
- data/test/lib/cable_ready/identifiable_test.rb +75 -0
- data/test/lib/cable_ready/operation_builder_test.rb +189 -0
- data/test/lib/generators/cable_ready/channel_generator_test.rb +157 -0
- data/test/support/generator_test_helpers.rb +28 -0
- data/test/test_helper.rb +15 -0
- data/yarn.lock +137 -127
- metadata +47 -8
- data/tags +0 -62
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CableReadyBroadcastJob < (defined?(ActiveJob::Base) ? ActiveJob::Base : Object)
|
4
|
+
include CableReady::Broadcaster
|
5
|
+
queue_as :default if defined?(ActiveJob::Base)
|
6
|
+
|
7
|
+
def perform(identifier:, operations:, model: nil)
|
8
|
+
if model.present?
|
9
|
+
cable_ready[identifier.safe_constantize].apply!(operations).broadcast_to(model)
|
10
|
+
else
|
11
|
+
cable_ready[identifier].apply!(operations).broadcast
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/bin/standardize
CHANGED
data/cable_ready.gemspec
CHANGED
@@ -8,10 +8,10 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = CableReady::VERSION
|
9
9
|
gem.authors = ["Nathan Hopkins"]
|
10
10
|
gem.email = ["natehop@gmail.com"]
|
11
|
-
gem.homepage = "https://github.com/
|
11
|
+
gem.homepage = "https://github.com/stimulusreflex/cable_ready"
|
12
12
|
gem.summary = "Out-of-Band Server Triggered DOM Operations"
|
13
13
|
|
14
|
-
gem.files = Dir["lib/**/*.rb", "app
|
14
|
+
gem.files = Dir["lib/**/*.rb", "app/**/*.rb", "bin/*", "[A-Z]*"]
|
15
15
|
gem.test_files = Dir["test/**/*.rb"]
|
16
16
|
|
17
17
|
gem.add_dependency "rails", ">= 5.2"
|
@@ -23,4 +23,5 @@ Gem::Specification.new do |gem|
|
|
23
23
|
gem.add_development_dependency "pry-nav"
|
24
24
|
gem.add_development_dependency "rake"
|
25
25
|
gem.add_development_dependency "standardrb"
|
26
|
+
gem.add_development_dependency "mocha"
|
26
27
|
end
|
data/lib/cable_ready.rb
CHANGED
@@ -1,20 +1,55 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rails/engine"
|
4
|
+
require "open-uri"
|
5
|
+
require "active_record"
|
6
|
+
require "action_view"
|
4
7
|
require "active_support/all"
|
8
|
+
require "thread/local"
|
9
|
+
require "monitor"
|
10
|
+
require "observer"
|
11
|
+
require "singleton"
|
5
12
|
require "cable_ready/version"
|
13
|
+
require "cable_ready/identifiable"
|
14
|
+
require "cable_ready/operation_builder"
|
6
15
|
require "cable_ready/config"
|
7
16
|
require "cable_ready/broadcaster"
|
17
|
+
require "cable_ready/sanity_checker"
|
18
|
+
require "cable_ready/compoundable"
|
19
|
+
require "cable_ready/channel"
|
20
|
+
require "cable_ready/channels"
|
21
|
+
require "cable_ready/cable_car"
|
22
|
+
require "cable_ready/stream_identifier"
|
8
23
|
|
9
24
|
module CableReady
|
10
25
|
class Engine < Rails::Engine
|
11
|
-
|
26
|
+
initializer "cable_ready.sanity_check" do
|
27
|
+
SanityChecker.check! unless Rails.env.production?
|
28
|
+
end
|
29
|
+
|
30
|
+
initializer "renderer" do
|
31
|
+
ActiveSupport.on_load(:action_controller) do
|
32
|
+
ActionController::Renderers.add :operations do |operations, options|
|
33
|
+
response.content_type ||= Mime[:cable_ready]
|
34
|
+
render json: operations.dispatch
|
35
|
+
end
|
12
36
|
|
13
|
-
|
14
|
-
|
37
|
+
Mime::Type.register "application/vnd.cable-ready.json", :cable_ready
|
38
|
+
end
|
39
|
+
end
|
15
40
|
end
|
16
41
|
|
17
|
-
|
18
|
-
|
42
|
+
class << self
|
43
|
+
def config
|
44
|
+
CableReady::Config.instance
|
45
|
+
end
|
46
|
+
|
47
|
+
def configure
|
48
|
+
yield config
|
49
|
+
end
|
50
|
+
|
51
|
+
def signed_stream_verifier
|
52
|
+
@signed_stream_verifier ||= ActiveSupport::MessageVerifier.new(config.verifier_key, digest: "SHA256", serializer: JSON)
|
53
|
+
end
|
19
54
|
end
|
20
55
|
end
|
@@ -1,17 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "channels"
|
4
|
-
|
5
3
|
module CableReady
|
6
4
|
module Broadcaster
|
5
|
+
include Identifiable
|
7
6
|
extend ::ActiveSupport::Concern
|
8
7
|
|
9
8
|
def cable_ready
|
10
9
|
CableReady::Channels.instance
|
11
10
|
end
|
12
11
|
|
13
|
-
def
|
14
|
-
|
12
|
+
def cable_car
|
13
|
+
CableReady::CableCar.instance
|
15
14
|
end
|
16
15
|
end
|
17
16
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CableReady
|
4
|
+
class CableCar < OperationBuilder
|
5
|
+
extend Thread::Local
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super "CableCar"
|
9
|
+
end
|
10
|
+
|
11
|
+
def dispatch(clear: true)
|
12
|
+
payload = operations_payload
|
13
|
+
reset! if clear
|
14
|
+
payload
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/cable_ready/channel.rb
CHANGED
@@ -1,47 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module CableReady
|
4
|
-
class Channel
|
5
|
-
attr_reader :identifier
|
6
|
-
|
7
|
-
def initialize(identifier)
|
8
|
-
@identifier = identifier
|
9
|
-
reset
|
10
|
-
CableReady.config.operation_names.each { |name| add_operation_method name }
|
11
|
-
|
12
|
-
config_observer = self
|
13
|
-
CableReady.config.add_observer config_observer, :add_operation_method
|
14
|
-
ObjectSpace.define_finalizer self, -> { CableReady.config.delete_observer config_observer }
|
15
|
-
end
|
4
|
+
class Channel < OperationBuilder
|
5
|
+
attr_reader :identifier
|
16
6
|
|
17
7
|
def broadcast(clear: true)
|
18
|
-
ActionCable.server.broadcast identifier, {"cableReady" => true, "operations" =>
|
19
|
-
reset if clear
|
8
|
+
ActionCable.server.broadcast identifier, {"cableReady" => true, "operations" => operations_payload}
|
9
|
+
reset! if clear
|
20
10
|
end
|
21
11
|
|
22
12
|
def broadcast_to(model, clear: true)
|
23
|
-
identifier.broadcast_to model, {"cableReady" => true, "operations" =>
|
24
|
-
reset if clear
|
13
|
+
identifier.broadcast_to model, {"cableReady" => true, "operations" => operations_payload}
|
14
|
+
reset! if clear
|
25
15
|
end
|
26
16
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
enqueued_operations[name.to_s] << options.stringify_keys
|
31
|
-
self # supports operation chaining
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def reset
|
38
|
-
@enqueued_operations = Hash.new { |hash, key| hash[key] = [] }
|
17
|
+
def broadcast_later(clear: true)
|
18
|
+
CableReadyBroadcastJob.perform_later(identifier: identifier, operations: operations_payload)
|
19
|
+
reset! if clear
|
39
20
|
end
|
40
21
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
.deep_transform_keys! { |key| key.to_s.camelize(:lower) }
|
22
|
+
def broadcast_later_to(model, clear: true)
|
23
|
+
CableReadyBroadcastJob.perform_later(identifier: identifier.name, operations: operations_payload, model: model)
|
24
|
+
reset! if clear
|
45
25
|
end
|
46
26
|
end
|
47
27
|
end
|
data/lib/cable_ready/channels.rb
CHANGED
@@ -1,22 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "thread/local"
|
4
|
-
require_relative "channel"
|
5
|
-
|
6
3
|
module CableReady
|
7
4
|
# This class is a thread local singleton: CableReady::Channels.instance
|
8
5
|
# SEE: https://github.com/socketry/thread-local/tree/master/guides/getting-started
|
9
6
|
class Channels
|
7
|
+
include Compoundable
|
10
8
|
extend Thread::Local
|
11
9
|
|
12
|
-
attr_accessor :operations
|
13
|
-
|
14
10
|
def initialize
|
15
11
|
@channels = {}
|
16
|
-
@operations = {}
|
17
12
|
end
|
18
13
|
|
19
|
-
def [](
|
14
|
+
def [](*keys)
|
15
|
+
keys.select!(&:itself)
|
16
|
+
identifier = keys.many? || (keys.one? && keys.first.is_a?(ActiveRecord::Base)) ? compound(keys) : keys.pop
|
20
17
|
@channels[identifier] ||= CableReady::Channel.new(identifier)
|
21
18
|
end
|
22
19
|
|
data/lib/cable_ready/config.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "monitor"
|
4
|
-
require "observer"
|
5
|
-
require "singleton"
|
6
|
-
|
7
3
|
module CableReady
|
8
4
|
# This class is a process level singleton shared by all threads: CableReady::Config.instance
|
9
5
|
class Config
|
@@ -11,9 +7,22 @@ module CableReady
|
|
11
7
|
include Observable
|
12
8
|
include Singleton
|
13
9
|
|
10
|
+
attr_accessor :on_failed_sanity_checks, :on_new_version_available
|
11
|
+
attr_writer :verifier_key
|
12
|
+
|
14
13
|
def initialize
|
15
14
|
super
|
16
15
|
@operation_names = Set.new(default_operation_names)
|
16
|
+
@on_failed_sanity_checks = :exit
|
17
|
+
@on_new_version_available = :ignore
|
18
|
+
end
|
19
|
+
|
20
|
+
def observers
|
21
|
+
@observer_peers&.keys || []
|
22
|
+
end
|
23
|
+
|
24
|
+
def verifier_key
|
25
|
+
@verifier_key || Rails.application.key_generator.generate_key("cable_ready/verifier_key")
|
17
26
|
end
|
18
27
|
|
19
28
|
def operation_names
|
@@ -33,6 +42,7 @@ module CableReady
|
|
33
42
|
append
|
34
43
|
clear_storage
|
35
44
|
console_log
|
45
|
+
console_table
|
36
46
|
dispatch_event
|
37
47
|
go
|
38
48
|
graft
|
@@ -42,9 +52,10 @@ module CableReady
|
|
42
52
|
morph
|
43
53
|
notification
|
44
54
|
outer_html
|
45
|
-
play_sound
|
46
55
|
prepend
|
47
56
|
push_state
|
57
|
+
redirect_to
|
58
|
+
reload
|
48
59
|
remove
|
49
60
|
remove_attribute
|
50
61
|
remove_css_class
|
@@ -56,6 +67,7 @@ module CableReady
|
|
56
67
|
set_cookie
|
57
68
|
set_dataset_property
|
58
69
|
set_focus
|
70
|
+
set_meta
|
59
71
|
set_property
|
60
72
|
set_storage_item
|
61
73
|
set_style
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CableReady
|
4
|
+
module Identifiable
|
5
|
+
def dom_id(record, prefix = nil)
|
6
|
+
return record.to_dom_selector if record.respond_to?(:to_dom_selector)
|
7
|
+
|
8
|
+
prefix = prefix.to_s.strip if prefix
|
9
|
+
|
10
|
+
id = if record.respond_to?(:to_dom_id)
|
11
|
+
record.to_dom_id
|
12
|
+
elsif record.is_a?(ActiveRecord::Relation)
|
13
|
+
[prefix, record.model_name.plural].compact.join("_")
|
14
|
+
elsif record.is_a?(ActiveRecord::Base)
|
15
|
+
ActionView::RecordIdentifier.dom_id(record, prefix)
|
16
|
+
else
|
17
|
+
[prefix, record.to_s.strip].compact.join("_")
|
18
|
+
end
|
19
|
+
|
20
|
+
"##{id}".squeeze("#").strip.downcase
|
21
|
+
end
|
22
|
+
|
23
|
+
def identifiable?(obj)
|
24
|
+
obj.respond_to?(:to_dom_selector) ||
|
25
|
+
obj.respond_to?(:to_dom_id) ||
|
26
|
+
obj.is_a?(ActiveRecord::Relation) ||
|
27
|
+
obj.is_a?(ActiveRecord::Base)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CableReady
|
4
|
+
class OperationBuilder
|
5
|
+
include Identifiable
|
6
|
+
attr_reader :identifier, :previous_selector
|
7
|
+
|
8
|
+
def self.finalizer_for(identifier)
|
9
|
+
proc {
|
10
|
+
channel = CableReady.config.observers.find { |o| o.try(:identifier) == identifier }
|
11
|
+
CableReady.config.delete_observer channel if channel
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(identifier)
|
16
|
+
@identifier = identifier
|
17
|
+
|
18
|
+
reset!
|
19
|
+
CableReady.config.operation_names.each { |name| add_operation_method name }
|
20
|
+
CableReady.config.add_observer self, :add_operation_method
|
21
|
+
ObjectSpace.define_finalizer self, self.class.finalizer_for(identifier)
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_operation_method(name)
|
25
|
+
return if respond_to?(name)
|
26
|
+
singleton_class.public_send :define_method, name, ->(*args) {
|
27
|
+
if args.one? && args.first.respond_to?(:to_operation_options) && [Array, Hash].include?(args.first.to_operation_options.class)
|
28
|
+
case args.first.to_operation_options
|
29
|
+
when Array
|
30
|
+
selector, options = nil, args.first.to_operation_options
|
31
|
+
.select { |e| e.is_a?(Symbol) && args.first.respond_to?("to_#{e}".to_sym) }
|
32
|
+
.each_with_object({}) { |option, memo| memo[option.to_s] = args.first.send("to_#{option}".to_sym) }
|
33
|
+
when Hash
|
34
|
+
selector, options = nil, args.first.to_operation_options
|
35
|
+
else
|
36
|
+
raise TypeError, ":to_operation_options returned an #{args.first.to_operation_options.class.name}. Must be an Array or Hash."
|
37
|
+
end
|
38
|
+
else
|
39
|
+
selector, options = nil, args.first || {} # 1 or 0 params
|
40
|
+
selector, options = options, {} unless options.is_a?(Hash) # swap if only selector provided
|
41
|
+
selector, options = args[0, 2] if args.many? # 2 or more params
|
42
|
+
options.stringify_keys!
|
43
|
+
options.each { |key, value| options[key] = value.send("to_#{key}".to_sym) if value.respond_to?("to_#{key}".to_sym) }
|
44
|
+
end
|
45
|
+
options["selector"] = selector if selector && options.exclude?("selector")
|
46
|
+
options["selector"] = previous_selector if previous_selector && options.exclude?("selector")
|
47
|
+
if options.include?("selector")
|
48
|
+
@previous_selector = options["selector"]
|
49
|
+
options["selector"] = identifiable?(previous_selector) ? dom_id(previous_selector) : previous_selector
|
50
|
+
end
|
51
|
+
options["operation"] = name.to_s.camelize(:lower)
|
52
|
+
@enqueued_operations << options
|
53
|
+
self
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_json(*args)
|
58
|
+
@enqueued_operations.to_json(*args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def apply!(operations = "[]")
|
62
|
+
operations = begin
|
63
|
+
JSON.parse(operations.is_a?(String) ? operations : operations.to_json)
|
64
|
+
rescue JSON::ParserError
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
@enqueued_operations.push(operations)
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def operations_payload
|
72
|
+
@enqueued_operations.map { |operation| operation.deep_transform_keys! { |key| key.to_s.camelize(:lower) } }
|
73
|
+
end
|
74
|
+
|
75
|
+
def reset!
|
76
|
+
@enqueued_operations = []
|
77
|
+
@previous_selector = nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -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 ENV["SKIP_SANITY_CHECK"]
|
11
|
+
return if CableReady.config.on_failed_sanity_checks == :ignore
|
12
|
+
return if called_by_generate_config?
|
13
|
+
return if called_by_rake?
|
14
|
+
|
15
|
+
instance = new
|
16
|
+
instance.check_package_versions_match
|
17
|
+
instance.check_new_version_available
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def called_by_generate_config?
|
23
|
+
ARGV.include?("cable_ready:initializer")
|
24
|
+
end
|
25
|
+
|
26
|
+
def called_by_rake?
|
27
|
+
File.basename($PROGRAM_NAME) == "rake"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def check_package_versions_match
|
32
|
+
if npm_version.nil?
|
33
|
+
warn_and_exit <<~WARN
|
34
|
+
👉 Can't locate the cable_ready npm package.
|
35
|
+
|
36
|
+
yarn add cable_ready@#{gem_version}
|
37
|
+
|
38
|
+
Either add it to your package.json as a dependency or use "yarn link cable_ready" if you are doing development.
|
39
|
+
WARN
|
40
|
+
end
|
41
|
+
|
42
|
+
if package_version_mismatch?
|
43
|
+
warn_and_exit <<~WARN
|
44
|
+
👉 The cable_ready npm package version (#{npm_version}) does not match the Rubygem version (#{gem_version}).
|
45
|
+
|
46
|
+
To update the cable_ready npm package:
|
47
|
+
|
48
|
+
yarn upgrade cable_ready@#{gem_version}
|
49
|
+
WARN
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_new_version_available
|
54
|
+
return if CableReady.config.on_new_version_available == :ignore
|
55
|
+
return if Rails.env.development? == false
|
56
|
+
return if using_preview_release?
|
57
|
+
begin
|
58
|
+
latest_version = URI.open("https://raw.githubusercontent.com/stimulusreflex/cable_ready/master/LATEST", open_timeout: 1, read_timeout: 1).read.strip
|
59
|
+
if latest_version != CableReady::VERSION
|
60
|
+
puts <<~WARN
|
61
|
+
|
62
|
+
👉 There is a new version of CableReady available!
|
63
|
+
Current: #{CableReady::VERSION} Latest: #{latest_version}
|
64
|
+
|
65
|
+
If you upgrade, it is very important that you update BOTH Gemfile and package.json
|
66
|
+
Then, run `bundle install && yarn install` to update to #{latest_version}.
|
67
|
+
|
68
|
+
WARN
|
69
|
+
exit if CableReady.config.on_new_version_available == :exit
|
70
|
+
end
|
71
|
+
rescue
|
72
|
+
puts "👉 CableReady #{CableReady::VERSION} update check skipped: connection timeout"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def package_version_mismatch?
|
79
|
+
npm_version != gem_version
|
80
|
+
end
|
81
|
+
|
82
|
+
def using_preview_release?
|
83
|
+
preview = CableReady::VERSION.match?(LATEST_VERSION_FORMAT) == false
|
84
|
+
puts "👉 CableReady #{CableReady::VERSION} update check skipped: pre-release build" if preview
|
85
|
+
preview
|
86
|
+
end
|
87
|
+
|
88
|
+
def gem_version
|
89
|
+
@_gem_version ||= CableReady::VERSION.gsub(".pre", "-pre")
|
90
|
+
end
|
91
|
+
|
92
|
+
def npm_version
|
93
|
+
@_npm_version ||= find_npm_version
|
94
|
+
end
|
95
|
+
|
96
|
+
def find_npm_version
|
97
|
+
if (match = search_file(package_json_path, regex: /version/))
|
98
|
+
match[JSON_VERSION_FORMAT, 1]
|
99
|
+
elsif (match = search_file(yarn_lock_path, regex: /^cable_ready/))
|
100
|
+
match[NODE_VERSION_FORMAT, 1]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def search_file(path, regex:)
|
105
|
+
return if File.exist?(path) == false
|
106
|
+
File.foreach(path).grep(regex).first
|
107
|
+
end
|
108
|
+
|
109
|
+
def package_json_path
|
110
|
+
Rails.root.join("node_modules", "cable_ready", "package.json")
|
111
|
+
end
|
112
|
+
|
113
|
+
def yarn_lock_path
|
114
|
+
Rails.root.join("yarn.lock")
|
115
|
+
end
|
116
|
+
|
117
|
+
def initializer_missing?
|
118
|
+
File.exist?(Rails.root.join("config", "initializers", "cable_ready.rb")) == false
|
119
|
+
end
|
120
|
+
|
121
|
+
def warn_and_exit(text)
|
122
|
+
puts
|
123
|
+
puts "Heads up! 🔥"
|
124
|
+
puts
|
125
|
+
puts text
|
126
|
+
puts
|
127
|
+
if CableReady.config.on_failed_sanity_checks == :exit
|
128
|
+
puts <<~INFO
|
129
|
+
To ignore any warnings and start the application anyway, you can set the SKIP_SANITY_CHECK environment variable:
|
130
|
+
|
131
|
+
SKIP_SANITY_CHECK=true rails
|
132
|
+
|
133
|
+
To do this permanently, add the following directive to the CableReady initializer:
|
134
|
+
|
135
|
+
CableReady.configure do |config|
|
136
|
+
config.on_failed_sanity_checks = :warn
|
137
|
+
end
|
138
|
+
|
139
|
+
INFO
|
140
|
+
if initializer_missing?
|
141
|
+
puts <<~INFO
|
142
|
+
You can create a CableReady initializer with the command:
|
143
|
+
|
144
|
+
bundle exec rails generate cable_ready:initializer
|
145
|
+
|
146
|
+
INFO
|
147
|
+
end
|
148
|
+
exit false if Rails.env.test? == false
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|