cable_ready 5.0.0.pre8 → 5.0.0.pre10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -542
  3. data/Gemfile +4 -1
  4. data/Gemfile.lock +125 -168
  5. data/IMPLEMENTATION.md +93 -0
  6. data/README.md +36 -10
  7. data/Rakefile +0 -8
  8. data/app/assets/javascripts/cable_ready.js +1265 -0
  9. data/app/assets/javascripts/cable_ready.min.js +2 -0
  10. data/app/assets/javascripts/cable_ready.min.js.map +1 -0
  11. data/app/assets/javascripts/cable_ready.umd.js +1186 -0
  12. data/app/assets/javascripts/cable_ready.umd.min.js +2 -0
  13. data/app/assets/javascripts/cable_ready.umd.min.js.map +1 -0
  14. data/app/channels/cable_ready/stream.rb +7 -5
  15. data/app/helpers/cable_ready/view_helper.rb +58 -0
  16. data/app/jobs/cable_ready_broadcast_job.rb +9 -8
  17. data/app/models/concerns/cable_ready/updatable/collection_updatable_callbacks.rb +2 -0
  18. data/app/models/concerns/cable_ready/updatable/collections_registry.rb +2 -0
  19. data/app/models/concerns/cable_ready/updatable/model_updatable_callbacks.rb +6 -3
  20. data/app/models/concerns/cable_ready/updatable.rb +110 -17
  21. data/app/models/concerns/extend_has_many.rb +2 -0
  22. data/cable_ready.gemspec +40 -0
  23. data/lib/cable_ready/broadcaster.rb +2 -0
  24. data/lib/cable_ready/cable_car.rb +2 -0
  25. data/lib/cable_ready/channel.rb +12 -4
  26. data/lib/cable_ready/channels.rb +3 -1
  27. data/lib/cable_ready/config.rb +16 -2
  28. data/lib/cable_ready/engine.rb +50 -0
  29. data/lib/cable_ready/identifiable.rb +23 -5
  30. data/lib/cable_ready/importmap.rb +4 -0
  31. data/lib/cable_ready/installer.rb +224 -0
  32. data/lib/cable_ready/operation_builder.rb +1 -1
  33. data/lib/cable_ready/sanity_checker.rb +1 -31
  34. data/lib/cable_ready/version.rb +1 -1
  35. data/lib/cable_ready.rb +4 -26
  36. data/lib/cable_ready_helper.rb +13 -0
  37. data/lib/generators/cable_ready/channel_generator.rb +51 -12
  38. data/lib/generators/cable_ready/templates/config/initializers/cable_ready.rb +10 -6
  39. data/lib/install/action_cable.rb +144 -0
  40. data/lib/install/broadcaster.rb +109 -0
  41. data/lib/install/bundle.rb +54 -0
  42. data/lib/install/compression.rb +51 -0
  43. data/lib/install/config.rb +39 -0
  44. data/lib/install/development.rb +34 -0
  45. data/lib/install/esbuild.rb +101 -0
  46. data/lib/install/importmap.rb +96 -0
  47. data/lib/install/initializers.rb +15 -0
  48. data/lib/install/mrujs.rb +121 -0
  49. data/lib/install/npm_packages.rb +13 -0
  50. data/lib/install/shakapacker.rb +61 -0
  51. data/lib/install/spring.rb +54 -0
  52. data/lib/install/updatable.rb +34 -0
  53. data/lib/install/vite.rb +62 -0
  54. data/lib/install/webpacker.rb +81 -0
  55. data/lib/install/yarn.rb +56 -0
  56. data/lib/tasks/cable_ready/cable_ready.rake +249 -0
  57. data/package.json +61 -0
  58. data/rollup.config.mjs +76 -0
  59. data/web-test-runner.config.mjs +12 -0
  60. data/yarn.lock +4623 -0
  61. metadata +96 -129
  62. data/LATEST +0 -1
  63. data/app/helpers/cable_ready_helper.rb +0 -25
  64. data/lib/generators/cable_ready/helpers_generator.rb +0 -43
  65. data/lib/generators/cable_ready/initializer_generator.rb +0 -14
  66. data/test/dummy/app/channels/application_cable/channel.rb +0 -4
  67. data/test/dummy/app/channels/application_cable/connection.rb +0 -4
  68. data/test/dummy/app/controllers/application_controller.rb +0 -2
  69. data/test/dummy/app/helpers/application_helper.rb +0 -2
  70. data/test/dummy/app/jobs/application_job.rb +0 -7
  71. data/test/dummy/app/mailers/application_mailer.rb +0 -4
  72. data/test/dummy/app/models/application_record.rb +0 -3
  73. data/test/dummy/app/models/global_idable_entity.rb +0 -16
  74. data/test/dummy/app/models/post.rb +0 -4
  75. data/test/dummy/app/models/section.rb +0 -6
  76. data/test/dummy/app/models/team.rb +0 -6
  77. data/test/dummy/app/models/topic.rb +0 -4
  78. data/test/dummy/app/models/user.rb +0 -7
  79. data/test/dummy/config/application.rb +0 -22
  80. data/test/dummy/config/boot.rb +0 -5
  81. data/test/dummy/config/environment.rb +0 -5
  82. data/test/dummy/config/environments/development.rb +0 -76
  83. data/test/dummy/config/environments/production.rb +0 -120
  84. data/test/dummy/config/environments/test.rb +0 -59
  85. data/test/dummy/config/initializers/application_controller_renderer.rb +0 -8
  86. data/test/dummy/config/initializers/assets.rb +0 -12
  87. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -8
  88. data/test/dummy/config/initializers/cable_ready.rb +0 -18
  89. data/test/dummy/config/initializers/content_security_policy.rb +0 -28
  90. data/test/dummy/config/initializers/cookies_serializer.rb +0 -5
  91. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -6
  92. data/test/dummy/config/initializers/inflections.rb +0 -16
  93. data/test/dummy/config/initializers/mime_types.rb +0 -4
  94. data/test/dummy/config/initializers/permissions_policy.rb +0 -11
  95. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  96. data/test/dummy/config/puma.rb +0 -43
  97. data/test/dummy/config/routes.rb +0 -3
  98. data/test/dummy/db/migrate/20210902154139_create_users.rb +0 -9
  99. data/test/dummy/db/migrate/20210902154153_create_posts.rb +0 -10
  100. data/test/dummy/db/migrate/20210904081930_create_topics.rb +0 -9
  101. data/test/dummy/db/migrate/20210904093607_create_sections.rb +0 -9
  102. data/test/dummy/db/migrate/20210913191735_create_teams.rb +0 -8
  103. data/test/dummy/db/migrate/20210913191759_add_team_reference_to_users.rb +0 -5
  104. data/test/dummy/db/schema.rb +0 -49
  105. data/test/dummy/test/models/post_test.rb +0 -7
  106. data/test/dummy/test/models/section_test.rb +0 -7
  107. data/test/dummy/test/models/team_test.rb +0 -7
  108. data/test/dummy/test/models/topic_test.rb +0 -7
  109. data/test/dummy/test/models/user_test.rb +0 -7
  110. data/test/lib/cable_ready/cable_car_test.rb +0 -50
  111. data/test/lib/cable_ready/compoundable_test.rb +0 -26
  112. data/test/lib/cable_ready/helper_test.rb +0 -25
  113. data/test/lib/cable_ready/identifiable_test.rb +0 -69
  114. data/test/lib/cable_ready/operation_builder_test.rb +0 -189
  115. data/test/lib/cable_ready/updatable_test.rb +0 -112
  116. data/test/lib/generators/cable_ready/channel_generator_test.rb +0 -157
  117. data/test/support/generator_test_helpers.rb +0 -28
  118. data/test/test_helper.rb +0 -18
