svelte-on-rails 22.4.4 → 22.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cb9864da582328d603e647cacb755402d42a08241ac60adaf73519d8627f10d
4
- data.tar.gz: b223d557c6a5eb030710926a55b5f9ee5446c2641748b6aca30f9d76f2ebaf5b
3
+ metadata.gz: d9c8ad89cdeda90311d9f2f60e3620d4bd87a8e148f40b6b9226136af7400ce3
4
+ data.tar.gz: cbc53e92bb4e44e97f0cd2076957618ddd8867d974490062d6ba9217930f134c
5
5
  SHA512:
6
- metadata.gz: 95bea92ab87a3c73cbe9cc51637dbc3506110c5af1074fde97b3a794314fdae3b39b76748d973a7d4587294dde211027bdf1ef8955be528424f9818110431c3f
7
- data.tar.gz: 6d21e528178d757eb73184d7f2b00a51123581645503fd5c6636f9e2297d3a3cc8a7364f656d062d36f73387ff045c51d1cabae9adb0154e6a39d30c30a5b0e7
6
+ metadata.gz: ff1bf4f5970164c5d185a3de9ea78506b16b8036dc04a8008ae020b20e6837cea4738f6d42af79aea11b563d048a4ed0c20e6d41abaddd61ff927cc6b72177ed
7
+ data.tar.gz: 13af465c198de0b3e918d30f68f0874f408e4d7b96e89c9467bdf3d193a4136bcc03684af5d2091e7670723529a089faa94c106eb743df49d9eeadcd28d24647
@@ -2,97 +2,64 @@ module SvelteOnRails
2
2
  module BootContext
3
3
  module_function
4
4
 
5
- # We deliberately use a BLACKLIST + program-name check, not a whitelist of
6
- # loaded constants. Reason: `puma` is typically in the app's Gemfile default
7
- # group, so `defined?(::Puma::Launcher)` is truthy even inside `rails console`
8
- # or `rails assets:precompile`.
5
+ # Returns true when we are certain the current process is a Puma web
6
+ # server (or a `rails server` process that will boot Puma). Everywhere
7
+ # else (rake, console, runner, tests, generators, unknown wrappers)
8
+ # returns false. False negatives are safe because the SsrClient has a
9
+ # lazy-start fallback that kicks in on the first render request.
9
10
  def serving_http?
10
- # Explicit overrides for tests / edge cases:
11
- return true if ENV["SVELTE_ON_RAILS_FORCE_SSR"] == "1"
11
+ # 1. Explicit user overrides always win.
12
+ return true if ENV["SVELTE_ON_RAILS_FORCE_SSR"] == "1"
12
13
  return false if ENV["SVELTE_ON_RAILS_DISABLE_SSR"] == "1"
13
14
 
14
- return false if rake_task?
15
- return false if rails_console?
16
- return false if rails_runner?
17
- return false if rails_dbconsole?
18
- return false if rails_generator?
19
- return false if test_runner?
20
-
21
- # Positive signal: `rails server` sets this constant during command dispatch.
22
- return true if defined?(Rails::Server)
23
-
24
- # Positive signal: launched directly via a server binary (bundle exec puma,
25
- # rackup, unicorn, falcon, passenger). $PROGRAM_NAME is set by the launcher
26
- # before it requires the app, so this is reliable.
27
- return true if server_program_name?
28
-
29
- # Default: assume this is NOT an HTTP-serving context. Better to be silent
30
- # than to spawn an unwanted Node process; users can force with the ENV var.
15
+ # 2. Positive signal: `rails server` has been dispatched. This
16
+ # constant is defined by Rails::Command::ServerCommand before the
17
+ # app boots, and is a very reliable indicator.
18
+ return true if defined?(::Rails::Server)
19
+
20
+ # 3. Positive signal: a Puma::Launcher instance is already alive.
21
+ # Puma instantiates its Launcher inside Puma::Runner#run, which
22
+ # runs BEFORE Rails' after_initialize (because Puma requires the
23
+ # Rack app, and requiring the app is what triggers Rails boot).
24
+ # So by the time this method is called from our after_initialize
25
+ # hook, the launcher exists in ObjectSpace iff we are inside Puma.
26
+ return true if puma_launcher_alive?
27
+
28
+ # 4. Positive signal: launched via `puma` / `pumactl` binary directly.
29
+ # Redundant with (3) in most cases, but harmless and useful for
30
+ # exotic launchers that bypass Puma::Runner.
31
+ return true if program_basename == "puma"
32
+
33
+ # Everything else: not an HTTP-serving context (as far as we can tell
34
+ # at boot time). If we're wrong, the lazy fallback will handle it.
31
35
  false
