cable_ready 4.5.0 → 5.0.0
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 +2 -376
- data/Gemfile +4 -1
- data/Gemfile.lock +146 -144
- data/README.md +54 -20
- data/Rakefile +8 -8
- data/app/assets/javascripts/cable_ready.js +1269 -0
- data/app/assets/javascripts/cable_ready.umd.js +1190 -0
- data/app/channels/cable_ready/stream.rb +14 -0
- data/app/helpers/cable_ready/view_helper.rb +58 -0
- data/app/jobs/cable_ready/broadcast_job.rb +15 -0
- data/app/models/concerns/cable_ready/updatable/collection_updatable_callbacks.rb +21 -0
- data/app/models/concerns/cable_ready/updatable/collections_registry.rb +59 -0
- data/app/models/concerns/cable_ready/updatable/memory_cache_debounce_adapter.rb +24 -0
- data/app/models/concerns/cable_ready/updatable/model_updatable_callbacks.rb +33 -0
- data/app/models/concerns/cable_ready/updatable.rb +211 -0
- data/app/models/concerns/extend_has_many.rb +15 -0
- data/bin/standardize +1 -1
- data/cable_ready.gemspec +20 -6
- data/lib/cable_ready/broadcaster.rb +4 -3
- data/lib/cable_ready/cable_car.rb +19 -0
- data/lib/cable_ready/channel.rb +29 -31
- data/lib/cable_ready/channels.rb +4 -5
- data/lib/cable_ready/compoundable.rb +11 -0
- data/lib/cable_ready/config.rb +28 -1
- data/lib/cable_ready/engine.rb +59 -0
- data/lib/cable_ready/identifiable.rb +48 -0
- data/lib/cable_ready/importmap.rb +4 -0
- data/lib/cable_ready/installer.rb +224 -0
- data/lib/cable_ready/operation_builder.rb +80 -0
- data/lib/cable_ready/sanity_checker.rb +63 -0
- data/lib/cable_ready/stream_identifier.rb +13 -0
- data/lib/cable_ready/version.rb +1 -1
- data/lib/cable_ready.rb +23 -10
- data/lib/cable_ready_helper.rb +13 -0
- data/lib/generators/cable_ready/channel_generator.rb +110 -0
- data/lib/generators/cable_ready/templates/app/javascript/channels/consumer.js.tt +6 -0
- data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.esbuild.tt +4 -0
- data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.importmap.tt +2 -0
- data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.shakapacker.tt +5 -0
- data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.vite.tt +1 -0
- data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.webpacker.tt +5 -0
- data/lib/generators/cable_ready/templates/app/javascript/config/cable_ready.js.tt +4 -0
- data/lib/generators/cable_ready/templates/app/javascript/config/index.js.tt +1 -0
- data/lib/generators/cable_ready/templates/app/javascript/config/mrujs.js.tt +9 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/%file_name%_controller.js.tt +38 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/application.js.tt +11 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.esbuild.tt +7 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.importmap.tt +5 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.shakapacker.tt +5 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.vite.tt +5 -0
- data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.webpacker.tt +5 -0
- data/lib/generators/cable_ready/templates/config/initializers/cable_ready.rb +27 -0
- data/lib/generators/cable_ready/templates/esbuild.config.mjs.tt +94 -0
- data/lib/install/action_cable.rb +144 -0
- data/lib/install/broadcaster.rb +109 -0
- data/lib/install/bundle.rb +54 -0
- data/lib/install/compression.rb +51 -0
- data/lib/install/config.rb +39 -0
- data/lib/install/development.rb +34 -0
- data/lib/install/esbuild.rb +101 -0
- data/lib/install/importmap.rb +96 -0
- data/lib/install/initializers.rb +15 -0
- data/lib/install/mrujs.rb +121 -0
- data/lib/install/npm_packages.rb +13 -0
- data/lib/install/shakapacker.rb +65 -0
- data/lib/install/spring.rb +54 -0
- data/lib/install/updatable.rb +34 -0
- data/lib/install/vite.rb +66 -0
- data/lib/install/webpacker.rb +93 -0
- data/lib/install/yarn.rb +56 -0
- data/lib/tasks/cable_ready/cable_ready.rake +247 -0
- data/package.json +42 -13
- data/rollup.config.mjs +57 -0
- data/web-test-runner.config.mjs +12 -0
- data/yarn.lock +3252 -327
- metadata +138 -9
- data/tags +0 -62
data/lib/install/vite.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cable_ready/installer"
|
|
4
|
+
|
|
5
|
+
return if pack_path_missing?
|
|
6
|
+
|
|
7
|
+
# verify that all critical dependencies are up to date; if not, queue for later
|
|
8
|
+
lines = package_json.readlines
|
|
9
|
+
if !lines.index { |line| line =~ /^\s*["']@hotwired\/stimulus["']:/ }
|
|
10
|
+
add_package "@hotwired/stimulus@^3.2"
|
|
11
|
+
else
|
|
12
|
+
say "⏩ @hotwired/stimulus npm package is already present. Skipping."
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
if !lines.index { |line| line =~ /^\s*["']stimulus-vite-helpers["']: ["']\^3["']/ }
|
|
16
|
+
add_package "stimulus-vite-helpers@^3"
|
|
17
|
+
else
|
|
18
|
+
say "⏩ @stimulus-vite-helpers npm package is already present. Skipping."
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
step_path = "/app/javascript/controllers/"
|
|
22
|
+
application_js_src = fetch(step_path, "application.js.tt")
|
|
23
|
+
application_js_path = controllers_path / "application.js"
|
|
24
|
+
index_src = fetch(step_path, "index.js.vite.tt")
|
|
25
|
+
index_path = controllers_path / "index.js"
|
|
26
|
+
|
|
27
|
+
# create entrypoint/controllers, as well as the index, application and application_controller
|
|
28
|
+
empty_directory controllers_path unless controllers_path.exist?
|
|
29
|
+
|
|
30
|
+
copy_file(application_js_src, application_js_path) unless application_js_path.exist?
|
|
31
|
+
copy_file(index_src, index_path) unless index_path.exist?
|
|
32
|
+
|
|
33
|
+
controllers_pattern = /import ['"](\.\.\/)?controllers['"]/
|
|
34
|
+
controllers_commented_pattern = /\s*\/\/\s*#{controllers_pattern}/
|
|
35
|
+
prefix = "..\/" # standard:disable Style/RedundantStringEscape
|
|
36
|
+
|
|
37
|
+
if pack.match?(controllers_pattern)
|
|
38
|
+
if pack.match?(controllers_commented_pattern)
|
|
39
|
+
proceed = if options.key? "uncomment"
|
|
40
|
+
options["uncomment"]
|
|
41
|
+
else
|
|
42
|
+
!no?("✨ Do you want to import your Stimulus controllers in application.js? (Y/n)")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if proceed
|
|
46
|
+
# uncomment_lines only works with Ruby comments 🙄
|
|
47
|
+
lines = pack_path.readlines
|
|
48
|
+
matches = lines.select { |line| line =~ controllers_commented_pattern }
|
|
49
|
+
lines[lines.index(matches.last).to_i] = "import \"#{prefix}controllers\"\n"
|
|
50
|
+
pack_path.write lines.join
|
|
51
|
+
say "✅ Stimulus controllers imported in #{friendly_pack_path}"
|
|
52
|
+
else
|
|
53
|
+
say "🤷 your Stimulus controllers are not being imported in your application.js. We trust that you have a reason for this."
|
|
54
|
+
end
|
|
55
|
+
else
|
|
56
|
+
say "✅ Stimulus controllers imported in #{friendly_pack_path}"
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
lines = pack_path.readlines
|
|
60
|
+
matches = lines.select { |line| line =~ /^import / }
|
|
61
|
+
lines.insert lines.index(matches.last).to_i + 1, "import \"#{prefix}controllers\"\n"
|
|
62
|
+
pack_path.write lines.join
|
|
63
|
+
say "✅ Stimulus controllers imported in #{friendly_pack_path}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
complete_step :vite
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cable_ready/installer"
|
|
4
|
+
|
|
5
|
+
return if pack_path_missing?
|
|
6
|
+
|
|
7
|
+
# verify that all critical dependencies are up to date; if not, queue for later
|
|
8
|
+
lines = package_json.readlines
|
|
9
|
+
if !lines.index { |line| line =~ /^\s*["']webpack["']: ["']\^4.46.0["']/ }
|
|
10
|
+
add_package "webpack@^4.46.0"
|
|
11
|
+
else
|
|
12
|
+
say "⏩ webpack npm package is already present. Skipping."
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
if !lines.index { |line| line =~ /^\s*["']webpack-cli["']: ["']\^3.3.12["']/ }
|
|
16
|
+
add_package "webpack-cli@^3.3.12"
|
|
17
|
+
else
|
|
18
|
+
say "⏩ webpack-cli npm package is already present. Skipping."
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if !lines.index { |line| line =~ /^\s*["']@rails\/webpacker["']: ["']\^5.4.3["']/ }
|
|
22
|
+
add_package "@rails/webpacker@^5.4.3"
|
|
23
|
+
else
|
|
24
|
+
say "⏩ @rails/webpacker npm package is already present. Skipping."
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
if !lines.index { |line| line =~ /^\s*["']@hotwired\/stimulus["']:/ }
|
|
28
|
+
add_package "@hotwired/stimulus@^3.2"
|
|
29
|
+
else
|
|
30
|
+
say "⏩ @hotwired/stimulus npm package is already present. Skipping."
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if !lines.index { |line| line =~ /^\s*["']@hotwired\/stimulus-webpack-helpers["']: ["']\^1.0.1["']/ }
|
|
34
|
+
add_package "@hotwired/stimulus-webpack-helpers@^1.0.1"
|
|
35
|
+
else
|
|
36
|
+
say "⏩ @hotwired/stimulus-webpack-helpers npm package is already present. Skipping."
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if !lines.index { |line| line =~ /^\s*["']webpack-dev-server["']: ["']\^3.11.3["']/ }
|
|
40
|
+
add_dev_package "webpack-dev-server@^3.11.3"
|
|
41
|
+
else
|
|
42
|
+
say "⏩ @webpack-dev-server is already present. Skipping."
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
step_path = "/app/javascript/controllers/"
|
|
46
|
+
application_js_src = fetch(step_path, "application.js.tt")
|
|
47
|
+
application_js_path = controllers_path / "application.js"
|
|
48
|
+
index_src = fetch(step_path, "index.js.webpacker.tt")
|
|
49
|
+
index_path = controllers_path / "index.js"
|
|
50
|
+
|
|
51
|
+
# create entrypoint/controllers, as well as the index, application and application_controller
|
|
52
|
+
empty_directory controllers_path unless controllers_path.exist?
|
|
53
|
+
|
|
54
|
+
# webpacker 5.4 did not colloquially feature a controllers/application.js file
|
|
55
|
+
copy_file(application_js_src, application_js_path) unless application_js_path.exist?
|
|
56
|
+
copy_file(index_src, index_path) unless index_path.exist?
|
|
57
|
+
|
|
58
|
+
controllers_pattern = /import ['"]controllers['"]/
|
|
59
|
+
controllers_commented_pattern = /\s*\/\/\s*#{controllers_pattern}/
|
|
60
|
+
|
|
61
|
+
if pack.match?(controllers_pattern)
|
|
62
|
+
if pack.match?(controllers_commented_pattern)
|
|
63
|
+
proceed = if options.key? "uncomment"
|
|
64
|
+
options["uncomment"]
|
|
65
|
+
else
|
|
66
|
+
!no?("✨ Do you want to import your Stimulus controllers in application.js? (Y/n)")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if proceed
|
|
70
|
+
# uncomment_lines only works with Ruby comments 🙄
|
|
71
|
+
lines = pack_path.readlines
|
|
72
|
+
matches = lines.select { |line| line =~ controllers_commented_pattern }
|
|
73
|
+
lines[lines.index(matches.last).to_i] = "import \"controllers\"\n"
|
|
74
|
+
pack_path.write lines.join
|
|
75
|
+
say "✅ Stimulus controllers imported in #{friendly_pack_path}"
|
|
76
|
+
else
|
|
77
|
+
say "🤷 your Stimulus controllers are not being imported in your application.js. We trust that you have a reason for this."
|
|
78
|
+
end
|
|
79
|
+
else
|
|
80
|
+
say "✅ Stimulus controllers imported in #{friendly_pack_path}"
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
lines = pack_path.readlines
|
|
84
|
+
matches = lines.select { |line| line =~ /^import / }
|
|
85
|
+
lines.insert lines.index(matches.last).to_i + 1, "import \"controllers\"\n"
|
|
86
|
+
pack_path.write lines.join
|
|
87
|
+
say "✅ Stimulus controllers imported in #{friendly_pack_path}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# ensure webpacker is installed in the Gemfile
|
|
91
|
+
add_gem "webpacker@5.4.3"
|
|
92
|
+
|
|
93
|
+
complete_step :webpacker
|
data/lib/install/yarn.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cable_ready/installer"
|
|
4
|
+
|
|
5
|
+
if !package_json.exist?
|
|
6
|
+
say "⏩ No package.json file found. Skipping."
|
|
7
|
+
|
|
8
|
+
return
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# run yarn install only when packages are waiting to be added or removed
|
|
12
|
+
add = package_list.exist? ? package_list.readlines.map(&:chomp) : []
|
|
13
|
+
dev = dev_package_list.exist? ? dev_package_list.readlines.map(&:chomp) : []
|
|
14
|
+
drop = drop_package_list.exist? ? drop_package_list.readlines.map(&:chomp) : []
|
|
15
|
+
|
|
16
|
+
json = JSON.parse(package_json.read)
|
|
17
|
+
|
|
18
|
+
if add.present? || dev.present? || drop.present?
|
|
19
|
+
|
|
20
|
+
add.each do |package|
|
|
21
|
+
matches = package.match(/(.+)@(.+)/)
|
|
22
|
+
name, version = matches[1], matches[2]
|
|
23
|
+
json["dependencies"] = {} unless json["dependencies"]
|
|
24
|
+
json["dependencies"][name] = version
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
dev.each do |package|
|
|
28
|
+
matches = package.match(/(.+)@(.+)/)
|
|
29
|
+
name, version = matches[1], matches[2]
|
|
30
|
+
json["devDependencies"] = {} unless json["devDependencies"]
|
|
31
|
+
json["devDependencies"][name] = version
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
drop.each do |package|
|
|
35
|
+
json["dependencies"].delete(package)
|
|
36
|
+
json["devDependencies"].delete(package)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
package_json.write JSON.pretty_generate(json)
|
|
40
|
+
|
|
41
|
+
system "yarn install --silent"
|
|
42
|
+
else
|
|
43
|
+
say "⏩ No yarn depdencies to add or remove. Skipping."
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if bundler == "esbuild" && json["scripts"]["build"] != "node esbuild.config.mjs"
|
|
48
|
+
json["scripts"]["build:default"] = json["scripts"]["build"]
|
|
49
|
+
json["scripts"]["build"] = "node esbuild.config.mjs"
|
|
50
|
+
package_json.write JSON.pretty_generate(json)
|
|
51
|
+
say "✅ Your build script has been updated to use esbuild.config.mjs"
|
|
52
|
+
else
|
|
53
|
+
say "⏩ Your build script is already setup. Skipping."
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
complete_step :yarn
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
CR_STEPS = {
|
|
4
|
+
"action_cable" => "Action Cable",
|
|
5
|
+
"webpacker" => "Install CableReady using Webpacker",
|
|
6
|
+
"shakapacker" => "Install CableReady using Shakapacker",
|
|
7
|
+
"npm_packages" => "Install CableReady npm package",
|
|
8
|
+
"importmap" => "Install CableReady using importmaps",
|
|
9
|
+
"esbuild" => "Install CableReady using esbuild",
|
|
10
|
+
"config" => "Client initialization",
|
|
11
|
+
"initializers" => "Generate and configure initializer",
|
|
12
|
+
"development" => "development environment configuration",
|
|
13
|
+
"spring" => "Disable spring gem. Spring has been removed from Rails 7",
|
|
14
|
+
"mrujs" => "Swap out Rails UJS for mrujs",
|
|
15
|
+
"broadcaster" => "Make CableReady::Broadcaster available to channels, controllers, jobs and models",
|
|
16
|
+
"updatable" => "Include CableReady::Updatable in Active Record model classes",
|
|
17
|
+
"vite" => "Install CableReady using Vite",
|
|
18
|
+
"compression" => "Compress WebSocket traffic with gzip"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
CR_BUNDLERS = {
|
|
22
|
+
"webpacker" => ["npm_packages", "webpacker", "config", "action_cable", "development", "initializers", "broadcaster", "updatable", "spring", "yarn", "bundle"],
|
|
23
|
+
"esbuild" => ["npm_packages", "esbuild", "config", "action_cable", "development", "initializers", "broadcaster", "updatable", "spring", "yarn", "bundle"],
|
|
24
|
+
"vite" => ["npm_packages", "vite", "config", "action_cable", "development", "initializers", "broadcaster", "updatable", "spring", "yarn", "bundle"],
|
|
25
|
+
"shakapacker" => ["npm_packages", "shakapacker", "config", "action_cable", "development", "initializers", "broadcaster", "updatable", "spring", "yarn", "bundle"],
|
|
26
|
+
"importmap" => ["config", "action_cable", "importmap", "development", "initializers", "broadcaster", "updatable", "spring", "bundle"]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def run_install_template(template, force: false, trace: false)
|
|
30
|
+
puts "--- [#{template}] ----"
|
|
31
|
+
|
|
32
|
+
if Rails.root.join("tmp/cable_ready_installer/halt").exist?
|
|
33
|
+
FileUtils.rm(Rails.root.join("tmp/cable_ready_installer/halt"))
|
|
34
|
+
puts "CableReady installation halted. Please fix the issues above and try again."
|
|
35
|
+
exit
|
|
36
|
+
end
|
|
37
|
+
if Rails.root.join("tmp/cable_ready_installer/#{template}").exist? && !force
|
|
38
|
+
puts "👍 Step #{template} already completed. Skipping."
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../../install/#{template}.rb", __dir__)} SKIP_SANITY_CHECK=true #{"--trace" if trace}"
|
|
43
|
+
|
|
44
|
+
puts
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
namespace :cable_ready do
|
|
48
|
+
desc "✨ Install CableReady ✨"
|
|
49
|
+
task :install do
|
|
50
|
+
FileUtils.mkdir_p(Rails.root.join("tmp/cable_ready_installer/templates"))
|
|
51
|
+
FileUtils.mkdir_p(Rails.root.join("tmp/cable_ready_installer/working"))
|
|
52
|
+
install_complete = Rails.root.join("tmp/cable_ready_installer/complete")
|
|
53
|
+
|
|
54
|
+
bundler = nil
|
|
55
|
+
options = {}
|
|
56
|
+
|
|
57
|
+
ARGV.each do |arg|
|
|
58
|
+
# make sure we have a valid build tool specified, or proceed to automatic detection
|
|
59
|
+
if ["webpacker", "esbuild", "vite", "shakapacker", "importmap"].include?(arg)
|
|
60
|
+
bundler = arg
|
|
61
|
+
else
|
|
62
|
+
kv = arg.split("=")
|
|
63
|
+
if kv.length == 2
|
|
64
|
+
kv[1] = if kv[1] == "true"
|
|
65
|
+
true
|
|
66
|
+
else
|
|
67
|
+
(kv[1] == "false") ? false : kv[1]
|
|
68
|
+
end
|
|
69
|
+
options[kv[0]] = kv[1]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
options_path = Rails.root.join("tmp/cable_ready_installer/options")
|
|
75
|
+
options_path.write(options.to_yaml)
|
|
76
|
+
|
|
77
|
+
if defined?(StimulusReflex)
|
|
78
|
+
puts "✨ \e[38;5;220mStimulusReflex\e[0m is present in this project ✨"
|
|
79
|
+
puts
|
|
80
|
+
puts "CableReady will be installed with StimulusReflex. Just run: \e[38;5;231mrails stimulus_reflex:install\e[0m"
|
|
81
|
+
puts
|
|
82
|
+
puts "Get help on Discord: \e[4;97mhttps://discord.gg/stimulus-reflex\e[0m. \e[38;5;196mWe are here for you.\e[0m 💙"
|
|
83
|
+
puts
|
|
84
|
+
exit
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if install_complete.exist?
|
|
88
|
+
puts "✨ \e[38;5;220mCableReady\e[0m is already installed ✨"
|
|
89
|
+
puts
|
|
90
|
+
puts "To restart the installation process, run: \e[38;5;231mrails cable_ready:install:restart\e[0m"
|
|
91
|
+
puts
|
|
92
|
+
puts "To get started, check out \e[4;97mhttps://cableready.stimulusreflex.com/guide/cableready-101\e[0m"
|
|
93
|
+
puts "or get help on Discord: \e[4;97mhttps://discord.gg/stimulus-reflex\e[0m. \e[38;5;196mWe are here for you.\e[0m 💙"
|
|
94
|
+
puts
|
|
95
|
+
exit
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# if there is an installation in progress, continue where we left off
|
|
99
|
+
cached_entrypoint = Rails.root.join("tmp/cable_ready_installer/entrypoint")
|
|
100
|
+
|
|
101
|
+
if cached_entrypoint.exist?
|
|
102
|
+
entrypoint = File.read(cached_entrypoint)
|
|
103
|
+
puts "✨ Resuming \e[38;5;220mCableReady\e[0m installation ✨"
|
|
104
|
+
puts
|
|
105
|
+
puts "If you have any setup issues, please consult \e[4;97mhttps://cableready.stimulusreflex.com/hello-world/setup\e[0m"
|
|
106
|
+
puts "or get help on Discord: \e[4;97mhttps://discord.gg/stimulus-reflex\e[0m. \e[38;5;196mWe are here for you.\e[0m 💙"
|
|
107
|
+
puts
|
|
108
|
+
puts "Resuming installation into \e[1m#{entrypoint}\e[22m"
|
|
109
|
+
puts "Run \e[1;94mrails cable_ready:install:restart\e[0m to restart the installation process"
|
|
110
|
+
puts
|
|
111
|
+
else
|
|
112
|
+
puts "✨ Installing \e[38;5;220mCableReady\e[0m ✨"
|
|
113
|
+
puts
|
|
114
|
+
puts "If you have any setup issues, please consult \e[4;97mhttps://cableready.stimulusreflex.com/hello-world/setup\e[0m"
|
|
115
|
+
puts "or get help on Discord: \e[4;97mhttps://discord.gg/stimulus-reflex\e[0m. \e[38;5;196mWe are here for you.\e[0m 💙"
|
|
116
|
+
if Rails.root.join(".git").exist?
|
|
117
|
+
puts
|
|
118
|
+
puts "We recommend running \e[1;94mgit commit\e[0m before proceeding. A diff will be generated at the end."
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if options.key? "entrypoint"
|
|
122
|
+
entrypoint = options["entrypoint"]
|
|
123
|
+
else
|
|
124
|
+
entrypoint = [
|
|
125
|
+
"app/javascript",
|
|
126
|
+
"app/frontend"
|
|
127
|
+
].find { |path| File.exist?(Rails.root.join(path)) } || "app/javascript"
|
|
128
|
+
|
|
129
|
+
puts
|
|
130
|
+
puts "Where do JavaScript files live in your app? Our best guess is: \e[1m#{entrypoint}\e[22m 🤔"
|
|
131
|
+
puts "Press enter to accept this, or type a different path."
|
|
132
|
+
print "> "
|
|
133
|
+
input = $stdin.gets.chomp
|
|
134
|
+
entrypoint = input unless input.blank?
|
|
135
|
+
end
|
|
136
|
+
File.write(cached_entrypoint, entrypoint)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# verify their bundler before starting, unless they explicitly specified on CLI
|
|
140
|
+
if !bundler
|
|
141
|
+
# auto-detect build tool based on existing packages and configuration
|
|
142
|
+
if Rails.root.join("config/importmap.rb").exist?
|
|
143
|
+
bundler = "importmap"
|
|
144
|
+
elsif Rails.root.join("package.json").exist?
|
|
145
|
+
package_json = File.read(Rails.root.join("package.json"))
|
|
146
|
+
bundler = "webpacker" if package_json.include?('"@rails/webpacker":')
|
|
147
|
+
bundler = "esbuild" if package_json.include?('"esbuild":')
|
|
148
|
+
bundler = "vite" if package_json.include?('"vite":')
|
|
149
|
+
bundler = "shakapacker" if package_json.include?('"shakapacker":')
|
|
150
|
+
if !bundler
|
|
151
|
+
puts "❌ You must be using a node-based bundler such as esbuild, webpacker, vite or shakapacker (package.json) or importmap (config/importmap.rb) to use CableReady."
|
|
152
|
+
exit
|
|
153
|
+
end
|
|
154
|
+
else
|
|
155
|
+
puts "❌ You must be using a node-based bundler such as esbuild, webpacker, vite or shakapacker (package.json) or importmap (config/importmap.rb) to use CableReady."
|
|
156
|
+
exit
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
puts
|
|
160
|
+
puts "It looks like you're using \e[1m#{bundler}\e[22m as your bundler. Is that correct? (Y/n)"
|
|
161
|
+
print "> "
|
|
162
|
+
input = $stdin.gets.chomp
|
|
163
|
+
if input.downcase == "n"
|
|
164
|
+
puts
|
|
165
|
+
puts "CableReady installation supports: esbuild, webpacker, vite, shakapacker and importmap."
|
|
166
|
+
puts "Please run \e[1;94mrails cable_ready:install [bundler]\e[0m to install CableReady."
|
|
167
|
+
exit
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
File.write("tmp/cable_ready_installer/bundler", bundler)
|
|
172
|
+
FileUtils.touch("tmp/cable_ready_installer/backups")
|
|
173
|
+
File.write("tmp/cable_ready_installer/template_src", File.expand_path("../../generators/cable_ready/templates/", __dir__))
|
|
174
|
+
|
|
175
|
+
# do the things
|
|
176
|
+
CR_BUNDLERS[bundler].each do |template|
|
|
177
|
+
run_install_template(template, trace: !!options["trace"])
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
puts
|
|
181
|
+
puts "🎉 \e[1;92mCableReady has been successfully installed!\e[22m 🎉"
|
|
182
|
+
puts
|
|
183
|
+
puts "👉 \e[4;97mhttps://cableready.stimulusreflex.com/guide/cableready-101\e[0m"
|
|
184
|
+
puts
|
|
185
|
+
puts "Join over 2000 CableReady developers on Discord: \e[4;97mhttps://discord.gg/stimulus-reflex\e[0m"
|
|
186
|
+
puts
|
|
187
|
+
|
|
188
|
+
backups = File.readlines("tmp/cable_ready_installer/backups").map(&:chomp)
|
|
189
|
+
|
|
190
|
+
if backups.any?
|
|
191
|
+
puts "🙆 The following files were modified during installation:"
|
|
192
|
+
puts
|
|
193
|
+
backups.each { |backup| puts " #{backup}" }
|
|
194
|
+
puts
|
|
195
|
+
puts "Each of these files has been backed up with a .bak extension. Please review the changes carefully."
|
|
196
|
+
puts "If you're happy with the changes, you can delete the .bak files."
|
|
197
|
+
puts
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
if Rails.root.join(".git").exist?
|
|
201
|
+
system "git diff > tmp/cable_ready_installer.diff"
|
|
202
|
+
puts "🏮 A diff of all changes has been saved to \e[1mtmp/cable_ready_installer.diff\e[22m"
|
|
203
|
+
puts
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
FileUtils.touch(install_complete)
|
|
207
|
+
`pkill -f spring` if Rails.root.join("tmp/cable_ready_installer/kill_spring").exist?
|
|
208
|
+
exit
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
namespace :install do
|
|
212
|
+
desc "Restart CableReady installation"
|
|
213
|
+
task :restart do
|
|
214
|
+
FileUtils.rm_rf Rails.root.join("tmp/cable_ready_installer")
|
|
215
|
+
system "rails cable_ready:install #{ARGV.join(" ")}"
|
|
216
|
+
exit
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
desc <<~DESC
|
|
220
|
+
Run specific CableReady install steps
|
|
221
|
+
|
|
222
|
+
#{CR_STEPS.sort.map { |step, description| "#{step.ljust(20)} #{description}" }.join("\n")}
|
|
223
|
+
DESC
|
|
224
|
+
|
|
225
|
+
task :step do
|
|
226
|
+
def warning(step = nil)
|
|
227
|
+
return if step.to_s.include?("=")
|
|
228
|
+
if step
|
|
229
|
+
puts "⚠️ #{step} is not a valid step. Valid steps are: #{CR_STEPS.keys.join(", ")}"
|
|
230
|
+
else
|
|
231
|
+
puts "❌ You must specify a step to re-run. Valid steps are: #{CR_STEPS.keys.join(", ")}"
|
|
232
|
+
puts "Example: \e[1;94mrails cable_ready:install:step initializers\e[0m"
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
warning if ARGV.empty?
|
|
237
|
+
|
|
238
|
+
ARGV.each do |step|
|
|
239
|
+
CR_STEPS.include?(step) ? run_install_template(step, force: true) : warning(step)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
run_install_template(:bundle, force: true)
|
|
243
|
+
run_install_template(:yarn, force: true)
|
|
244
|
+
exit
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cable_ready",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "CableReady helps you create great real-time user experiences by making it simple to trigger client-side DOM changes from server-side Ruby.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ruby",
|
|
@@ -13,24 +13,53 @@
|
|
|
13
13
|
"client-side",
|
|
14
14
|
"dom"
|
|
15
15
|
],
|
|
16
|
-
"homepage": "https://cableready.stimulusreflex.com
|
|
17
|
-
"bugs":
|
|
18
|
-
|
|
19
|
-
},
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "git+https://github.com:hopsoft/cable_ready.git"
|
|
23
|
-
},
|
|
16
|
+
"homepage": "https://cableready.stimulusreflex.com",
|
|
17
|
+
"bugs": "https://github.com/stimulusreflex/cable_ready/issues",
|
|
18
|
+
"repository": "https://github.com/stimulusreflex/cable_ready",
|
|
24
19
|
"license": "MIT",
|
|
25
20
|
"author": "Nathan Hopkins <natehop@gmail.com>",
|
|
26
|
-
"
|
|
21
|
+
"contributors": [
|
|
22
|
+
"Andrew Mason <andrewmcodes@protonmail.com>",
|
|
23
|
+
"Julian Rubisch <julian@julianrubisch.at>",
|
|
24
|
+
"Marco Roth <marco.roth@intergga.ch>",
|
|
25
|
+
"Nathan Hopkins <natehop@gmail.com>"
|
|
26
|
+
],
|
|
27
|
+
"main": "./dist/cable_ready.js",
|
|
28
|
+
"module": "./dist/cable_ready.js",
|
|
29
|
+
"browser": "./dist/cable_ready.js",
|
|
30
|
+
"import": "./dist/cable_ready.js",
|
|
31
|
+
"unpkg": "./dist/cable_ready.umd.js",
|
|
32
|
+
"umd": "./dist/cable_ready.umd.js",
|
|
33
|
+
"files": [
|
|
34
|
+
"dist/*",
|
|
35
|
+
"javascript/*"
|
|
36
|
+
],
|
|
27
37
|
"scripts": {
|
|
28
|
-
"
|
|
38
|
+
"lint": "yarn run format --check",
|
|
39
|
+
"format": "yarn run prettier-standard ./javascript/**/*.js rollup.config.mjs",
|
|
40
|
+
"build": "yarn rollup -c",
|
|
41
|
+
"watch": "yarn rollup -wc",
|
|
42
|
+
"test": "web-test-runner javascript/test/**/*.test.js",
|
|
43
|
+
"docs:dev": "vitepress dev docs",
|
|
44
|
+
"docs:build": "vitepress build docs && cp ./docs/_redirects ./docs/.vitepress/dist",
|
|
45
|
+
"docs:preview": "vitepress preview docs"
|
|
29
46
|
},
|
|
30
47
|
"dependencies": {
|
|
31
|
-
"morphdom": "
|
|
48
|
+
"morphdom": "2.6.1"
|
|
32
49
|
},
|
|
33
50
|
"devDependencies": {
|
|
34
|
-
"
|
|
51
|
+
"@open-wc/testing": "^3.1.7",
|
|
52
|
+
"@rollup/plugin-json": "^6.0.0",
|
|
53
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
54
|
+
"@rollup/plugin-terser": "^0.4.0",
|
|
55
|
+
"@web/dev-server-esbuild": "^0.3.3",
|
|
56
|
+
"@web/dev-server-rollup": "^0.3.21",
|
|
57
|
+
"@web/test-runner": "^0.15.1",
|
|
58
|
+
"prettier-standard": "^16.4.1",
|
|
59
|
+
"rollup": "^3.19.1",
|
|
60
|
+
"sinon": "^15.0.2",
|
|
61
|
+
"vite": "^4.1.4",
|
|
62
|
+
"vitepress": "^1.0.0-alpha.56",
|
|
63
|
+
"vitepress-plugin-search": "^1.0.4-alpha.19"
|
|
35
64
|
}
|
|
36
65
|
}
|
data/rollup.config.mjs
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import resolve from '@rollup/plugin-node-resolve'
|
|
2
|
+
import json from '@rollup/plugin-json'
|
|
3
|
+
import terser from '@rollup/plugin-terser'
|
|
4
|
+
|
|
5
|
+
const pretty = () => {
|
|
6
|
+
return terser({
|
|
7
|
+
mangle: false,
|
|
8
|
+
compress: false,
|
|
9
|
+
format: {
|
|
10
|
+
comments: 'all',
|
|
11
|
+
beautify: true,
|
|
12
|
+
indent_level: 2
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const esConfig = {
|
|
18
|
+
format: 'es',
|
|
19
|
+
inlineDynamicImports: true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const umdConfig = {
|
|
23
|
+
name: 'CableReady',
|
|
24
|
+
format: 'umd',
|
|
25
|
+
exports: 'named',
|
|
26
|
+
globals: { morphdom: 'morphdom' }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const baseName = 'cable_ready'
|
|
30
|
+
const distFolders = ['dist', 'app/assets/javascripts']
|
|
31
|
+
|
|
32
|
+
const output = distFolders
|
|
33
|
+
.map(distFolder => [
|
|
34
|
+
{
|
|
35
|
+
...esConfig,
|
|
36
|
+
file: `${distFolder}/${baseName}.js`,
|
|
37
|
+
plugins: [pretty()]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
...umdConfig,
|
|
41
|
+
file: `${distFolder}/${baseName}.umd.js`,
|
|
42
|
+
plugins: [pretty()]
|
|
43
|
+
}
|
|
44
|
+
])
|
|
45
|
+
.flat()
|
|
46
|
+
|
|
47
|
+
export default [
|
|
48
|
+
{
|
|
49
|
+
external: ['morphdom'],
|
|
50
|
+
input: 'javascript/index.js',
|
|
51
|
+
output,
|
|
52
|
+
plugins: [resolve(), json()],
|
|
53
|
+
watch: {
|
|
54
|
+
include: 'javascript/**'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
]
|