@@ -5,6 +5,7 @@ module CableReady
5
5
  attr_reader :identifier
6
6
 
7
7
  def broadcast(clear: true)
8
+ raise("Action Cable must be enabled to use broadcast") unless defined?(ActionCable)
8
9
  clients_received = ActionCable.server.broadcast identifier, {
9
10
  "cableReady" => true,
10
11
  "operations" => operations_payload,
@@ -15,6 +16,7 @@ module CableReady
15
16
  end
16
17
 
17
18
  def broadcast_to(model, clear: true)
19
+ raise("Action Cable must be enabled to use broadcast_to") unless defined?(ActionCable)
18
20
  clients_received = identifier.broadcast_to model, {
19
21
  "cableReady" => true,
20
22
  "operations" => operations_payload,
@@ -24,13 +26,19 @@ module CableReady
24
26
  clients_received
25
27
  end
26
28
 
27
- def broadcast_later(clear: true)
28
- CableReadyBroadcastJob.perform_later(identifier: identifier, operations: operations_payload)
29
+ def broadcast_later(clear: true, queue: nil)
30
+ raise("Action Cable must be enabled to use broadcast_later") unless defined?(ActionCable)
31
+ CableReadyBroadcastJob
32
+ .set(queue: queue ? queue.to_sym : CableReady.config.broadcast_job_queue)
33
+ .perform_later(identifier: identifier, operations: operations_payload)
29
34
  reset! if clear
30
35
  end
31
36
 
32
- def broadcast_later_to(model, clear: true)
33
- CableReadyBroadcastJob.perform_later(identifier: identifier.name, operations: operations_payload, model: model)
37
+ def broadcast_later_to(model, clear: true, queue: nil)
38
+ raise("Action Cable must be enabled to use broadcast_later_to") unless defined?(ActionCable)
39
+ CableReadyBroadcastJob
40
+ .set(queue: queue ? queue.to_sym : CableReady.config.broadcast_job_queue)
41
+ .perform_later(identifier: identifier.name, operations: operations_payload, model: model)
34
42
  reset! if clear
35
43
  end
36
44
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "thread/local"
4
+
3
5
  module CableReady
4
6
  # This class is a thread local singleton: CableReady::Channels.instance
5
7
  # SEE: https://github.com/socketry/thread-local/tree/master/guides/getting-started
@@ -13,7 +15,7 @@ module CableReady
13
15
 
14
16
  def [](*keys)
15
17
  keys.select!(&:itself)
16
- identifier = keys.many? || (keys.one? && keys.first.respond_to?(:to_global_id)) ? compound(keys) : keys.pop
18
+ identifier = (keys.many? || (keys.one? && keys.first.respond_to?(:to_global_id))) ? compound(keys) : keys.pop
17
19
  @channels[identifier] ||= CableReady::Channel.new(identifier)
18
20
  end
19
21
 
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "monitor"
4
+ require "observer"
5
+ require "singleton"
6
+
3
7
  module CableReady
4
8
  # This class is a process level singleton shared by all threads: CableReady::Config.instance
5
9
  class Config
@@ -7,14 +11,23 @@ module CableReady
7
11
  include Observable
8
12
  include Singleton
9
13
 
10
- attr_accessor :on_failed_sanity_checks, :on_new_version_available
14
+ attr_accessor :on_failed_sanity_checks, :broadcast_job_queue, :precompile_assets
11
15
  attr_writer :verifier_key
12
16
 
17
+ def on_new_version_available
18
+ warn "NOTICE: The `config.on_new_version_available` option has been removed from the CableReady initializer. You can safely remove this option from your initializer."
19
+ end
20
+
21
+ def on_new_version_available=(_)
22
+ warn "NOTICE: The `config.on_new_version_available` option has been removed from the CableReady initializer. You can safely remove this option from your initializer."
23
+ end
24
+
13
25
  def initialize
14
26
  super
15
27
  @operation_names = Set.new(default_operation_names)
16
28
  @on_failed_sanity_checks = :exit
17
- @on_new_version_available = :ignore
29
+ @broadcast_job_queue = :default
30
+ @precompile_assets = true
18
31
  end
19
32
 
20
33
  def observers
@@ -72,6 +85,7 @@ module CableReady
72
85
  set_storage_item
73
86
  set_style
74
87
  set_styles
88
+ set_title
75
89
  set_value
76
90
  text_content
77
91
  ]).freeze
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/engine"
4
+
5
+ module CableReady
6
+ class Engine < Rails::Engine
7
+ # If you don't want to precompile CableReady's assets (eg. because you're using webpack),
8
+ # you can do this in an initializer:
9
+ #
10
+ # config.after_initialize do
11
+ # config.assets.precompile -= CableReady::Engine::PRECOMPILE_ASSETS
12
+ # end
13
+ PRECOMPILE_ASSETS = %w[
14
+ cable_ready.js
15
+ cable_ready.min.js
16
+ cable_ready.min.js.map
17
+ cable_ready.umd.js
18
+ cable_ready.umd.min.js
19
+ cable_ready.umd.min.js.map
20
+ ]
21
+
22
+ initializer "cable_ready.sanity_check" do
23
+ SanityChecker.check! unless Rails.env.production?
24
+ end
25
+
26
+ initializer "cable_ready.renderer" do
27
+ ActiveSupport.on_load(:action_controller) do
28
+ ActionController::Renderers.add :operations do |operations, options|
29
+ response.content_type ||= Mime[:cable_ready]
30
+ render json: operations.dispatch
31
+ end
32
+
33
+ Mime::Type.register "application/vnd.cable-ready.json", :cable_ready
34
+ end
35
+ end
36
+
37
+ initializer "cable_ready.assets" do |app|
38
+ if app.config.respond_to?(:assets) && CableReady.config.precompile_assets
39
+ app.config.assets.precompile += PRECOMPILE_ASSETS
40
+ end
41
+ end
42
+
43
+ initializer "cable_ready.importmap", before: "importmap" do |app|
44
+ if app.config.respond_to?(:importmap)
45
+ app.config.importmap.paths << Engine.root.join("lib/cable_ready/importmap.rb")
46
+ app.config.importmap.cache_sweepers << Engine.root.join("app/assets/javascripts")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "action_view"
4
+
3
5
  module CableReady
