cable_ready 5.0.0.pre9 → 5.0.0.pre10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/Gemfile.lock +119 -100
  4. data/README.md +2 -5
  5. data/app/assets/javascripts/cable_ready.js +457 -151
  6. data/app/assets/javascripts/cable_ready.min.js +1 -1
  7. data/app/assets/javascripts/cable_ready.min.js.map +1 -1
  8. data/app/assets/javascripts/cable_ready.umd.js +441 -165
  9. data/app/assets/javascripts/cable_ready.umd.min.js +1 -1
  10. data/app/assets/javascripts/cable_ready.umd.min.js.map +1 -1
  11. data/app/channels/cable_ready/stream.rb +7 -5
  12. data/app/helpers/cable_ready/view_helper.rb +58 -0
  13. data/app/jobs/cable_ready_broadcast_job.rb +9 -8
  14. data/app/models/concerns/cable_ready/updatable/collection_updatable_callbacks.rb +2 -0
  15. data/app/models/concerns/cable_ready/updatable/collections_registry.rb +2 -0
  16. data/app/models/concerns/cable_ready/updatable/model_updatable_callbacks.rb +5 -2
  17. data/app/models/concerns/cable_ready/updatable.rb +67 -19
  18. data/app/models/concerns/extend_has_many.rb +2 -0
  19. data/cable_ready.gemspec +4 -6
  20. data/lib/cable_ready/broadcaster.rb +2 -0
  21. data/lib/cable_ready/cable_car.rb +2 -0
  22. data/lib/cable_ready/channel.rb +12 -4
  23. data/lib/cable_ready/channels.rb +3 -1
  24. data/lib/cable_ready/config.rb +16 -2
  25. data/lib/cable_ready/engine.rb +19 -9
  26. data/lib/cable_ready/identifiable.rb +23 -5
  27. data/lib/cable_ready/importmap.rb +2 -0
  28. data/lib/cable_ready/installer.rb +224 -0
  29. data/lib/cable_ready/operation_builder.rb +1 -1
  30. data/lib/cable_ready/sanity_checker.rb +1 -31
  31. data/lib/cable_ready/version.rb +1 -1
  32. data/lib/cable_ready.rb +3 -8
  33. data/lib/cable_ready_helper.rb +13 -0
  34. data/lib/generators/cable_ready/channel_generator.rb +51 -12
  35. data/lib/generators/cable_ready/templates/config/initializers/cable_ready.rb +10 -6
  36. data/lib/install/action_cable.rb +144 -0
  37. data/lib/install/broadcaster.rb +109 -0
  38. data/lib/install/bundle.rb +54 -0
  39. data/lib/install/compression.rb +51 -0
  40. data/lib/install/config.rb +39 -0
  41. data/lib/install/development.rb +34 -0
  42. data/lib/install/esbuild.rb +101 -0
  43. data/lib/install/importmap.rb +96 -0
  44. data/lib/install/initializers.rb +15 -0
  45. data/lib/install/mrujs.rb +121 -0
  46. data/lib/install/npm_packages.rb +13 -0
  47. data/lib/install/shakapacker.rb +61 -0
  48. data/lib/install/spring.rb +54 -0
  49. data/lib/install/updatable.rb +34 -0
  50. data/lib/install/vite.rb +62 -0
  51. data/lib/install/webpacker.rb +81 -0
  52. data/lib/install/yarn.rb +56 -0
  53. data/lib/tasks/cable_ready/cable_ready.rake +249 -0
  54. data/package.json +28 -18
  55. data/{rollup.config.js → rollup.config.mjs} +9 -8
  56. data/web-test-runner.config.mjs +12 -0
  57. data/yarn.lock +2210 -404
  58. metadata +37 -161
  59. data/LATEST +0 -1
  60. data/app/helpers/cable_ready_helper.rb +0 -26
  61. data/lib/generators/cable_ready/helpers_generator.rb +0 -43
  62. data/lib/generators/cable_ready/initializer_generator.rb +0 -14
  63. data/test/dummy/app/channels/application_cable/channel.rb +0 -4
  64. data/test/dummy/app/channels/application_cable/connection.rb +0 -4
  65. data/test/dummy/app/controllers/application_controller.rb +0 -2
  66. data/test/dummy/app/helpers/application_helper.rb +0 -2
  67. data/test/dummy/app/jobs/application_job.rb +0 -7
  68. data/test/dummy/app/mailers/application_mailer.rb +0 -4
  69. data/test/dummy/app/models/application_record.rb +0 -3
  70. data/test/dummy/app/models/dugong.rb +0 -4
  71. data/test/dummy/app/models/global_idable_entity.rb +0 -16
  72. data/test/dummy/app/models/post.rb +0 -4
  73. data/test/dummy/app/models/section.rb +0 -6
  74. data/test/dummy/app/models/team.rb +0 -6
  75. data/test/dummy/app/models/topic.rb +0 -4
  76. data/test/dummy/app/models/user.rb +0 -7
  77. data/test/dummy/config/application.rb +0 -22
  78. data/test/dummy/config/boot.rb +0 -5
  79. data/test/dummy/config/environment.rb +0 -5
  80. data/test/dummy/config/environments/development.rb +0 -76
  81. data/test/dummy/config/environments/production.rb +0 -120
  82. data/test/dummy/config/environments/test.rb +0 -59
  83. data/test/dummy/config/initializers/application_controller_renderer.rb +0 -8
  84. data/test/dummy/config/initializers/assets.rb +0 -12
  85. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -8
  86. data/test/dummy/config/initializers/cable_ready.rb +0 -18
  87. data/test/dummy/config/initializers/content_security_policy.rb +0 -28
  88. data/test/dummy/config/initializers/cookies_serializer.rb +0 -5
  89. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -6
  90. data/test/dummy/config/initializers/inflections.rb +0 -16
  91. data/test/dummy/config/initializers/mime_types.rb +0 -4
  92. data/test/dummy/config/initializers/permissions_policy.rb +0 -11
  93. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  94. data/test/dummy/config/puma.rb +0 -43
  95. data/test/dummy/config/routes.rb +0 -3
  96. data/test/dummy/db/migrate/20210902154139_create_users.rb +0 -9
  97. data/test/dummy/db/migrate/20210902154153_create_posts.rb +0 -10
  98. data/test/dummy/db/migrate/20210904081930_create_topics.rb +0 -9
  99. data/test/dummy/db/migrate/20210904093607_create_sections.rb +0 -9
  100. data/test/dummy/db/migrate/20210913191735_create_teams.rb +0 -8
  101. data/test/dummy/db/migrate/20210913191759_add_team_reference_to_users.rb +0 -5
  102. data/test/dummy/db/migrate/20220329222959_create_dugongs.rb +0 -8
  103. data/test/dummy/db/migrate/20220329230221_create_active_storage_tables.active_storage.rb +0 -36
  104. data/test/dummy/db/schema.rb +0 -84
  105. data/test/dummy/test/models/dugong_test.rb +0 -7
  106. data/test/dummy/test/models/post_test.rb +0 -7
  107. data/test/dummy/test/models/section_test.rb +0 -7
  108. data/test/dummy/test/models/team_test.rb +0 -7
  109. data/test/dummy/test/models/topic_test.rb +0 -7
  110. data/test/dummy/test/models/user_test.rb +0 -7
  111. data/test/lib/cable_ready/cable_car_test.rb +0 -50
  112. data/test/lib/cable_ready/compoundable_test.rb +0 -26
  113. data/test/lib/cable_ready/helper_test.rb +0 -25
  114. data/test/lib/cable_ready/identifiable_test.rb +0 -69
  115. data/test/lib/cable_ready/operation_builder_test.rb +0 -189
  116. data/test/lib/cable_ready/updatable_test.rb +0 -135
  117. data/test/lib/generators/cable_ready/channel_generator_test.rb +0 -157
  118. data/test/support/generator_test_helpers.rb +0 -28
  119. data/test/test_helper.rb +0 -18
