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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -376
  3. data/Gemfile +4 -1
  4. data/Gemfile.lock +146 -144
  5. data/README.md +54 -20
  6. data/Rakefile +8 -8
  7. data/app/assets/javascripts/cable_ready.js +1269 -0
  8. data/app/assets/javascripts/cable_ready.umd.js +1190 -0
  9. data/app/channels/cable_ready/stream.rb +14 -0
  10. data/app/helpers/cable_ready/view_helper.rb +58 -0
  11. data/app/jobs/cable_ready/broadcast_job.rb +15 -0
  12. data/app/models/concerns/cable_ready/updatable/collection_updatable_callbacks.rb +21 -0
  13. data/app/models/concerns/cable_ready/updatable/collections_registry.rb +59 -0
  14. data/app/models/concerns/cable_ready/updatable/memory_cache_debounce_adapter.rb +24 -0
  15. data/app/models/concerns/cable_ready/updatable/model_updatable_callbacks.rb +33 -0
  16. data/app/models/concerns/cable_ready/updatable.rb +211 -0
  17. data/app/models/concerns/extend_has_many.rb +15 -0
  18. data/bin/standardize +1 -1
  19. data/cable_ready.gemspec +20 -6
  20. data/lib/cable_ready/broadcaster.rb +4 -3
  21. data/lib/cable_ready/cable_car.rb +19 -0
  22. data/lib/cable_ready/channel.rb +29 -31
  23. data/lib/cable_ready/channels.rb +4 -5
  24. data/lib/cable_ready/compoundable.rb +11 -0
  25. data/lib/cable_ready/config.rb +28 -1
  26. data/lib/cable_ready/engine.rb +59 -0
  27. data/lib/cable_ready/identifiable.rb +48 -0
  28. data/lib/cable_ready/importmap.rb +4 -0
  29. data/lib/cable_ready/installer.rb +224 -0
  30. data/lib/cable_ready/operation_builder.rb +80 -0
  31. data/lib/cable_ready/sanity_checker.rb +63 -0
  32. data/lib/cable_ready/stream_identifier.rb +13 -0
  33. data/lib/cable_ready/version.rb +1 -1
  34. data/lib/cable_ready.rb +23 -10
  35. data/lib/cable_ready_helper.rb +13 -0
  36. data/lib/generators/cable_ready/channel_generator.rb +110 -0
  37. data/lib/generators/cable_ready/templates/app/javascript/channels/consumer.js.tt +6 -0
  38. data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.esbuild.tt +4 -0
  39. data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.importmap.tt +2 -0
  40. data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.shakapacker.tt +5 -0
  41. data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.vite.tt +1 -0
  42. data/lib/generators/cable_ready/templates/app/javascript/channels/index.js.webpacker.tt +5 -0
  43. data/lib/generators/cable_ready/templates/app/javascript/config/cable_ready.js.tt +4 -0
  44. data/lib/generators/cable_ready/templates/app/javascript/config/index.js.tt +1 -0
  45. data/lib/generators/cable_ready/templates/app/javascript/config/mrujs.js.tt +9 -0
  46. data/lib/generators/cable_ready/templates/app/javascript/controllers/%file_name%_controller.js.tt +38 -0
  47. data/lib/generators/cable_ready/templates/app/javascript/controllers/application.js.tt +11 -0
  48. data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.esbuild.tt +7 -0
  49. data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.importmap.tt +5 -0
  50. data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.shakapacker.tt +5 -0
  51. data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.vite.tt +5 -0
  52. data/lib/generators/cable_ready/templates/app/javascript/controllers/index.js.webpacker.tt +5 -0
  53. data/lib/generators/cable_ready/templates/config/initializers/cable_ready.rb +27 -0
  54. data/lib/generators/cable_ready/templates/esbuild.config.mjs.tt +94 -0
  55. data/lib/install/action_cable.rb +144 -0
  56. data/lib/install/broadcaster.rb +109 -0
  57. data/lib/install/bundle.rb +54 -0
  58. data/lib/install/compression.rb +51 -0
  59. data/lib/install/config.rb +39 -0
  60. data/lib/install/development.rb +34 -0
  61. data/lib/install/esbuild.rb +101 -0
  62. data/lib/install/importmap.rb +96 -0
  63. data/lib/install/initializers.rb +15 -0
  64. data/lib/install/mrujs.rb +121 -0
  65. data/lib/install/npm_packages.rb +13 -0
  66. data/lib/install/shakapacker.rb +65 -0
  67. data/lib/install/spring.rb +54 -0
  68. data/lib/install/updatable.rb +34 -0
  69. data/lib/install/vite.rb +66 -0
  70. data/lib/install/webpacker.rb +93 -0
  71. data/lib/install/yarn.rb +56 -0
  72. data/lib/tasks/cable_ready/cable_ready.rake +247 -0
  73. data/package.json +42 -13
  74. data/rollup.config.mjs +57 -0
  75. data/web-test-runner.config.mjs +12 -0
  76. data/yarn.lock +3252 -327
  77. metadata +138 -9
  78. data/tags +0 -62
@@ -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
@@ -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": "4.4.6",
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
- "url": "https://github.com/hopsoft/cable_ready/issues"
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
- "main": "./javascript/cable_ready.js",
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
- "prettier-standard-check": "yarn run prettier-standard --check ./javascript/**/*.js"
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": "^2.6.1"
48
+ "morphdom": "2.6.1"
32
49
  },
33
50
  "devDependencies": {
34
- "prettier-standard": "^16.1.0"
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
+ ]
@@ -0,0 +1,12 @@
1
+ import rollupJson from '@rollup/plugin-json'
2
+ import { fromRollup } from '@web/dev-server-rollup'
3
+
4
+ const json = fromRollup(rollupJson)
5
+
6
+ export default {
7
+ nodeResolve: true,
8
+ mimeTypes: {
9
+ '**/*.json': 'js'
10
+ },
11
+ plugins: [json({})]
12
+ }