32
36
  end
33
37
 
38
+ # Short human-readable label for the log line when we skip SSR startup.
34
39
  def description
35
- return "rake tasks: #{Rake.application.top_level_tasks.join(', ')}" if rake_task?
36
- return "rails console" if rails_console?
37
- return "rails runner" if rails_runner?
38
- return "rails dbconsole" if rails_dbconsole?
39
- return "rails generator" if rails_generator?
40
- return "test runner (#{test_runner_name})" if test_runner?
41
- return "rails server" if defined?(Rails::Server)
42
- "program=#{File.basename($PROGRAM_NAME)}"
43
- end
44
-
45
- # --- detectors -----------------------------------------------------------
46
-
47
- def rake_task?
48
- defined?(Rake) && Rake.respond_to?(:application) && Rake.application.top_level_tasks.any?
49
- end
50
-
51
- def rails_console?
52
- defined?(Rails::Console) ||
53
- program_basename == "irb" ||
54
- (defined?(IRB) && $PROGRAM_NAME.to_s.include?("irb"))
55
- end
56
-
57
- def rails_runner?
58
- defined?(Rails::Command::RunnerCommand) &&
59
- Rails::Command.const_defined?(:RunnerCommand) &&
60
- current_rails_command?("runner")
40
+ return "rails server" if defined?(::Rails::Server)
41
+ return "puma" if puma_launcher_alive? || program_basename == "puma"
42
+ return "rake: #{Rake.application.top_level_tasks.join(', ')}" if rake_task?
43
+ return "rails console" if defined?(::Rails::Console)
44
+ return "rails runner" if defined?(::Rails::Command::RunnerCommand)
45
+ return "rails dbconsole" if defined?(::Rails::DBConsole)
46
+ "program=#{program_basename}"
61
47
  end
62
48
 
63
- def rails_dbconsole?
64
- defined?(Rails::DBConsole) || current_rails_command?("dbconsole")
65
- end
66
-
67
- def rails_generator?
68
- defined?(Rails::Generators) && current_rails_command?("generate", "destroy", "new")
69
- end
70
-
71
- def test_runner?
72
- !test_runner_name.nil?
73
- end
74
-
75
- def test_runner_name
76
- return "rspec" if $PROGRAM_NAME.to_s.include?("rspec")
77
- return "minitest" if defined?(Minitest) && Minitest.respond_to?(:run) && !defined?(Rails::Server)
78
- return "cucumber" if $PROGRAM_NAME.to_s.include?("cucumber")
79
- nil
49
+ def puma_launcher_alive?
50
+ return false unless defined?(::Puma::Launcher)
51
+ ObjectSpace.each_object(::Puma::Launcher).any?
52
+ rescue
53
+ false
80
54
  end
81
55
 
82
- def server_program_name?
83
- %w[puma rackup unicorn unicorn_rails falcon passenger].include?(program_basename)
56
+ def rake_task?
57
+ defined?(::Rake) && Rake.respond_to?(:application) &&
58
+ Rake.application.top_level_tasks.any?
84
59
  end
85
60
 
86
61
  def program_basename
87
62
  File.basename($PROGRAM_NAME.to_s)
88
63
  end
89
-
90
- # `rails <command>` sets ARGV[0] to the command name before Rails::Command
91
- # dispatches. This is stable across Rails 6/7/8.
92
- def current_rails_command?(*names)
93
- argv0 = (defined?(ARGV) && ARGV.first) || nil
94
- return false unless argv0
95
- names.include?(argv0.to_s)
96
- end
97
64
  end
98
65
  end
@@ -240,7 +240,7 @@ module SvelteOnRails
240
240
  def render_with_ssr_server(caller_loc)
241
241
  return {} unless @conf.configs[:ssr_server]
242
242
 