4
6
  module Identifiable
5
7
  def dom_id(record, prefix = nil)
@@ -9,9 +11,9 @@ module CableReady
9
11
 
10
12
  id = if record.respond_to?(:to_dom_id)
11
13
  record.to_dom_id
12
- elsif record.is_a?(ActiveRecord::Relation)
14
+ elsif ar_relation?(record)
13
15
  [prefix, record.model_name.plural].compact.join("_")
14
- elsif record.is_a?(ActiveRecord::Base)
16
+ elsif ar_base?(record)
15
17
  ActionView::RecordIdentifier.dom_id(record, prefix)
16
18
  else
17
19
  [prefix, record.to_s.strip].compact.join("_")
@@ -21,10 +23,26 @@ module CableReady
21
23
  end
22
24
 
23
25
  def identifiable?(obj)
24
- obj.respond_to?(:to_dom_selector) ||
26
+ (
27
+ obj.respond_to?(:to_dom_selector) ||
25
28
  obj.respond_to?(:to_dom_id) ||
26
- obj.is_a?(ActiveRecord::Relation) ||
27
- obj.is_a?(ActiveRecord::Base)
29
+ ar_relation?(obj) ||
30
+ ar_base?(obj)
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ def ar_relation?(obj)
37
+ return false if defined?(ActiveRecord).nil? || defined?(ActiveRecord::Relation).nil?
38
+
39
+ obj.is_a?(ActiveRecord::Relation)
40
+ end
41
+
42
+ def ar_base?(obj)
43
+ return false if defined?(ActiveRecord).nil? || defined?(ActiveRecord::Base).nil?
44
+
45
+ obj.is_a?(ActiveRecord::Base)
28
46
  end
29
47
  end
30
48
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ pin "morphdom", to: "https://ga.jspm.io/npm:morphdom@2.6.1/dist/morphdom.js", preload: true
4
+ pin "cable_ready", to: "cable_ready.min.js", preload: true
@@ -0,0 +1,224 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cable_ready/version"
4
+
5
+ ### general utilities
6
+
7
+ def fetch(step_path, file)
8
+ relative_path = step_path + file
9
+ location = template_src + relative_path
10
+
11
+ Pathname.new(location)
12
+ end
13
+
14
+ def complete_step(step)
15
+ create_file "tmp/cable_ready_installer/#{step}", verbose: false
16
+ end
17
+
18
+ def create_or_append(path, *args, &block)
19
+ FileUtils.touch(path)
20
+ append_file(path, *args, &block)
21
+ end
22
+
23
+ def current_template
24
+ ENV["LOCATION"].split("/").last.gsub(".rb", "")
25
+ end
26
+
27
+ def pack_path_missing?
28
+ return false unless pack_path.nil?
29
+ halt "#{friendly_pack_path} is missing. You need a valid application pack file to proceed."
30
+ end
31
+
32
+ def halt(message)
33
+ say "❌ #{message}", :red
34
+ create_file "tmp/cable_ready_installer/halt", verbose: false
35
+ end
36
+
37
+ def backup(path, delete: false)
38
+ if !path.exist?
39
+ yield
40
+ return
41
+ end
42
+
43
+ backup_path = Pathname.new("#{path}.bak")
44
+ old_path = path.relative_path_from(Rails.root).to_s
45
+ filename = path.to_path.split("/").last
46
+
47
+ if backup_path.exist?
48
+ if backup_path.read == path.read
49
+ path.delete if delete
50
+ yield
51
+ return
52
+ end
53
+ backup_path.delete
54
+ end
55
+
56
+ copy_file(path, backup_path, verbose: false)
57
+ path.delete if delete
58
+
59
+ yield
60
+
61
+ if path.read != backup_path.read
62
+ create_or_append(backups_path, "#{old_path}\n", verbose: false)
63
+ end
64
+ say "📦 #{old_path} backed up as #{filename}.bak"
65
+ end
66
+
67
+ def add_gem(name)
68
+ create_or_append(add_gem_list, "#{name}\n", verbose: false)
69
+ say "☑️ Added #{name} to the Gemfile"
70
+ end
71
+
72
+ def remove_gem(name)
73
+ create_or_append(remove_gem_list, "#{name}\n", verbose: false)
74
+ say "❎ Removed #{name} from Gemfile"
75
+ end
76
+
77
+ def add_package(name)
78
+ create_or_append(package_list, "#{name}\n", verbose: false)
79
+ say "☑️ Enqueued #{name} to be added to dependencies"
80
+ end
81
+
82
+ def add_dev_package(name)
83
+ create_or_append(dev_package_list, "#{name}\n", verbose: false)
84
+ say "☑️ Enqueued #{name} to be added to dev dependencies"
85
+ end
86
+
87
+ def drop_package(name)
88
+ create_or_append(drop_package_list, "#{name}\n", verbose: false)
89
+ say "❎ Enqueued #{name} to be removed from dependencies"
90
+ end
91
+
92
+ def gemfile_hash
93
+ Digest::MD5.hexdigest(gemfile_path.read)
94
+ end
95
+
96
+ ### memoized values
97
+
98
+ def cr_npm_version
99
+ @cr_npm_version ||= CableReady::VERSION.gsub(".pre", "-pre")
100
+ end
101
+
102
+ def package_json
103
+ @package_json ||= Rails.root.join("package.json")
104
+ end
105
+
106
+ def entrypoint
107
+ @entrypoint ||= File.read("tmp/cable_ready_installer/entrypoint")
108
+ end
109
+
110
+ def bundler
111
+ @bundler ||= File.read("tmp/cable_ready_installer/bundler")
112
+ end
113
+
114
+ def config_path
115
+ @config_path ||= Rails.root.join(entrypoint, "config")
116
+ end
117
+
118
+ def importmap_path
119
+ @importmap_path ||= Rails.root.join("config/importmap.rb")
120
+ end
121
+
122
+ def friendly_importmap_path
123
+ @friendly_importmap_path ||= importmap_path.relative_path_from(Rails.root).to_s
124
+ end
125
+
126
+ def pack
127
+ @pack ||= pack_path.read
128
+ end
129
+
130
+ def friendly_pack_path
131
+ @friendly_pack_path ||= pack_path.relative_path_from(Rails.root).to_s
132
+ end
133
+
134
+ def pack_path
135
+ @pack_path ||= [
136
+ Rails.root.join(entrypoint, "application.js"),
137
+ Rails.root.join(entrypoint, "packs/application.js"),
138
+ Rails.root.join(entrypoint, "entrypoints/application.js")
139
+ ].find(&:exist?)
140
+ end
141
+
142
+ def package_list
143
+ @package_list ||= Rails.root.join("tmp/cable_ready_installer/npm_package_list")
144
+ end
145
+
146
+ def dev_package_list
147
+ @dev_package_list ||= Rails.root.join("tmp/cable_ready_installer/npm_dev_package_list")
148
+ end
149
+
150
+ def drop_package_list
151
+ @drop_package_list ||= Rails.root.join("tmp/cable_ready_installer/drop_npm_package_list")
152
+ end
153
+
154
+ def template_src
155
+ @template_src ||= File.read("tmp/cable_ready_installer/template_src")
156
+ end
157
+
158
+ def controllers_path
159
+ @controllers_path ||= Rails.root.join(entrypoint, "controllers")
160
+ end
161
+
162
+ def gemfile_path
163
+ @gemfile_path ||= Rails.root.join("Gemfile")
164
+ end
165
+
166
+ def gemfile
167
+ @gemfile ||= gemfile_path.read
168
+ end
169
+
170
+ def prefix
171
+ # standard:disable Style/RedundantStringEscape
172
+ @prefix ||= {
173
+ "vite" => "..\/",
174
+ "webpacker" => "",
175
+ "shakapacker" => "",
176
+ "importmap" => "",
177
+ "esbuild" => ".\/"
178
+ }[bundler]
179
+ # standard:enable Style/RedundantStringEscape
180
+ end
181
+
182
+ def application_record_path
183
+ @application_record_path ||= Rails.root.join("app/models/application_record.rb")
184
+ end
185
+
186
+ def action_cable_initializer_path
187
+ @action_cable_initializer_path ||= Rails.root.join("config/initializers/action_cable.rb")
188
+ end
189
+
190
+ def action_cable_initializer_working_path
191
+ @action_cable_initializer_working_path ||= Rails.root.join(working, "action_cable.rb")
192
+ end
193
+
194
+ def development_path
195
+ @development_path ||= Rails.root.join("config/environments/development.rb")
196
+ end
197
+
198
+ def development_working_path
199
+ @development_working_path ||= Rails.root.join(working, "development.rb")
200
+ end
201
+
202
+ def backups_path
203
+ @backups_path ||= Rails.root.join("tmp/cable_ready_installer/backups")
204
+ end
205
+
206
+ def add_gem_list
207
+ @add_gem_list ||= Rails.root.join("tmp/cable_ready_installer/add_gem_list")
208
+ end
209
+
210
+ def remove_gem_list
211
+ @remove_gem_list ||= Rails.root.join("tmp/cable_ready_installer/remove_gem_list")
212
+ end
213
+
214
+ def options_path
215
+ @options_path ||= Rails.root.join("tmp/cable_ready_installer/options")
216
+ end
217
+
218
+ def options
219
+ @options ||= YAML.safe_load(File.read(options_path))
220
+ end
221
+
222
+ def working
223
+ @working ||= Rails.root.join("tmp/cable_ready_installer/working")
224
+ end
@@ -64,7 +64,7 @@ module CableReady
64
64
  rescue JSON::ParserError
65
65
  {}
66
66
  end
67
- @enqueued_operations.push(operations)
67
+ @enqueued_operations.concat(Array.wrap(operations))
68
68
  self
69
69
  end
70
70
 
@@ -10,8 +10,7 @@ class CableReady::SanityChecker
10
10
  return if called_by_generate_config?
11
11
  return if called_by_rake?
12
12
 
13
- instance = new
14
- instance.check_new_version_available
13
+ new
15
14
  end
16
15
 
17
16
  private
@@ -25,37 +24,8 @@ class CableReady::SanityChecker
25
24
  end
26
25
  end
27
26
 
28
- def check_new_version_available
29
- return if CableReady.config.on_new_version_available == :ignore
30
- return if Rails.env.development? == false
31
- return if using_preview_release?
32
- begin
33
- latest_version = URI.open("https://raw.githubusercontent.com/stimulusreflex/cable_ready/master/LATEST", open_timeout: 1, read_timeout: 1).read.strip
34
- if latest_version != CableReady::VERSION
35
- puts <<~WARN
36
-
37
- 👉 There is a new version of CableReady available!
38
- Current: #{CableReady::VERSION} Latest: #{latest_version}
39
-
40
- If you upgrade, it is very important that you update BOTH Gemfile and package.json
41
- Then, run `bundle install && yarn install` to update to #{latest_version}.
42
-
43
- WARN
44
- exit if CableReady.config.on_new_version_available == :exit
45
- end
46
- rescue
47
- puts "👉 CableReady #{CableReady::VERSION} update check skipped: connection timeout"
48
- end
49
- end
50
-
51
27
  private
52
28
 
53
- def using_preview_release?
54
- preview = CableReady::VERSION.match?(LATEST_VERSION_FORMAT) == false
55
- puts "👉 CableReady #{CableReady::VERSION} update check skipped: pre-release build" if preview
56
- preview
57
- end
58
-
59
29
  def initializer_missing?
60
30
  File.exist?(Rails.root.join("config", "initializers", "cable_ready.rb")) == false
61
31
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CableReady
4
- VERSION = "5.0.0.pre8"
4
+ VERSION = "5.0.0.pre10"
5
5
  end
data/lib/cable_ready.rb CHANGED
@@ -1,44 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails/engine"
4
3
  require "open-uri"
5
- require "active_record"
6
- require "action_view"
7
- require "active_support/all"
8
- require "thread/local"
9
- require "monitor"
10
- require "observer"
11
- require "singleton"
12
- require "cable_ready/version"
4
+ require "active_support/message_verifier"
13
5
  require "cable_ready/identifiable"
14
6
  require "cable_ready/operation_builder"
15
7
  require "cable_ready/config"
16
8
  require "cable_ready/broadcaster"
9
+ require "cable_ready/engine"
17
10
  require "cable_ready/sanity_checker"
18
11
  require "cable_ready/compoundable"
19
12
  require "cable_ready/channel"
20
13
  require "cable_ready/channels"
21
14
  require "cable_ready/cable_car"
22
15
  require "cable_ready/stream_identifier"
16
+ require "cable_ready/version"
17
+ require "cable_ready_helper"
23
18
 
24
19
  module CableReady
25
- class Engine < Rails::Engine
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
36
-
37
- Mime::Type.register "application/vnd.cable-ready.json", :cable_ready
38
- end
39
- end
40
- end
41
-
42
20
  class << self
43
21
  def config
44
22
  CableReady::Config.instance
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: remove me once CableReady 5.0 was released
4
+
5
+ require_relative "../app/helpers/cable_ready/view_helper"
6
+
7
+ module CableReadyHelper
8
+ def self.included(base)
9
+ warn "NOTICE: `CableReadyHelper` was renamed to `CableReady::ViewHelper`. Please update your include accordingly."
10
+
11
+ base.include(::CableReady::ViewHelper)
12
+ end
13
+ end
@@ -7,32 +7,71 @@ class CableReady::ChannelGenerator < Rails::Generators::NamedBase
7
7
  class_option :stream_for, type: :string
8
8
  class_option :stimulus, type: :boolean
9
9
 
10
+ def destroy_not_supported
11
+ if behavior == :revoke
12
+ puts "Sorry, we don't support destroying generated channels.\nDelete the Action Cable channel class, as well as any corresponding JavaScript classes."
13
+ exit
14
+ end
15
+ end
16
+
10
17
  def check_options
11
- raise "Can't specify --stream-from and --stream-for at the same time" if options.key?(:stream_from) && options.key?(:stream_for)
18
+ if options.key?(:stream_from) && options.key?(:stream_for)
19
+ puts "Can't specify --stream-from and --stream-for at the same time"
20
+ exit
21
+ end
12
22
  end
13
23
 
14
24
  def create_channel
15
- generate "channel", file_name
25
+ generate "channel", file_name, "--skip"
16
26
  end
17
27
 
18
28
  def enhance_channels
29
+ @entrypoint = [
30
+ "app/javascript",
31
+ "app/frontend"
32
+ ].find { |path| File.exist?(Rails.root.join(path)) } || "app/javascript"
33
+ puts "Where do JavaScript files live in your app? Our best guess is: \e[1m#{@entrypoint}\e[22m 🤔"
34
+ puts "Press enter to accept this, or type a different path."
35
+ print "> "
36
+ input = Rails.env.test? ? "tmp/app/javascript" : $stdin.gets.chomp
37
+ @entrypoint = input unless input.blank?
38
+ @js_channel = "#{@entrypoint}/channels/#{file_name}_channel.js"
39
+
19
40
  if using_broadcast_to?
20
- gsub_file "app/channels/#{file_name}_channel.rb", /# stream_from.*\n/, "stream_for #{resource}.find(params[:id])\n"
21
- template "app/javascript/controllers/%file_name%_controller.js" if using_stimulus?
22
- else
23
- prepend_to_file "app/javascript/channels/#{file_name}_channel.js", "import CableReady from 'cable_ready'\n"
24
- inject_into_file "app/javascript/channels/#{file_name}_channel.js", after: "// Called when there's incoming data on the websocket for this channel\n" do
25
- <<-JS
26
- if (data.cableReady) CableReady.perform(data.operations)
27
- JS
41
+ if using_stimulus?
42
+ template("#{@entrypoint}/controllers/%file_name%_controller.js")
43
+ Rails.root.join(@js_channel).delete
44
+ else
45
+ gsub_file "app/channels/#{file_name}_channel.rb", /# stream_from.*\n/, "stream_for #{resource}.find(params[:id])\n", verbose: false
46
+ gsub_file @js_channel, /"#{resource}Channel"/, verbose: false do
47
+ <<-JS
48
+
49
+ {
50
+ channel: "#{resource}Channel",
51
+ id: 1
52
+ }
53
+ JS
54
+ end
55
+ doctor_javascript_channel_class
56
+ puts "\nDon't forget to update the id in the channel subscription: #{@js_channel}\nIt's currently set to 1; you'll want to change that to a dynamic value based on something in your DOM."
28
57
  end
29
-
30
- gsub_file "app/channels/#{file_name}_channel.rb", /# stream_from.*\n/, "stream_from \"#{identifier}\"\n"
58
+ else
59
+ gsub_file "app/channels/#{file_name}_channel.rb", /# stream_from.*\n/, "stream_from \"#{identifier}\"\n", verbose: false
60
+ doctor_javascript_channel_class
31
61
  end
32
62
  end
33
63
 
34
64
  private
35
65
 
66
+ def doctor_javascript_channel_class
67
+ prepend_to_file @js_channel, "import CableReady from 'cable_ready'\n", verbose: false
68
+ inject_into_file @js_channel, after: "// Called when there's incoming data on the websocket for this channel\n", verbose: false do
69
+ <<-JS
70
+ if (data.cableReady) CableReady.perform(data.operations)
71
+ JS
72
+ end
73
+ end
74
+
36
75
  def option_given?
37
76
  options.key?(:stream_from) || options.key?(:stream_for)
38
77
  end
@@ -3,16 +3,20 @@
3
3
  CableReady.configure do |config|
4
4
  # Enable/disable exiting / warning when the sanity checks fail options:
5
5
  # `:exit` or `:warn` or `:ignore`
6
-
6
+ #
7
7
  # config.on_failed_sanity_checks = :exit
8
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
9
+ # Enable/disable assets compilation
10
+ # `true` or `false`
11
+ #
12
+ # config.precompile_assets = true
13
13
 
14
14
  # Define your own custom operations
15
15
  # https://cableready.stimulusreflex.com/customization#custom-operations
16
-
16
+ #
17
17
  # config.add_operation_name :jazz_hands
18
+
19
+ # Change the default Active Job queue used for broadcast_later and broadcast_later_to
20
+ #
21
+ # config.broadcast_job_queue = :default
18
22
  end