@@ -1,18 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module CableReady
4
6
  module Updatable
5
7
  extend ::ActiveSupport::Concern
6
8
 
7
9
  included do |base|
8
- if base < ActiveRecord::Base
10
+ if defined?(ActiveRecord) && base < ActiveRecord::Base
9
11
  include ExtendHasMany
10
12
 
11
13
  after_commit CollectionUpdatableCallbacks.new(:create), on: :create
12
14
  after_commit CollectionUpdatableCallbacks.new(:update), on: :update
13
15
  after_commit CollectionUpdatableCallbacks.new(:destroy), on: :destroy
14
16
 
15
- def self.enable_updates(*options)
17
+ def self.enable_updates(...)
18
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` class method will be removed from a future version of CableReady 5"
19
+
20
+ enable_cable_ready_updates(...)
21
+ end
22
+
23
+ def self.skip_updates(...)
24
+ warn "DEPRECATED: please use `skip_cable_ready_updates` instead. The `skip_updates` class method will be removed from a future version of CableReady 5"
25
+
26
+ skip_cable_ready_updates(...)
27
+ end
28
+
29
+ def self.enable_cable_ready_updates(*options)
16
30
  options = options.extract_options!
17
31
  options = {
18
32
  on: [:create, :update, :destroy],
@@ -26,7 +40,7 @@ module CableReady
26
40
  after_commit(ModelUpdatableCallbacks.new(:destroy, enabled_operations), {on: :destroy, if: options[:if]})
27
41
  end
28
42
 
29
- def self.skip_updates
43
+ def self.skip_cable_ready_updates
30
44
  skip_updates_classes.push(self)
31
45
  yield
32
46
  ensure
@@ -39,15 +53,47 @@ module CableReady
39
53
 
40
54
  module ClassMethods
41
55
  def has_many(name, scope = nil, **options, &extension)
42
- option = options.delete(:enable_updates)
56
+ option = if options.has_key?(:enable_updates)
57
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` option will be removed from a future version of CableReady 5"
58
+ options.delete(:enable_updates)
59
+ else
60
+ options.delete(:enable_cable_ready_updates)
61
+ end
62
+
63
+ descendants = options.delete(:descendants)
64
+
65
+ broadcast = option.present?
66
+ result = super
67
+ enrich_association_with_updates(name, option, descendants) if broadcast
68
+ result
69
+ end
70
+
71
+ def has_one(name, scope = nil, **options, &extension)
72
+ option = if options.has_key?(:enable_updates)
73
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` option will be removed from a future version of CableReady 5"
74
+ options.delete(:enable_updates)
75
+ else
76
+ options.delete(:enable_cable_ready_updates)
77
+ end
78
+
79
+ descendants = options.delete(:descendants)
80
+
43
81
  broadcast = option.present?
44
82
  result = super
45
- enrich_association_with_updates(name, option) if broadcast
83
+ enrich_association_with_updates(name, option, descendants) if broadcast
46
84
  result
47
85
  end
48
86
 
49
87
  def has_many_attached(name, **options)
50
- option = options.delete(:enable_updates)
88
+ raise("ActiveStorage must be enabled to use has_many_attached") unless defined?(ActiveStorage)
89
+
90
+ option = if options.has_key?(:enable_updates)
91
+ warn "DEPRECATED: please use `enable_cable_ready_updates` instead. The `enable_updates` option will be removed from a future version of CableReady 5"
92
+ options.delete(:enable_updates)
93
+ else
94
+ options.delete(:enable_cable_ready_updates)
95
+ end
96
+
51
97
  broadcast = option.present?
52
98
  result = super
53
99
  enrich_attachments_with_updates(name, option) if broadcast
@@ -63,7 +109,7 @@ module CableReady
63
109
  broadcast_updates(identifier, model.respond_to?(:previous_changes) ? {changed: model.previous_changes.keys} : {})
64
110
  end
65
111
 
66
- def enrich_association_with_updates(name, option)
112
+ def enrich_association_with_updates(name, option, descendants = nil)
67
113
  reflection = reflect_on_association(name)
68
114
 
69
115
  inverse_of = reflection.inverse_of&.name&.to_s
@@ -76,16 +122,17 @@ module CableReady
76
122
 
77
123
  options = build_options(option)
78
124
 
79
- reflection.klass.send(:include, CableReady::Updatable) unless reflection.klass.respond_to?(:cable_ready_collections)
80
-
81
- reflection.klass.cable_ready_collections.register({
82
- klass: self,
83
- foreign_key: reflection.foreign_key,
84
- name: name,
85
- inverse_association: inverse_of,
86
- through_association: through_association,
87
- options: options
88
- })
125
+ [reflection.klass, *descendants&.map(&:to_s)&.map(&:constantize)].each do |klass|
126
+ klass.send(:include, CableReady::Updatable) unless klass.respond_to?(:cable_ready_collections)
127
+ klass.cable_ready_collections.register({
128
+ klass: self,
129
+ foreign_key: reflection.foreign_key,
130
+ name: name,
131
+ inverse_association: inverse_of,
132
+ through_association: through_association,
133
+ options: options
134
+ })
135
+ end
89
136
  end
90
137
 
91
138
  def enrich_attachments_with_updates(name, option)
@@ -111,7 +158,7 @@ module CableReady
111
158
 
112
159
  case option
113
160
  when TrueClass
114
- # proceed!
161
+ # proceed!
115
162
  when FalseClass
116
163
  options[:on] = []
117
164
  when Array
@@ -124,7 +171,7 @@ module CableReady
124
171
  when Proc
125
172
  options[:if] = option
126
173
  else
127
- raise ArgumentError, "Invalid enable_updates option #{option}"
174
+ raise ArgumentError, "Invalid enable_cable_ready_updates option #{option}"
128
175
  end
129
176
 
130
177
  options
@@ -132,6 +179,7 @@ module CableReady
132
179
 
133
180
  def broadcast_updates(model_class, options)
134
181
  return if skip_updates_classes.any? { |klass| klass >= self }
182
+ raise("ActionCable must be enabled to use Updatable") unless defined?(ActionCable)
135
183
  ActionCable.server.broadcast(model_class, options)
136
184
  end
137
185
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module ExtendHasMany
4
6
  extend ::ActiveSupport::Concern
5
7
 
data/cable_ready.gemspec CHANGED
@@ -12,31 +12,29 @@ Gem::Specification.new do |gem|
12
12
  gem.summary = "Out-of-Band Server Triggered DOM Operations"
13
13
 
14
14
  gem.files = Dir[
15
- "lib/**/*.rb",
15
+ "lib/**/*.{rb,rake}",
16
16
  "app/**/*.rb",
17
17
  "app/assets/javascripts/*",
18
18
  "bin/*",
19
19
  "[A-Z]*"
20
20
  ]
21
21
 
22
- gem.test_files = Dir["test/**/*.rb"]
22
+ gem.required_ruby_version = ">= 2.7.0"
23
23
 
24
24
  rails_version = ">= 5.2"
25
- gem.add_dependency "actioncable", rails_version
25
+
26
26
  gem.add_dependency "actionpack", rails_version
27
27
  gem.add_dependency "actionview", rails_version
28
- gem.add_dependency "activerecord", rails_version
29
28
  gem.add_dependency "activesupport", rails_version
30
29
  gem.add_dependency "railties", rails_version
31
-
32
30
  gem.add_dependency "thread-local", ">= 1.1.0"
33
31
 
34
32
  gem.add_development_dependency "magic_frozen_string_literal"
35
33
  gem.add_development_dependency "mocha"
36
34
  gem.add_development_dependency "pry"
37
35
  gem.add_development_dependency "pry-nav"
38
- gem.add_development_dependency "rails", rails_version
39
36
  gem.add_development_dependency "rake"
40
37
  gem.add_development_dependency "sqlite3"
38
+ gem.add_development_dependency "standard", "1.19.1"
41
39
  gem.add_development_dependency "standardrb"
42
40
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/concern"
4
+
3
5
  module CableReady
4
6
  module Broadcaster
5
7
  include Identifiable
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "thread/local"
4
+
3
5
  module CableReady
4
6
  class CableCar < OperationBuilder
5
7
  extend Thread::Local
@@ -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
@@ -1,7 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rails/engine"
2
4
 
3
5
  module CableReady
4
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
+
5
22
  initializer "cable_ready.sanity_check" do
6
23
  SanityChecker.check! unless Rails.env.production?
7
24
  end
@@ -18,15 +35,8 @@ module CableReady
18
35
  end
19
36
 
20
37
  initializer "cable_ready.assets" do |app|
21
- if app.config.respond_to?(:assets)
22
- app.config.assets.precompile += %w[
23
- cable_ready.js
24
- cable_ready.min.js
25
- cable_ready.min.js.map
26
- cable_ready.umd.js
27
- cable_ready.umd.min.js
28
- cable_ready.umd.min.js.map
29
- ]
38
+ if app.config.respond_to?(:assets) && CableReady.config.precompile_assets
39
+ app.config.assets.precompile += PRECOMPILE_ASSETS
30
40
  end
31
41
  end
32
42
 
@@ -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
@@ -1,2 +1,4 @@
1
+ # frozen_string_literal: true
2
+
1
3
  pin "morphdom", to: "https://ga.jspm.io/npm:morphdom@2.6.1/dist/morphdom.js", preload: true
2
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