243
- result = SvelteOnRails::SsrClient.instance.render(
243
+ result = SvelteOnRails::SsrClient.instance(caller: "Request/View-helper").render(
244
244
  component_paths,
245
245
  cached_props,
246
246
  debug?,
@@ -23,7 +23,7 @@ module SvelteOnRails
23
23
  )
24
24
  $stdout.flush
25
25
  elsif SvelteOnRails::Configuration.instance.configs[:ssr]
26
- SvelteOnRails::SsrClient.instance
26
+ SvelteOnRails::SsrClient.instance(caller: 'initializer/booting')
27
27
  end
28
28
 
29
29
  end
@@ -52,8 +52,9 @@ module SvelteOnRails
52
52
  end
53
53
 
54
54
  rake_tasks do
55
- load File.expand_path("../../tasks/svelte_on_rails_tasks.rake", __FILE__)
55
+ load File.expand_path("../../tasks/general_tasks.rake", __FILE__)
56
56
  load File.expand_path("../../tasks/cache_tasks.rake", __FILE__)
57
+ load File.expand_path("../../tasks/ssr_client_tasks.rake", __FILE__)
57
58
  end
58
59
  end
59
60
  end
@@ -10,34 +10,50 @@ module SvelteOnRails
10
10
  :logfile_max_lines,
11
11
  :socket_path,
12
12
  :ssr_server_bin_path,
13
- :node_bin
13
+ :node_bin,
14
+ :initialized_by
14
15
 
15
16
  # methods
16
17
 
17
- def self.instance
18
- @instance ||= new
18
+ def self.instance(caller: nil)
19
+
20
+ @instance ||= new(caller: caller)
21
+ @instance
19
22
  end
20
23
 
21
- def initialize
24
+ def initialize(caller: nil)
25
+
26
+ @initialized_by = caller
27
+
28
+ File.open(SvelteOnRails::Lib::Utils.ssr_server_logfile, 'w') do |f|
29
+ f.sync = true
30
+ f.puts("[#{Time.now.utc.iso8601(3)} ppid:#{Process.ppid} pid:#{Process.pid}] >>> Logfile deleted on initializing SsrClient, called by #{caller} <<<")
31
+ end
22
32
 
23
- SvelteOnRails::Lib::Utils.ssr_server_logfile.delete if SvelteOnRails::Lib::Utils.ssr_server_logfile.exist?
24
33
 
25
- @helpers = SsrServerHelpers.new
34
+ @socket_namespace = [
35
+ "svelte",
36
+ Rails.application.class.module_parent_name[0..30],
37
+ short_env
38
+ ].join("-")
39
+ @socket_path = socket_path_fresh
26
40
 
27
41
  @logfile_path = Rails.root.join("log/svelte-ssr-server-#{Rails.env}.log")
28
42
  @logfile_max_lines = build_logfile_max_lines
29
- @socket_path = @helpers.socket_path
30
43
  @ssr_server = SvelteOnRails::Configuration.instance.configs[:ssr_server]
31
- @ssr_server_bin_path = @helpers.ssr_server_bin_path
44
+ @ssr_server_bin_path = SvelteOnRails::Configuration.instance.ssr_server_bin_path
45
+ @started = Time.now
32
46
 
33
47
  File.delete(restart_marker_file) if File.exist?(restart_marker_file)
34
48
 
49
+ SvelteOnRails::SsrClientControlChannel.install_control_listener
50
+
35
51
  if @ssr_server
36
52
 
37
53
  start_node_server!
38
54
 
39
55
  at_exit do
40
- @helpers.shutdown
56
+ shutdown(caller: 'at_exit')
41
57
  File.delete(restart_marker_file) if File.exist?(restart_marker_file)
42
58
  end
43
59
  else
@@ -169,21 +185,12 @@ module SvelteOnRails
169
185
 
170
186
  SvelteOnRails::Lib::Utils.ssr_server_log("SOR start_node_server! called", ssr_logfile_only: !restart_after_failure)
171
187
 
172
- # notice ppid
173
- FileUtils.mkdir_p(@helpers.ssr_client_ppid_file.dirname)
174
- File.write(@helpers.ssr_client_ppid_file, Process.ppid.to_s)
175
- if @helpers.ssr_client_ppid_file.exist?
176
- SvelteOnRails::Lib::Utils.ssr_server_log("File #{@helpers.ssr_client_ppid_file} written, PPID: #{Process.ppid}", ssr_logfile_only: true)
177
- else
178
- SvelteOnRails::Lib::Utils.ssr_server_log("ERROR: File #{@helpers.ssr_client_ppid_file} could not be written")
179
- end
180
-
181
188
  start = Time.now
182
189
 
183
190
  @node_server_output = {}
184
191
  Thread.new do
185
192
  stdout, stderr, status = Open3.capture3(
186
- @helpers.start_node_server_command(started_by),
193
+ start_node_server_command(started_by),
187
194
  chdir: Rails.root
188
195
  )
189
196
  @node_server_output = {
@@ -215,7 +222,7 @@ module SvelteOnRails
215
222
  end
216
223
  SvelteOnRails::Lib::Utils.ssr_server_log("Server responded successfully")
217
224
 
218
- @helpers.cleanup_leftover_processes
225
+ cleanup_leftover_processes
219
226
  end
220
227
 
221
228
  def restart_my_server(tag = nil)
@@ -234,7 +241,7 @@ module SvelteOnRails
234
241
  Rails.logger.error(msg)
235
242
  SvelteOnRails::Lib::Utils.ssr_server_log("[ERROR] #{msg}")
236
243
 
237
- @helpers.shutdown
244
+ shutdown(caller: 'restart')
238
245
  begin
239
246
  start_node_server!("#{tag.gsub(' ', '-') + '-' if tag}#{count}", restart_after_failure: true)
240
247
  rescue
@@ -253,6 +260,57 @@ module SvelteOnRails
253
260
  nil
254
261
  end
255
262
 
263
+ def uptime
264
+ Time.now - @started
265
+ end
266
+
267
+ def start_node_server_command(started_by = '')
268
+ workers = SvelteOnRails::Configuration.instance.configs[:ssr_server_workers]
269
+ [
270
+ (started_by ? "SVELTE_SSR_SERVER_STARTED_BY=#{started_by}" : nil),
271
+ SvelteOnRails::Configuration.instance.node_bin_path,
272
+ @ssr_server_bin_path,
273
+ socket_path,
274
+ (workers > 1 ? "--workers=#{workers}" : nil)
275
+ ].compact.join(' ')
276
+ end
277
+
278
+ def shutdown(caller: '')
279
+ SsrClient.instance_variable_set(:@instance, nil)
280
+ SvelteOnRails::Lib::Utils.ssr_server_log("Shutting down SSR client, ppid: #{Process.ppid} (#{caller})")
281
+ terminate_node_processes(own_processes, label: "own")
282
+ {
283
+ success: true
284
+ }
285
+ rescue => e
286
+ {
287
+ error: e
288
+ }
289
+ end
290
+
291
+ # NODE PROCESS MANAGEMENT
292
+
293
+ SsrProcess = Struct.new(:pid, :ppid, :socket_path, keyword_init: true)
294
+
295
+ def own_processes
296
+ scan_processes.select { |p| p.ppid == Process.ppid }
297
+ end
298
+
299
+ def leftover_processes
300
+ scan_processes.reject { |p| p.ppid == Process.ppid }
301
+ end
302
+
303
+ def leftover_sockets
304
+ scan_sockets.reject { |s| s[:ppid] == Process.ppid }
305
+ end
306
+
307
+ def cleanup_leftover_processes
308
+ terminate_node_processes(leftover_processes, label: "leftover")
309
+ delete_sockets(leftover_sockets.map { |s| s[:path] }, label: "leftover")
310
+ end
311
+
312
+ # END node process management
313
+
256
314
  private
257
315
 
258
316
  def restart_marker_file
@@ -325,34 +383,8 @@ module SvelteOnRails
325
383
  end
326
384
  end
327
385
 
328
- end
329
-
330
- class SsrServerHelpers
331
-
332
- # theese helpers are used from the :check rake task
333
- # For that reason they are within a separate class
334
-
335
- attr_reader :socket_namespace,
336
- :socket_path,
337
- :ssr_server_bin_path
338
-
339
- def initialize
340
-
341
- @socket_namespace = [
342
- "svelte-ssr",
343
- Rails.application.class.module_parent_name[0..30],
344
- Rails.env,
345
- ].join("-")
346
-
347
- @ssr_server_bin_path = SvelteOnRails::Configuration.instance.ssr_server_bin_path
348
-
349
- end
350
-
351
- def ssr_client_ppid_file
352
- Rails.root.join("tmp", "pids", 'svelte_on_rails.ppid')
353
- end
354
-
355
- def socket_path(ppid: Process.ppid)
386
+ def socket_path_fresh
387
+ ppid = Process.ppid
356
388
  app_sock = Rails.root.join("tmp/sockets/#{@socket_namespace}-#{ppid}.sock")
357
389
  FileUtils.mkdir_p(File.dirname(app_sock))
358
390
 
@@ -368,47 +400,9 @@ module SvelteOnRails
368
400
  fallback
369
401
  end
370
402
 
371
- def start_node_server_command(started_by, ppid: Process.ppid)
372
- workers = SvelteOnRails::Configuration.instance.configs[:ssr_server_workers]
373
- [
374
- (started_by ? "SVELTE_SSR_SERVER_STARTED_BY=#{started_by}" : nil),
375
- SvelteOnRails::Configuration.instance.node_bin_path,
376
- @ssr_server_bin_path,
377
- socket_path(ppid: ppid),
378
- (workers > 1 ? "--workers=#{workers}" : nil)
379
- ].compact.join(' ')
380
- end
381
-
382
- SsrProcess = Struct.new(:pid, :ppid, :socket_path, keyword_init: true)
383
-
384
- def own_processes(current_ppid: Process.ppid)
385
- scan_processes.select { |p| p.ppid == current_ppid }
386
- end
387
-
388
- def leftover_processes(current_ppid: Process.ppid)
389
- scan_processes.reject { |p| p.ppid == current_ppid }
390
- end
391
-
392
- def leftover_sockets(current_ppid: Process.ppid)
393
- scan_sockets.reject { |s| s[:ppid] == current_ppid }
394
- end
395
-
396
- def cleanup_leftover_processes(current_ppid: Process.ppid)
397
- terminate_processes(leftover_processes(current_ppid: current_ppid), label: "leftover")
398
- delete_sockets(leftover_sockets(current_ppid: current_ppid).map { |s| s[:path] }, label: "leftover")
399
- end
400
-
401
- def shutdown(current_ppid: Process.ppid)
402
- terminate_processes(own_processes(current_ppid: current_ppid), label: "own")
403
- ensure
404
- File.delete(ssr_client_ppid_file) if File.exist?(ssr_client_ppid_file)
405
- end
406
-
407
- private
403
+ # NODE PROCESS MANAGEMENT
408
404
 
409
- # Cluster mode: a primary + N workers share one socket path.
410
- # SIGINT the primary first (lowest pid per socket group); survivors get SIGINT too.
411
- def terminate_processes(processes, label:)
405
+ def terminate_node_processes(processes, label:)
412
406
  return if processes.empty?
413
407
 
414
408
  processes.group_by(&:socket_path).values.flat_map { |g| g.sort_by(&:pid) }.each do |p|
@@ -431,7 +425,6 @@ module SvelteOnRails
431
425
  SvelteOnRails::Lib::Utils.ssr_server_log("Deleted #{socket_paths.size} #{label} socket#{'s' if socket_paths.size != 1}")
432
426
  end
433
427
 
434
- # All running SSR processes matching our namespace (any ppid).
435
428
  def scan_processes
436
429
  stdout, = Open3.capture3("ps aux | grep svelte | grep -v grep")
437
430
  regex = %r{(/\S*#{Regexp.escape(@socket_namespace)}-(\d+)\.sock)\b}
@@ -443,8 +436,6 @@ module SvelteOnRails
443
436
  end
444
437
  end
445
438
 
446
- # All socket files on disk matching our namespace (any ppid).
447
- # Looks in both the app's tmp/sockets dir and the macOS/BSD fallback dir.
448
439
  def scan_sockets
449
440
  dirs = [Rails.root.join("tmp/sockets").to_s, "/tmp/svelte"]
450
441
  regex = /#{Regexp.escape(@socket_namespace)}-(\d+)\.sock\z/
@@ -453,6 +444,106 @@ module SvelteOnRails
453
444
  .filter_map { |path| (m = path.match(regex)) && { path: path, ppid: m[1].to_i } }
454
445
  end
455
446
 
447
+ # END node process management
448
+
449
+ def short_env
450
+
451
+ name = Rails.env.to_s
452
+
453
+ short = {
454
+ "development" => "dev",
455
+ "production" => "prod",
456
+ "staging" => "stage",
457
+ }[name]
458
+
459
+ return name unless short
460
+ return name if Rails.root.join("config", "environments", "#{short}.rb").exist?
461
+ short
462
+ end
463
+
464
+ end
465
+
466
+ class SsrClientControlChannel
467
+
468
+ SOCKET_FILENAME = "svelte-ctl.sock"
469
+
470
+ # Full path of the control socket.
471
+ # Sits next to the SSR socket in tmp/sockets, or in the /tmp/svelte
472
+ # fallback directory when Rails.root pushes total length over 104 chars.
473
+ def self.socket_path
474
+ primary = Rails.root.join("tmp", "sockets", SOCKET_FILENAME)
475
+ return primary if primary.to_s.length < 104
476
+
477
+ fallback_dir = Pathname.new('/tmp/svelte')
478
+ FileUtils.mkdir_p(fallback_dir)
479
+ FileUtils.chmod(0777, fallback_dir)
480
+ fallback_dir.join(SOCKET_FILENAME)
481
+ end
482
+
483
+ # enable communication by rake task for admin purposes
484
+ def self.install_control_listener
485
+
486
+ path = socket_path.to_s
487
+ FileUtils.mkdir_p(File.dirname(path))
488
+ File.unlink(path) if File.exist?(path)
489
+
490
+ server = UNIXServer.new(path)
491
+ File.chmod(0600, path)
492
+
493
+ Thread.new do
494
+ loop do
495
+ client = server.accept
496
+ begin
497
+ request = client.gets&.strip.to_sym
498
+ client_instance = SsrClient.instance(caller: 'rake task (manual)')
499
+
500
+ response = case request
501
+ when :status
502
+ {
503
+ env: Rails.env,
504
+ uptime: client_instance.uptime,
505
+ request: request,
506
+ socket_path: client_instance.socket_path,
507
+ initialized_by: client_instance.initialized_by,
508
+ ping: client_instance.ping?,
509
+ start_node_server_command: client_instance.start_node_server_command
510
+ }
511
+ when :stop
512
+ begin
513
+ client_instance.shutdown
514
+ {
515
+ success: true
516
+ }
517
+ rescue => e
518
+ {
519
+ error: "Failed to stop SSR server => #{e}"
520
+ }
521
+ end
522
+ end
523
+
524
+ client.puts(response.to_json)
525
+ rescue => e
526
+ SvelteOnRails::Lib::Utils.ssr_server_log(
527
+ "[control] handler error: #{e.class}: #{e.message}",
528
+ ssr_logfile_only: true
529
+ )
530
+ ensure
531
+ client.close rescue nil
532
+ end
533
+ end
534
+ end
535
+
536
+ at_exit do
537
+ server.close rescue nil
538
+ File.unlink(path) rescue nil
539
+ end
540
+
541
+ SvelteOnRails::Lib::Utils.ssr_server_log(
542
+ "Control listener installed on #{path}",
543
+ ssr_logfile_only: true
544
+ )
545
+
546
+ end
456
547
  end
457
548
 
458
549
  class SsrError < StandardError; end
@@ -0,0 +1,10 @@
1
+ namespace :svelte_on_rails do
2
+ desc "Precompile Svelte components for server side rendering"
3
+ task :precompile do
4
+ SvelteOnRails::Configuration.instance.vite_build
5
+ end
6
+
7
+
8
+
9
+ end
10
+ Rake::Task["assets:precompile"].enhance ["svelte_on_rails:precompile"]
@@ -0,0 +1,103 @@
1
+ namespace :svelte_on_rails do
2
+
3
+ desc "Check svelte-on-rails setup and SSR server status"
4
+ task :check do
5
+
6
+ @line_width = 130
7
+
8
+ # SSR CLIENT STATUS
9
+
10
+ cs = get_from_ssr_client(:status)
11
+ exit(1) unless cs
12
+ client_status = JSON.parse(cs).symbolize_keys
13
+ configs = SvelteOnRails::Configuration.instance
14
+ socket_path = client_status[:socket_path]
15
+
16
+ puts
17
+ puts '=' * @line_width
18
+ puts
19
+ puts "INFO FROM THE SSR CLIENT (Rails-side):"
20
+ puts
21
+ puts " Rails env : #{client_status[:env]}"
22
+ puts " Uptime : #{client_status[:uptime].round(0)}sec"
23
+ puts " Initialized by : #{client_status[:initialized_by]}"
24
+ puts " Socket (Node) : #{socket_path} (#{File.socket?(socket_path) ? 'Present/OK' : 'NOT FOUND!'})"
25
+ puts " Ping to Node : #{client_status[:ping] ? 'SUCCESS' : 'FAILED'}"
26
+ puts ' Node bin : ' + configs.node_bin_path.to_s
27
+ puts ' Node version : ' + configs.node_version_test
28
+ puts ' SSR Server bin : ' + configs.ssr_server_bin_path.to_s
29
+ puts ' NPM package version : ' + configs.npm_package_version_test.to_s
30
+ puts
31
+
32
+ # NODE SERVER STATUS
33
+
34
+ curl_installed = system('which curl > /dev/null 2>&1')
35
+ if !curl_installed
36
+ puts '*' * @line_width
37
+ puts ' ERROR'
38
+ puts ' curl is not installed on this machine.'
39
+ puts ' unable to check node server status.'
40
+ puts '*' * @line_width
41
+ exit(1)
42
+ else
43
+ puts '=' * @line_width
44
+ puts
45
+ puts "SSR SERVER (NODE) STATUS:"
46
+ puts
47
+ curl_cmd = "curl --unix-socket #{socket_path} http://localhost"
48
+ stdout, stderr, status = Open3.capture3(curl_cmd)
49
+ puts stdout
50
+ puts
51
+ end
52
+
53
+ puts '=' * @line_width
54
+ puts
55
+ puts 'ADDITIONAL INFO:'
56
+ puts
57
+ puts 'How was the node bin path determined:'
58
+ configs.instance_variable_get(:@node_bin_path_log).each_with_index do |line, index|
59
+ puts " #{index + 1} #{line}"
60
+ end
61
+ puts
62
+ puts 'Commands:'
63
+ puts " • start node server (node path/to/svelte-ssr-server.js path/to/socket.sock):"
64
+ puts " • #{client_status[:start_node_server_command]}"
65
+ puts
66
+ puts '=' * @line_width
67
+ puts
68
+
69
+ end
70
+
71
+ namespace :ssr_client do
72
+
73
+ desc 'For development: to simulate when a client did not start on deploy (Then, on the first request of a svelte component - if not cached! - it must start)'
74
+ task :stop do
75
+ r = get_from_ssr_client(:stop)
76
+ if r['success']
77
+ puts "SSR client stopped successfully."
78
+ else
79
+ puts "ERROR: #{r}"
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ def get_from_ssr_client(request)
86
+
87
+ raise "invalid request" unless [:status, :stop].include?(request)
88
+
89
+ path = SvelteOnRails::SsrClientControlChannel.socket_path.to_path
90
+ unless File.socket?(path)
91
+ puts "*" * @line_width
92
+ puts "ERROR: Control socket not found at #{path} — is Rails running?"
93
+ puts "*" * @line_width
94
+ return
95
+ end
96
+
97
+ sock = UNIXSocket.new(path)
98
+ sock.puts(request)
99
+ response = sock.gets
100
+ sock.close
101
+ response
102
+ end
103
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svelte-on-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 22.4.4
4
+ version: 22.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Sedlmair
@@ -102,7 +102,8 @@ files:
102
102
  - lib/svelte_on_rails/turbo_stream.rb
103
103
  - lib/svelte_on_rails/view_helpers.rb
104
104
  - lib/tasks/cache_tasks.rake
105
- - lib/tasks/svelte_on_rails_tasks.rake
105
+ - lib/tasks/general_tasks.rake
106
+ - lib/tasks/ssr_client_tasks.rake
106
107
  - templates/config_base/app/frontend/ssr/ssr.js
107
108
  - templates/config_base/config/svelte_on_rails.yml
108
109
  - templates/config_base/tsconfig.json
@@ -1,108 +0,0 @@
1
- namespace :svelte_on_rails do
2
- desc "Precompile Svelte components for server side rendering"
3
- task :precompile do
4
- SvelteOnRails::Configuration.instance.vite_build
5
- end
6
-
7
- desc "check ssr requirements and status"
8
- task :check do
9
-
10
- line_width = 100
11
- configs = SvelteOnRails::Configuration.instance
12
- ppid_file = Rails.root.join("tmp", "pids", 'svelte_on_rails.ppid')
13
- ppid = (ppid_file.exist? ? File.read(ppid_file).chomp : nil)
14
- server_helpers = SvelteOnRails::SsrServerHelpers.new
15
- socket_path = server_helpers.socket_path(ppid: ppid)
16
-
17
- unless File.socket?(socket_path)
18
- puts "*" * 80
19
- puts "ERROR: socket file does not exist or is not a socket: #{socket_path}"
20
- puts "Do you have set RAILS_ENV correctly?"
21
- puts "*" * 80
22
- end
23
-
24
- unless ppid_file.exist?
25
- puts "*" * 80
26
- puts "ERROR: PPID File does not exist: #{ppid_file}"
27
- puts "Is the app running?"
28
- puts "*" * 80
29
- end
30
-
31
- curl_installed = system('which curl > /dev/null 2>&1')
32
- if curl_installed
33
- curl_cmd = "curl --unix-socket #{socket_path} http://localhost"
34
- stdout, stderr, status = Open3.capture3(curl_cmd + '/health')
35
- srv_details = (JSON.parse(stdout) rescue {})
36
- end
37
-
38
- puts
39
- puts '=' * line_width
40
- puts "Svelte on Rails SSR Server Status:"
41
- puts " Rails env: #{Rails.env}"
42
- if srv_details['uptime']
43
- puts " Uptime: #{srv_details['uptime'].round(0)}sec"
44
- else
45
- puts " Status: not running"
46
- end
47
- puts '=' * line_width
48
- puts
49
- puts 'Node'
50
- puts label('Node bin') + configs.node_bin_path.to_s
51
- puts label('Node version') + configs.node_version_test
52
- puts label('SSR Server bin') + configs.ssr_server_bin_path.to_s
53
- puts label('SSR Server version') + configs.npm_package_version_test.to_s
54
- puts
55
- puts 'Rails instance'
56
- puts label('Process.ppid') + ppid.to_s
57
- puts label('Socket') + socket_path.to_s
58
- puts
59
- puts '=' * line_width
60
- puts
61
- puts 'MORE DETAILS:'
62
- puts
63
- puts 'How was the node bin path determined:'
64
- configs.instance_variable_get(:@node_bin_path_log).each do |line|
65
- puts " • #{line}"
66
- puts " • kill #{line}"
67
- end
68
- puts
69
- puts 'Commands:'
70
- puts " • node path/to/svelte-ssr-server.js path/to/socket.sock:"
71
- puts " • #{server_helpers.start_node_server_command(nil)}"
72
- if srv_details['pid']
73
- puts " • #{curl_cmd}"
74
- puts " • kill #{srv_details['pid']}" if srv_details['pid']
75
- end
76
- puts
77
-
78
- puts '=' * line_width
79
- puts
80
- puts 'NODE INSTANCE INFO:'
81
- puts ' (output of the above mentioned curl command)'
82
- puts
83
- puts '-' * line_width
84
- if curl_installed
85
- stdout, stderr, status = Open3.capture3(curl_cmd)
86
- if status.success?
87
- puts stdout
88
- else
89
- puts "curl exited with status #{status.exitstatus}"
90
- puts stderr unless stderr.to_s.strip.empty?
91
- end
92
- else
93
- puts "curl is not installed on this machine, skipping execution."
94
- end
95
- puts
96
- puts '=' * line_width
97
- puts
98
-
99
- end
100
-
101
- def label(msg)
102
- l = msg.length
103
- " #{msg}:"[0..20] + (msg.length > 22 ? ':' : '') + ' ' * (20 - l)
104
- end
105
-
106
- end
107
-
108
- Rake::Task["assets:precompile"].enhance ["svelte_on_rails:precompile"]